5

我有一个显示 html 文件的 webview。当用户在 webview 中滚动到这个文件的底部时,我想要一个以前隐藏的按钮显示出来,然后用户可以按下它来做一些活动

我在 iOS 中做了类似的事情,我只是将委托设置为 ViewController 并将按钮设置为可见。我如何在 Android 上做类似的事情?我注意到没有像 iOS 那样的回调方法。

编辑:现在,我有一个包含 2 个对象的活动:一个包含我的文本的 web 视图和一个当前不可见的按钮。我希望我的活动在 webview 文本滚动到底部时收到一条消息,并使按钮可见

4

5 回答 5

8

I had to do this myself, in order to display an "I Agree" button once the user has scrolled to the bottom of a EULA. Lawyers, huh?

In fact when you override the WebView (rather than the ScrollView as in the answer from @JackTurky) you can call computeVerticalScrollRange() to get the height of the content, rather than getBottom() which returns the visible bottom and is not useful.

This is my comprehensive solution. As far as I can see this is all API Level 1 stuff, so it should work anywhere.

public class EulaWebView extends WebView {
    public EulaWebView(Context context) 
    {
        this(context, null);
    }

    public EulaWebView(Context context, AttributeSet attrs) 
    {
        this(context, attrs, 0);
    }

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

    public OnBottomReachedListener mOnBottomReachedListener = null;
    private int mMinDistance = 0;

    /**
     * Set the listener which will be called when the WebView is scrolled to within some
     * margin of the bottom.
     * @param bottomReachedListener
     * @param allowedDifference
     */
    public void setOnBottomReachedListener(OnBottomReachedListener bottomReachedListener, int allowedDifference ) {
        mOnBottomReachedListener = bottomReachedListener;
        mMinDistance = allowedDifference;
    }

    /**
     * Implement this interface if you want to be notified when the WebView has scrolled to the bottom.
     */
    public interface OnBottomReachedListener {
        void onBottomReached(View v);
    }

    @Override
    protected void onScrollChanged(int left, int top, int oldLeft, int oldTop) {
        if ( mOnBottomReachedListener != null ) {
            if ( (computeVerticalScrollRange() - (top + getHeight())) <= mMinDistance )
                mOnBottomReachedListener.onBottomReached(this);
        }
        super.onScrollChanged(left, top, oldLeft, oldTop);
    }

}

I use this to display an "I Agree" button once the user has scrolled to the bottom of the WebView, where I call it like this (in a class which "implements OnBottomReachedListener":

EulaWebView mEulaContent;
Button mEulaAgreed;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.eula);
    mEulaContent = (EulaWebView) findViewById(R.id.eula_content);
    StaticHelpers.loadWebView(this, mEulaContent, R.raw.stylesheet, StaticHelpers.readRawTextFile(this, R.raw.eula), null);
    mEulaContent.setVerticalScrollBarEnabled(true);
    mEulaContent.setOnBottomReachedListener(this, 50);

    mEulaAgreed = (Button) findViewById(R.id.eula_agreed);
    mEulaAgreed.setOnClickListener(this);
    mEulaAgreed.setVisibility(View.GONE);
}

@Override
public void onBottomReached(View v) {
    mEulaAgreed.setVisibility(View.VISIBLE);
}

So when the bottom is reached (or in this case, when they get within 50 pixels of it) the "I Agree" button appears.

于 2013-04-27T23:15:38.533 回答
2

[我无法对答案发表评论,因此将我的评论留在这里作为新答案]

karora 的答案(第一个)效果很好,除了在

protected void onScrollChanged(int left, int top, int oldLeft, int oldTop)

方法,调用

getContentHeight()

对我来说非常不准确。它报告的值太小了,所以当用户仅向下滚动 WebView 的三分之一时调用了我的侦听器。我用了

computeVerticalScrollRange()

相反,这是完美的。感谢这篇文章的有用提示。

于 2017-11-03T08:55:01.963 回答
0

