可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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>
回答1:
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...");
}
});
回答2:
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:
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()
}
回答4:
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());
}
});
回答5:
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);
}