Вопрос


We have a GridView with a bunch of items in it, so much so that the user needs to scroll down to see them all. Each item in the GridView is composed by a Textview and a Webview with some events attached to them.
Problem: OnItemLongClickListener is not fired for items that are not visible when the Activity is first created (the ones you need to scroll down to see).

Relevant code:

Activity --

public class MyCoursesActivity extends ActivityBase implements ILoginListener, IUpdateListener, OnDragListener {

private ArrayList<Course> myCoursesList = new ArrayList<Course>();
private int draggedIndex = -1;
CoursesListAdapter coursesAdapter = new CoursesListAdapter(MyCoursesActivity.this, myCoursesList);

MyCourseAdapter mca = new MyCourseAdapter();

private void Load() throws ParseException
{
    myCoursesList = mca.Load();

    coursesAdapter = new CoursesListAdapter(MyCoursesActivity.this, myCoursesList);
    final GridView gv = (GridView) findViewById(R.id.mycourses_Grid);
    gv.setAdapter(coursesAdapter);

    gv.setOnItemLongClickListener(new OnItemLongClickListener() {

        public boolean onItemLongClick(AdapterView gridView, View view,
                int position, long row) {
            view = gridView.getChildAt(position);
            ClipData.Item item = new ClipData.Item("");
            ClipData clipData = new ClipData("",
                    new String[] { ClipDescription.MIMETYPE_TEXT_PLAIN }, item);

            view.startDrag(clipData, new View.DragShadowBuilder(view), null, 0);
            View trashCan = findViewById(R.id.trash_can);
            trashCan.setVisibility(View.VISIBLE);
            trashCan.setOnDragListener(MyCoursesActivity.this);

            draggedIndex = position;
            return true;
        }
    });             
}   


public boolean onDrag(View view, DragEvent dragEvent) {
    switch (dragEvent.getAction()) {
    case DragEvent.ACTION_DRAG_STARTED:
        if (view.getId() == R.id.trash_can) {
            view.animate().scaleX(1.0f);
            view.animate().scaleY(1.0f);
            return true;
        } else
        if (dragEvent.getClipDescription().hasMimeType(
                ClipDescription.MIMETYPE_TEXT_PLAIN)) {
            return true;

        } else {
            return false;
        }
    case DragEvent.ACTION_DRAG_ENTERED:
        if (view.getId() == R.id.trash_can) {
            view.animate().scaleX(1.5f);
            view.animate().scaleY(1.5f);
        }
        return true;
    case DragEvent.ACTION_DRAG_EXITED:
        if (view.getId() == R.id.trash_can) {
            view.animate().scaleX(1.0f);
            view.animate().scaleY(1.0f);
        }
        view.invalidate();
        return true;
    case DragEvent.ACTION_DRAG_LOCATION:
        return true;
    case DragEvent.ACTION_DROP:
        if (view.getId() == R.id.trash_can) {
                        //do stuff
        }
        coursesAdapter.notifyDataSetChanged();          
    case DragEvent.ACTION_DRAG_ENDED:
        // Hide the trash can
        new Handler().postDelayed(new Runnable() {

            @Override
            public void run() {
                findViewById(R.id.trash_can).setVisibility(View.INVISIBLE);
            }
        }, 1000l);
        if (view.getId() == R.id.trash_can) {
            view.animate().scaleX(1.0f);
            view.animate().scaleY(1.0f);
        } else {
            view.setVisibility(View.VISIBLE);
        }
        // remove drag listeners
        view.setOnDragListener(null);
        return true;

    }
    return false;
}

 }

GridView Adapter --

