How to make a Scroll Listener for WebView in Andro

2020-01-23 06:53发布

How to implement the Scroll Listener for WebView in Android

i tried this but its not calling my Log.i on scrolling the webview.

package com.example.webview.full.width;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.webkit.WebView;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;

public class scorllableWebview extends WebView implements OnScrollListener {


Context ctx;
AttributeSet atrs;

public scorllableWebview(Context context) {
    super(context);

    ctx = context;
}

public scorllableWebview(Context context, AttributeSet atters){
    super(context, atters);

    ctx = context;
    atrs = atters;
}

@Override
public void onScroll(AbsListView view, int firstVisibleItem,
        int visibleItemCount, int totalItemCount) {

    Log.i("onScroll", "Called");
}

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {


    Log.i("onScrollStateChanged", "Called");

}
}

Here is my MainActivity.java

package com.example.webview.full.width;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.view.Menu;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

public class MainActivity extends Activity {

ProgressDialog progressDialog;
scorllableWebview wv;

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

    wv = (scorllableWebview) findViewById(R.id.scorllableWebview);

    wv.getSettings().setJavaScriptEnabled(true);

    wv.getSettings().setBuiltInZoomControls(true);
    wv.getSettings().supportZoom();

    progressDialog = ProgressDialog.show(MainActivity.this,
            "Loading Book...!", "Please Wait");
    progressDialog.setCancelable(true);

    String htnlString = "<!DOCTYPE html><html><body style = \"text-align:center\"><script type=\"text/javascript\">for(a=1;a<=10;a++)document.write('<img style=\"border-style:dotted;border-width:10px;border-color:black;\"src=\"http://myURL.com/books_snaps/EN567/'+a+'.jpg\" alt=\"Page Not Found\"/>');</script></body></html>";
    // width=\"100%\"
    wv.setWebViewClient(new WebViewClient() {

        @Override
        public void onPageFinished(WebView view, String url) {
            progressDialog.dismiss();
            Toast.makeText(MainActivity.this, "Completed",
                    Toast.LENGTH_SHORT).show();
            wv.pageUp(true);
            super.onPageFinished(view, url);
        }

    });

    wv.loadDataWithBaseURL(null, htnlString, "text/html", "UTF-8", null);

}
   }

and here is my XML file.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<com.example.webview.full.width.scorllableWebview
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/scorllableWebview"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

</RelativeLayout>

5条回答
Explosion°爆炸
2楼-- · 2020-01-23 07:28

Since API 23, you won't need to do it anymore, you can just use the new OnScrollChangeListener available on all views, including on the WebView. But as you still need to support older versions, you can still use the suggestion from @Chris.Jenkins. I made some adjustments the proposed class to be 'more compatible' with the new OnScrollChangeListener interface:

public class ObservableWebView extends WebView {
private OnScrollChangeListener onScrollChangeListener;

public ObservableWebView(Context context) {
    super(context);
}

public ObservableWebView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public ObservableWebView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
    super.onScrollChanged(l, t, oldl, oldt);
    if (onScrollChangeListener != null) {
        onScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
    }
}

public void setOnScrollChangeListener(OnScrollChangeListener onScrollChangeListener) {
    this.onScrollChangeListener = onScrollChangeListener;
}

public OnScrollChangeListener getOnScrollChangeListener() {
    return onScrollChangeListener;
}

public interface OnScrollChangeListener {
    /**
     * Called when the scroll position of a view changes.
     *
     * @param v          The view whose scroll position has changed.
     * @param scrollX    Current horizontal scroll origin.
     * @param scrollY    Current vertical scroll origin.
     * @param oldScrollX Previous horizontal scroll origin.
     * @param oldScrollY Previous vertical scroll origin.
     */
    void onScrollChange(WebView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
}
}
查看更多
女痞
3楼-- · 2020-01-23 07:29

There is no need to extend WebView. What about:

webView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
    @Override
    public void onScrollChanged() {
        Log.v(TAG, "+++ scrollchanged "+webView.getScrollY());
    }
});
查看更多
Summer. ? 凉城
4楼-- · 2020-01-23 07:31

Here is more elegant Kotlin version of accepted answer


class ObservableWebView @JvmOverloads constructor(
        context: Context,
        attrs: AttributeSet? = null,
        defStyleAttr: Int = 0
) : WebView(context, attrs, defStyleAttr) {
    var scrollListener: WebViewScrollListener? = null

    override fun onScrollChanged(scrollX: Int, scrollY: Int, oldScrollX: Int, oldScrollY: Int) {
        super.onScrollChanged(scrollX, scrollY, oldScrollX, oldScrollY)
        when {
            scrollY > oldScrollY -> scrollListener?.onScrollDown()
            scrollY < oldScrollY -> scrollListener?.onScrollUp()
        }
        scrollListener?.onScroll(scrollX, scrollY, oldScrollX, oldScrollY)
    }
}

