How to make a Scroll Listener for WebView in Android
Asked Answered
T

7

48

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>
Tallbot answered 7/2, 2013 at 13:40 Comment(3)
check this https://mcmap.net/q/341546/-android-webview-scrollable and #10553202Supplemental
then what do you want?Supplemental
its not calling my onScroll method while scrolling the webview. please have a look on my scorllableWebview.java classTallbot
B
92

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...");
    }
});
Biotite answered 7/2, 2013 at 14:16 Comment(10)
@Biotite it didn't worked, it gave an error on line where we used findViewBid of ClassCastExceptionTourism
@AnasReza You have to make sure you implement your ObservableWebView in your XML file. This was implied.Biotite
@Biotite yeah thanks i implemented in my XML file and it worked fineTourism
nt tek = (int) Math.floor(mTermsCondWV.getContentHeight() * mTermsCondWV.getScale()); if(tek - mTermsCondWV.getScrollY() == mTermsCondWV.getHeight()){ mAgreeBT.setEnabled(true); mAgreeBT.setBackground(ContextCompat.getDrawable(getActivity(),R.drawable.button_bg)); }Sussex
I use this code for end of the scroll but its not working in naugatSussex
@AmitVerma literally see the answer below: https://mcmap.net/q/341290/-how-to-make-a-scroll-listener-for-webview-in-androidBiotite
UI flicker on scrolling.Khudari
Hi its not working for the latest version apis , can you please update answerUndersized
is there any way to do for IOS ?Diplopia
@MukeshLokare Could I ask which version api is not working for you?Helpless
D
23

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);
}
}
Denier answered 5/12, 2015 at 20:20 Comment(2)
@LucasS.Müller : you have to support backward version so you can't simply ignore itRubble
Hi Alecio its not working for the latest version apisUndersized
S
10

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());
    }
});
She answered 24/10, 2019 at 13:50 Comment(3)
And what is the webView Scroll Stop Listener ?Carnahan
workin in 2022 best answer... for webview...Overboard
Still 100% workable in 2023.Aborigine
V
6

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()
}

Vitalize answered 3/10, 2019 at 11:29 Comment(0)
C
3

You can try this:

It works for API >= 23 Android Marshmallow

web.setOnScrollChangeListener(new View.OnScrollChangeListener() {

            @Override
            public void onScrollChange(View p1, int p2, int p3, int p4, int p5)
            {
                Toast.makeText(getApplicationContext, "Scrolled", Toast.LENGTH_SHORT).show();
            }
        });
Casimir answered 27/6, 2020 at 12:53 Comment(0)
R
2

From API 23 (Android - 6.0) , You can implement WebView.OnScrollChangeListener like

    public class MainActivity extends AppCompatActivity implements WebView.OnScrollChangeListener
    {
         @Override
         public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) 
         {
             if(oldScrollY < scrollY) 
             {
                 //Scrolling Upwards
             }
             else if(oldScrollY > scrollY)
             {
                 //Scrolling Downwards
             }
         }
    }
Reprehensible answered 7/8, 2021 at 2:59 Comment(0)
L
1

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);

        }
Larimor answered 6/6, 2019 at 8:22 Comment(2)
please explain your answerAsare
Сreate a gesturdektor then touchlister and set to a view who scrollingLarimor

© 2022 - 2024 — McMap. All rights reserved.