Qadir Hussain
Qadir Hussain

Reputation: 8856

webview inside the listview: Touch events conflicts Hence unable to pinch Zoom IN/OUT in android

I have a custom listview which is filled with webview. I want to use the pinch zoom in/Zoom out for my webview. But i m not getting the pinch zoom in/out flexibly when i m pinching the webview it is triggering the listview's scrolling up and down.

how can I handle the scroll UP/DOWN event for the listview and pinch for webview simultaneously .

here is my listview_layout.xml

<RelativeLayout 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" >

ListView
    android:id="@+id/listReader"
    android:layout_width="match_parent"
    android:layout_height="fill_parent"
    android:layout_below="@+id/readerHeader"
    android:divider="@android:color/background_dark"
    android:dividerHeight="5dp" >
</ListView>

here is my webview_layour.xml

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

<WebView
    android:id="@+id/webView1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:clickable="true"
    android:focusable="false"
    android:focusableInTouchMode="false"
    android:scrollbars="none" />
</RelativeLayout>

and here is my java file

public class WebViewBookReader extends Activity {
static final String URL = "http://www.XXXXXXXX.com/requesthandler.ashx";
static final String KEY_ITEM_LOGIN = "Result"; // parent node
static final String KEY_STATUS = "Status";
static final String KEY_CUSTOMERID = "CustomerID";
static final String KEY_FNAME = "FirstName";

ArrayList<String> URLs = null;
Activity act = this;
LayoutInflater inflater = null;
Context context = WebViewBookReader.this;

InputMethodManager imm;
SharedPreferences presForLastLogin;
ImageAdapter adapter;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.book_reader_layout);

    imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    getInfo = getIntent();

    URLs = new ArrayList<String>();
    listView = (ListView) findViewById(R.id.listReader);

    cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);



@Override
protected void onStart() {

    super.onStart();


    if (cm.getActiveNetworkInfo() != null
            && cm.getActiveNetworkInfo().isAvailable()
            && cm.getActiveNetworkInfo().isConnected()) {

        new LoadBookPages().execute("");
    } else {
        Toast.makeText(
                context,
                "Connectivity Error..!\nNo any active Internet Connection Found.",
                Toast.LENGTH_LONG).show();
    }

}

public class ImageAdapter extends BaseAdapter {

    public ImageAdapter(Context c) {
        context = c;
    }

    // ---returns the number of images---
    public int getCount() {
        return URLs.size();

    }

    public ImageAdapter(Context ctx, Activity act) {
        inflater = (LayoutInflater) act
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    // ---returns the ID of an item---
    public Object getItem(int position) {
        return position;
    }

    public long getItemId(int position) {
        return position;
    }

    // ---returns an ImageView view---
    public View getView(final int position, View convertView,
            ViewGroup parent) {

        // ImageView bmImage;

        View vi = convertView;
        if (convertView == null) {
            vi = inflater.inflate(R.layout.book_reader_list_style, parent,
                    false);
            holder = new ViewHolder();

            holder.webView = (WebView) vi.findViewById(R.id.webView1);

            // holder.webView.setInitialScale(scaleWebView);
            WebSettings webSettings = holder.webView.getSettings();
            holder.webView.setVerticalScrollBarEnabled(false);
            holder.webView.setHorizontalScrollBarEnabled(false);
            holder.webView.setVisibility(View.VISIBLE);
            webSettings.setLoadWithOverviewMode(true);
            webSettings.setUseWideViewPort(false);

            webSettings.setBuiltInZoomControls(true);
            webSettings.setSupportZoom(true);
            webSettings.setLoadWithOverviewMode(true);

            holder.webView.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    Log.i("Webview", "Clicked");

                }
            });

            vi.setTag(holder);
        } else {

            holder = (ViewHolder) vi.getTag();
        }

        holder.webView
                .loadDataWithBaseURL(
                        null,
                        "<!DOCTYPE html><html><body style = \"text-align:center\"><img style=\"border-style:dotted;border-width:5px;border-color:black;\" src= "
                                + URLs.get(position)
                                + " alt=\"page Not Found\"></body></html>",
                        "text/html", "UTF-8", null);

        return vi;

    }
}

class ViewHolder {
    WebView webView;
    ImageButton btnZoomIn;
    ImageButton btnZoomOut;

}

class LoadBookPages extends AsyncTask<String, Integer, String> {
    ImageAdapter adapter = new ImageAdapter(context, act);
    ProgressDialog progressDialog;

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        progressDialog = ProgressDialog.show(context, "Loading Book...",
                "Please Wait...");
    }

    @Override
    protected String doInBackground(String... params) {

        for (int i = 1; i <= bookPageCount; i++) {
            URLs.add(bookLink + i + ".jpg");
            publishProgress(i);

        }

        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {

        super.onProgressUpdate(values);

        progressDialog.setMessage(values[0]
                + " Page(s) Loaded \nPlease wait...");

    }

    @Override
    protected void onPostExecute(String result) {

        super.onPostExecute(result);
        Toast.makeText(context, "Page No. " + pageNo, Toast.LENGTH_SHORT)
                .show();
        listView.setAdapter(adapter);
        listView.requestFocus();
        progressDialog.dismiss();
        listView.setSelection(pageNo - 1);
    }

}