public class CoursesListAdapter extends BaseAdapter {

private Context context;
private ArrayList<Course> courses;

public CoursesListAdapter(Context context, ArrayList<Course> courses){
    this.context = context;
    this.courses = courses;
}

<@Override getCount etc.>

@Override
public View getView(int position, View convertView, ViewGroup parentView) {
    final Course course = (Course) getItem(position);

    LayoutInflater inflater = LayoutInflater.from(context);
    convertView = inflater.inflate(R.layout.course_view, parentView, false);


    if(context instanceof OnDragListener){
        convertView.setTag(course);
        convertView.setOnDragListener((OnDragListener) context);
    }

    TextView title = (TextView) convertView.findViewById(R.id.courseview_titleTv);
    title.setText(course.getTitle());

    WebView wv = (WebView) convertView.findViewById(R.id.courseview_imageWv);

    wv.setOnTouchListener(new OnTouchListener(){

        @Override
        public boolean onTouch(View arg0, MotionEvent event) {
            if(event.getAction() == MotionEvent.ACTION_UP){
                Intent myIntent = new Intent(context, CourseDetailsActivity.class);
                myIntent.putExtra("Course", course);
                context.startActivity(myIntent);
                return true;
            }
            return false;
        }

    });

    convertView.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            Intent myIntent = new Intent(context, CourseDetailsActivity.class);
            myIntent.putExtra("Course", course);
            context.startActivity(myIntent);    
        }
    });

    return convertView;
}

 }

Any idea? Thank you.

EDIT: Tried to put ImageViews instead of WebViews and there doesn't seem to be a problem with events anymore. We tried with a fixed drawable. We're trying to get the actual content of webview to be displayed in the ImageView on project of its own to ease troubleshooting. Here's the code so far. The ImageView doesn't display any image (e.g. google doodle)

WebView to ImageView --

    final WebView mWeb = (WebView) findViewById(R.id.webView1);
    //final WebView mWeb = new WebView(this);
    final ImageView imgView = (ImageView) findViewById(R.id.imageView1);

    mWeb.setInitialScale(100);

     mWeb.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView v, String url){
     Picture picture = mWeb.capturePicture();

    Bitmap bitmap = Bitmap.createBitmap(picture.getWidth(), picture.getHeight(),   Bitmap.Config.ARGB_8888);
    final Canvas c =new Canvas(bitmap);
    picture.draw(c);

    imgView.setMinimumWidth(bitmap.getWidth());
    imgView.setMinimumHeight(bitmap.getHeight());
    imgView.setImageBitmap(bitmap);
    imgView.setVisibility(View.VISIBLE);

}
});

mWeb.loadUrl("http://www.google.com");
Это было полезно?

Решение

This is how I did it, it is working for me:

package com.test.progress;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Picture;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ImageView;

public class MainActivity extends FragmentActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final WebView mWeb = (WebView) findViewById(R.id.webView1);
    // final WebView mWeb = new WebView(this);
    final ImageView imgView = (ImageView) findViewById(R.id.imageView1);

    mWeb.setInitialScale(100);

    mWeb.setWebViewClient(new WebViewClient() {
        public void onPageFinished(WebView v, String url) {
            v.postDelayed(new Runnable() {

                @Override
                public void run() {
                    Picture picture = mWeb.capturePicture();

                    Bitmap bitmap = Bitmap.createBitmap(picture.getWidth(),
                            picture.getHeight(), Bitmap.Config.ARGB_8888);
                    final Canvas c = new Canvas(bitmap);
                    picture.draw(c);

                    imgView.setMinimumWidth(bitmap.getWidth());
                    imgView.setMinimumHeight(bitmap.getHeight());
                    imgView.setImageBitmap(bitmap);
                    imgView.setVisibility(View.VISIBLE);
                }
            }, 100);
        }
    });

    mWeb.loadUrl("http://www.google.com");
}
}

xml layout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/frage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<WebView
    android:id="@+id/webView1"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1" />

<ImageView
    android:id="@+id/imageView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_launcher" />

</LinearLayout>

Don't forget to add:

<uses-permission android:name="android.permission.INTERNET" />

UPDATE 1:

It seems WebView must be visible to user to capture picture, here is a silly solution that is working perfectly.

NOTE: Never store bitmaps in memory like I am doing in the following sample. There are very good libraries available for caching purpose, use them.

package com.vj.test;

