Android: Making a button visible once webview is d

2020-02-12 08:10发布

I have a webview which shows an html file. When the user scrolls to the bottom of this file in webview, I want a button that was previously hidden to show up, which the user can then press to do some activity

I did something similar in iOS, where I just set the delegate to the ViewController and just set the button as visible. How do I do something similar on Android? I noticed there isn't a callback method like in iOS.

Edit: Right now, I have an activity with 2 objects: a webview containing my text, and a button which is currently invisible. I want my activity to receive a message when the webview text scrolls to the bottom, and make the button visible

5条回答
唯我独甜
2楼-- · 2020-02-12 08:18

[I can't comment on an answer, so leaving my comment here as a new answer]

karora's answer (the first) works very well, except that in the

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

method, calling

getContentHeight()

was wildly inaccurate for me. It reported a value much too small, so my listener was called when the user had only scrolled maybe a third of the way down the WebView. I used

computeVerticalScrollRange()

instead, and that is perfect. Thanks to this post for that helpful hint.

查看更多
爷、活的狠高调
3楼-- · 2020-02-12 08:18

try this:

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

To implement this, extend ScrollView and then override the onScrollChanged method (inherited from View).

查看更多
Viruses.
4楼-- · 2020-02-12 08:37

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.

查看更多
戒情不戒烟
5楼-- · 2020-02-12 08:37

Loading / Visible button only when webview reached / scrolled to bottom.

Create JavaScript class :

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

          }
       });
      }
    }

In onCreate() :

final JavaScriptInterface jsInterface = new JavaScriptInterface();
myWebView.addJavascriptInterface(jsInterface, "AndroidFunction");
查看更多
Bombasti
6楼-- · 2020-02-12 08:38

Solutions above didn't fully work for me for the similar issue (hide button while webView is being scrolled, show after scrolling is over). The reason I wanted it to hide while scrolling is because button I want to hide is for jumping to the very bottom of webview, and when it only worked for me when webview is static, but didn't jump to bottom while view is still being scrolled. So I did the following:

added a onScrollChanged callback to overridden webView, like suggested nearby:

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

and in my activity class which implements OnScrollChangedCallback

UPDATED:

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;
}
查看更多
登录 后发表回答