interface WebViewScrollListener{
    fun onScroll(scrollX: Int, scrollY: Int, oldScrollX: Int, oldScrollY: Int)

    fun onScrollDown()

    fun onScrollUp()
}

查看更多
狗以群分
5楼-- · 2020-01-23 07:32

Something like:

public class ObservableWebView extends WebView
{
    private OnScrollChangedCallback mOnScrollChangedCallback;

    public ObservableWebView(final Context context)
    {
        super(context);
    }

    public ObservableWebView(final Context context, final AttributeSet attrs)
    {
        super(context, attrs);
    }

    public ObservableWebView(final Context context, final AttributeSet attrs, final int defStyle)
    {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onScrollChanged(final int l, final int t, final int oldl, final int oldt)
    {
        super.onScrollChanged(l, t, oldl, oldt);
        if(mOnScrollChangedCallback != null) mOnScrollChangedCallback.onScroll(l, t, oldl, oldt);
    }

    public OnScrollChangedCallback getOnScrollChangedCallback()
    {
        return mOnScrollChangedCallback;
    }

    public void setOnScrollChangedCallback(final OnScrollChangedCallback onScrollChangedCallback)
    {
        mOnScrollChangedCallback = onScrollChangedCallback;
    }

    /**
     * Impliment in the activity/fragment/view that you want to listen to the webview
     */
    public static interface OnScrollChangedCallback
    {
        public void onScroll(int l, int t, int oldl, int oldt);
    }
}

Should work, this is untested but this works for almost every other view in Android.

You would implement like:

wv = (ObservableWebView) findViewById(R.id.scorllableWebview);
wv.setOnScrollChangedCallback(new OnScrollChangedCallback(){
    public void onScroll(int l, int t, int oldl, int oldt){
        if(t> oldt){
            //Do stuff
            System.out.println("Swipe UP");
            //Do stuff
        }
        else if(t< oldt){
            System.out.println("Swipe Down");
        }
        Log.d(TAG,"We Scrolled etc...");
    }
});
查看更多
家丑人穷心不美
6楼-- · 2020-01-23 07:44

Try this (for all view what you want): Сreate a GestureDetector then a TouchListener and set to a view who scrolling

OnCreate
         private GestureDetector gestureDetector;
         gestureDetector = new GestureDetector(this, new 
         GestureDetector.SimpleOnGestureListener() {
                @Override
                public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float 
           velocityY) {

                    if (velocityY < 0) {
                        collapse(frToolBar);

                    } else if (velocityY > 0) {
                        if (frToolBar.getVisibility()==View.GONE)
                        expand(frToolBar);
                    }
                    return super.onFling(e1, e2, velocityX, velocityY);
                }

                @Override
                public boolean onDown(MotionEvent e) {
                    return super.onDown(e);
                }
            });

          webView.setOnTouchListener((view, motionEvent) -> 
          gestureDetector.onTouchEvent(motionEvent));


    Two method - 

           public static void expand(final View v) {
            v.measure(WindowManager.LayoutParams.MATCH_PARENT,  
          indowManager.LayoutParams.WRAP_CONTENT);
             // final int targetHeight = v.getMeasuredHeight();
            final int targetHeight = v.getHeight();
            v.getLayoutParams().height = 1;
            v.setVisibility(View.VISIBLE);
            Animation a = new Animation() {
                @Override
                protected void applyTransformation(float interpolatedTime, Transformation t) 
           {
                    v.getLayoutParams().height = interpolatedTime == 1
                            ? WindowManager.LayoutParams.WRAP_CONTENT
                            : (int) (targetHeight * interpolatedTime);
                    v.requestLayout();
                }

                @Override
                public boolean willChangeBounds() {
                    return true;
                }
            };
            a.setDuration(300);
            v.startAnimation(a);

        }


        public static void collapse(final View v) {
            final int initialHeight = v.getMeasuredHeight();
            Animation a = new Animation() {
                @Override
                protected void applyTransformation(float interpolatedTime, Transformation t) 
           {
                    if (interpolatedTime == 1) {
                        v.setVisibility(View.GONE);
                    } else {
                        v.getLayoutParams().height = initialHeight - (int) (initialHeight * 
              interpolatedTime);
                        v.requestLayout();
                    }
                }

                @Override
                public boolean willChangeBounds() {
                    return true;
                }
            };
            a.setDuration(300);
            v.startAnimation(a);

        }
查看更多
登录 后发表回答