import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Picture;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends Activity {
ArrayAdapter<Data> mAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    GridView gv = (GridView) findViewById(R.id.gridView1);
    final List<Data> data = new ArrayList<Data>();
    try {
        data.add(new Data(new URI("http://www.google.com")));
        data.add(new Data(new URI("http://www.yahoo.com")));
        data.add(new Data(new URI("http://www.facebook.com")));
        data.add(new Data(new URI("http://www.google.com")));
        data.add(new Data(new URI("http://www.google.com")));
        data.add(new Data(new URI("http://www.google.com")));
    } catch (Exception e) {
    }
    mAdapter = new ArrayAdapter<Data>(this, R.layout.cell, R.id.url, data) {
        private Map<URI, Boolean> loadingUrls = new HashMap<URI, Boolean>();
        private boolean loadingStarted = false;

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = LayoutInflater.from(MainActivity.this)
                        .inflate(R.layout.cell, null);
            }
            Data d = getItem(position);
            ImageView imageView = (ImageView) convertView
                    .findViewById(R.id.bitmap);
            if (d.bm == null) {
                convertView.findViewById(R.id.progress).setVisibility(
                        View.VISIBLE);
                imageView.setImageBitmap(null);
                loadBitmap(d);
            } else {
                imageView.setImageBitmap(d.bm);
                convertView.findViewById(R.id.progress).setVisibility(
                        View.GONE);

            }
            TextView tv = (TextView) convertView.findViewById(R.id.url);
            tv.setText(d.url.getHost() + "");
            return convertView;
        }

        private void loadBitmap(final Data d) {
            synchronized (loadingUrls) {
                if (loadingUrls.containsKey(d.url)) {
                    return;
                }
                loadingUrls.put(d.url, false);
            }

            if (loadingStarted) {
                return;
            }
            loadingStarted = true;
            final WebView mWeb = (WebView) findViewById(R.id.laodingWebView);
            mWeb.setDrawingCacheEnabled(true);
            mWeb.setInitialScale(100);
            mWeb.setWebViewClient(new WebViewClient() {
                public void onPageFinished(WebView v, final String url) {
                    v.postDelayed(new Runnable() {

                        @Override
                        public void run() {
                            Picture picture = mWeb.capturePicture();
                            Bitmap bitmap = Bitmap.createBitmap(100, 100,
                                    Bitmap.Config.ARGB_8888);
                            final Canvas c = new Canvas(bitmap);
                            picture.draw(c);
                            URI nextUrl = null;
                            // d.bm = bitmap;
                            synchronized (loadingUrls) {
                                loadingUrls.put((URI) mWeb.getTag(), true);
                            }
                            updateAllSimilar((URI) mWeb.getTag(), bitmap);
                            mAdapter.notifyDataSetChanged();
                            for (Entry<URI, Boolean> s : loadingUrls
                                    .entrySet()) {
                                if (!s.getValue()) {
                                    nextUrl = s.getKey();break;
                                }
                            }

                            if (nextUrl != null) {
                                loadNext(mWeb, nextUrl);
                            } else {
                                mWeb.setVisibility(View.GONE);
                            }
                        }
                    }, 50);
                }
            });
            URI url = null;
            for (Entry<URI, Boolean> s : loadingUrls.entrySet()) {
                if (!s.getValue()) {
                    url = s.getKey();break;
                }
            }
            if (url != null) {
                loadNext(mWeb, url);
            }
        }

        private void updateAllSimilar(URI url, Bitmap bm) {
            synchronized (data) {
                for (Data d : data) {
                    if (d.url.equals(url)) {
                        d.bm = bm;
                    }
                }
            }
        }

        private void loadNext(WebView mWeb, URI url) {
            mWeb.loadUrl(url.toString());
            mWeb.setTag(url);
        }
    };
    gv.setAdapter(mAdapter);
}

static class Data {
    Bitmap bm;// don't ever do this, Use cache libraries instead
    URI url;

    public Data(URI uri) {
        this.url = uri;
    }
}
}

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >

<GridView
    android:id="@+id/gridView1"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1"
    android:numColumns="2" >
</GridView>

<WebView
    android:id="@+id/laodingWebView"
    android:layout_width="match_parent"
    android:layout_height="1px" />

</LinearLayout>

cell.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/bitmap"
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:scaleType="fitCenter" />

    <TextView
        android:id="@+id/url"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:maxLines="1"
        android:singleLine="true" />
</LinearLayout>

<ProgressBar
    android:id="@+id/progress"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

</FrameLayout>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top