仅当 webview 到达/滚动到底部时加载/可见按钮。

创建 JavaScript 类:

public class JavaScriptInterface {

  @android.webkit.JavascriptInterface
  public void didScrollToBottom() {
    Log.d(TAG, "Scroll to Bottom");
    myHandler.post(new Runnable() {
      @Override
      public void run() {
         btnAccept.setVisibility(View.VISIBLE);

          }
       });
      }
    }

在 onCreate() :

final JavaScriptInterface jsInterface = new JavaScriptInterface();
myWebView.addJavascriptInterface(jsInterface, "AndroidFunction");
于 2014-12-17T11:35:41.673 回答
0

尝试这个:

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        View view = (View) getChildAt(getChildCount()-1);
        int diff = (view.getBottom()-(getHeight()+getScrollY()));// Calculate the scrolldiff
        if( diff == 0 ){  // if diff is zero, then the bottom has been reached
            Log.d(ScrollTest.LOG_TAG, "MyScrollView: Bottom has been reached" );
            yourButton.setVisible(true);
        }
        super.onScrollChanged(l, t, oldl, oldt);
}

要实现这一点,请扩展 ScrollView,然后重写 onScrollChanged 方法(继承自 View)。

于 2012-06-08T22:41:25.987 回答
-1

对于类似的问题,上述解决方案对我来说并不完全有效(滚动 webView 时隐藏按钮,滚动结束后显示)。我希望它在滚动时隐藏的原因是因为我想隐藏的按钮是为了跳到 webview 的最底部,当它只在 webview 是静态的时候才对我有用,但在视图仍然存在时没有跳到底部滚动。所以我做了以下事情:

为覆盖的 webView 添加了一个 onScrollChanged 回调,就像附近建议的那样:

private OnScrollChangedCallback mOnScrollChangedCallback;

public OnScrollChangedCallback getOnScrollChangedCallback() {
    return mOnScrollChangedCallback;
}

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

@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.onScrollChanged(l, t);
    }
}

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

在我实现 OnScrollChangedCallback 的活动类中

更新:

Timer timer2showJumpButton;
private long lastScrollEventTimestamp;
public final static int HIDING_JUMP_BUTTON_ON_SCROLL_DELAY  = 500;

    public void onScrollChanged(int l, int t) {

    // showing button when scrolling starts
    if (btnJumpToBottom != null) {
        btnJumpToBottom.setVisibility(View.VISIBLE);
    }

    if (btnJumpToTop!= null) {
        btnJumpToTop.setVisibility(View.VISIBLE);
    }


    if (timer2showJumpButton == null) {

        final Runnable r2 = new Runnable() {

            @Override
            public void run() {
                if (btnJumpToBottom != null) {
                    btnJumpToBottom.setVisibility(View.GONE);
                }
                if (btnJumpToTop!= null) {
                    btnJumpToTop.setVisibility(View.GONE);
                }

            }
        };

        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                if (btnJumpToTop.getVisibility() == View.VISIBLE || btnJumpToBottom.getVisibility() == View.VISIBLE){
                    long currentTimestamp = System.currentTimeMillis();

                    if (currentTimestamp - lastScrollEventTimestamp > HIDING_JUMP_BUTTON_ON_SCROLL_DELAY1 ){                        
                        webView.postDelayed(r2, HIDING_JUMP_BUTTON_ON_SCROLL_DELAY);
                    }else{
                        //too soon
                    }
                }
            }
        };

        try {
            timer2showJumpButton = new Timer();
            timer2showJumpButton.schedule(timerTask, 500, 500);
        } catch (IllegalStateException e) {
            logger.warn(TAG + "/onScrollChanged/" + e.getMessage());

        }   
    }

    // adding runnable which will hide button back
    long currentTimestamp = System.currentTimeMillis();

    lastScrollEventTimestamp = currentTimestamp;
}
于 2014-10-08T12:16:38.820 回答