private class UIThread_BookMark extends AsyncTask<String, Integer, String> {

    ProgressDialog progressDialog;

    @Override
    protected void onPreExecute() {
        super.onPreExecute();

        progressDialog = ProgressDialog.show(context, "BookMarking...",
                "Please Wait...");
    }

    @Override
    protected String doInBackground(String... params) {

        String URL = params[0];

        XMLParser parser = new XMLParser();

        String XMLString = parser.getXmlFromUrl_BookMark(URL,
                Home.CustomerID, Integer.valueOf(bookID), pageNo);
        Document doc = parser.getDomElement(XMLString);
        NodeList nl = doc.getElementsByTagName(KEY_ITEM_LOGIN);
        Element e = (Element) nl.item(0);

        loginStatus = parser.getValue(e, KEY_STATUS);

        if (loginStatus.equals("OK")) {

            publishProgress(1);

        } else {

            publishProgress(0);
        }
        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        if (values[0] == 1) {

            Toast.makeText(context, "BookMark Successful",
                    Toast.LENGTH_SHORT).show();

            if (getInfo.getStringExtra("CHECK_FOR_NOWREADING")
                    .equals("YES")) {
                NowReading.pageNoReadingNow.set(
                        getInfo.getIntExtra("BOOK_NO_INLIST", pageNo),
                        pageNo + "");
                Toast.makeText(context, "BookMark Updated",
                        Toast.LENGTH_SHORT).show();
                BookOverView.updatePageFlag = true;
                BookOverView.tempPageNo = pageNo + "";
            } else {
                NowReading.BookTitle = null;
                NowReading.BookRating = null;
                NowReading.BookDescription = null;
                NowReading.BookCoverPhotos = null;
                NowReading.BookAuther = null;
                NowReading.BookPublishDate = null;
                NowReading.BookCode = null;
                NowReading.BookID = null;
                NowReading.BookPageCount = null;
                NowReading.bitmapArray = null;
                NowReading.pageNoReadingNow = null;
                BookOverView.updatePageFlag = false;
            }

        } else if (values[0] == 0) {
            Toast.makeText(context, "Already BookMarked.",
                    Toast.LENGTH_LONG).show();
        }
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        progressDialog.dismiss();
    }
}
}

Upvotes: 5

Views: 5289

Answers (3)

George Vortelinos
George Vortelinos

Reputation: 41

I found a solution by creating a custom WebView class

CustomWebView catches touch events that are related with MORE than ONE finger on screen. So user can swipe next item in listview with only one finger.

According the case webView tells its parent view to intercept touch events

@SuppressLint("ClickableViewAccessibility")
class CustomWebView : WebView {
    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

    init {
        setOnTouchListener { _, event ->
            if (event.action != MotionEvent.INVALID_POINTER_ID &&

                //is for extra fingers that enter the screen beyond the first
                event.action == MotionEvent.ACTION_POINTER_DOWN ||

                //is sent when a finger leaves the screen but at least one finger is still touching it.
                event.action == MotionEvent.ACTION_POINTER_UP ||

                //The number of pointers of data contained in this event.
                event.pointerCount >= 2
            ) {
                //the child does not want the parent to intercept touch events.
                parent.requestDisallowInterceptTouchEvent(true)
            }

            // return always false
            // because the listener has not consumed the event
            false
        }
    }
}

Upvotes: 0

Rohit
Rohit

Reputation: 490

I have done this thing with 2 scroll views. May be it can help you a bit. here is my code:

ScrollView s_parent= (ScrollView) detailView.findViewById(R.id.parent_scroll);
ScrollView s_child=(ScrollView)detailView.findViewById(R.id.child_scroll);
s_child.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub
        //Log.v("scrooll_touch","CHILD TOUCH");
        // Disallow the touch request for parent scroll on touch of child view
        v.getParent().requestDisallowInterceptTouchEvent(true);
        return false;
    }
});
s_parent.setOnTouchListener(new View.OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) {
        // Log.v("scrooll_touch","PARENT TOUCH");
        findViewById(R.id.child_scroll).getParent().requestDisallowInterceptTouchEvent(false);
        return false;
    }
});

Upvotes: 0

Pratik
Pratik

Reputation: 30855

you need to implement setOnTouchListener listener on webView and write this statement inside onTouch()

webView.setOnTouchListener(new View.OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {                     

        if(event.getAction()==MotionEvent.ACTION_UP){
            webView.getParent().requestDisallowInterceptTouchEvent(false);

        }else                                   
            webView.getParent().requestDisallowInterceptTouchEvent(true);

        return false;
    }

});

for more detail

http://developer.android.com/reference/android/view/ViewParent.html#requestDisallowInterceptTouchEvent%28boolean%29

Edited

Detecting pinch in Android

How to detect the pinch-zoom event with OnGestureListener in Android?

http://www.krvarma.com/2010/10/multi-touch-in-android/

http://code.almeros.com/android-multitouch-gesture-detectors#.UP4qp4Zu_ox

Upvotes: 9

Related Questions