web-dev-qa-db-ja.com

スクロール位置が上部にあるときのSwipeRefreshLayout + WebView

WebViewでSwipeRefreshLayoutを使用しようとしています。

ページの中央で、ユーザーが下にスクロールすると、不要な更新が開始されるという問題に直面しています。

更新イベントを発生させる方法は、webviewのスクロール位置が一番上にある場合のみです。 (つまり、彼はページの上部を見ています)?

26
eugene

何も拡張することなく、なんとか解決できました。このスニペットをご覧ください(フラグメント固有):

private ViewTreeObserver.OnScrollChangedListener mOnScrollChangedListener;

@Override
public void onStart() {
    super.onStart();

    swipeLayout.getViewTreeObserver().addOnScrollChangedListener(mOnScrollChangedListener =
            new ViewTreeObserver.OnScrollChangedListener() {
                @Override
                public void onScrollChanged() {
                    if (mWebView.getScrollY() == 0)
                        swipeLayout.setEnabled(true);
                    else
                        swipeLayout.setEnabled(false);

                }
            });
}

@Override
public void onStop() {
    swipeLayout.getViewTreeObserver().removeOnScrollChangedListener(mOnScrollChangedListener);
    super.onStop();
}

より広いコンテキストについては、 Android-空のtextviewを使用したSwipeRefreshLayout に対する私の答えをご覧ください。

27
vizZ

これを行うための推奨される方法は、SwipeRefreshLayoutを拡張し、canChildScrollUp()をオーバーライドすることだと思います- https://developer.Android.com/reference/Android/support/v4/ widget/SwipeRefreshLayout.html#canChildScrollUp()

これがGoogleでの方法ですIO 2014 Scheduleアプリ- https://github.com/google/iosched/blob/master/Android/src/main/Java/ com/google/samples/apps/iosched/ui/widget/MultiSwipeRefreshLayout.Java#L76

CustomSwipeRefreshLayoutはおそらく次のようになります。

public class CustomSwipeRefreshLayout extends SwipeRefreshLayout {

    private CanChildScrollUpCallback mCanChildScrollUpCallback;

    public interface CanChildScrollUpCallback {
        boolean canSwipeRefreshChildScrollUp();
    }

    public void setCanChildScrollUpCallback(CanChildScrollUpCallback canChildScrollUpCallback) {
        mCanChildScrollUpCallback = canChildScrollUpCallback;
    }

    @Override
    public boolean canChildScrollUp() {
        if (mCanChildScrollUpCallback != null) {
            return mCanChildScrollUpCallback.canSwipeRefreshChildScrollUp();
        }
        return super.canChildScrollUp();
    }
}

そして、Activityを持つWebViewで、

public class FooActivity
        implements CustomSwipeRefreshLayout.CanChildScrollUpCallback {

    private CustomSwipeRefreshLayout mRefreshLayout;
    private WebView mWebView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // after initialization
        mRefreshLayout.setCanChildScrollUpCallback(this);
    }

    @Override
    public boolean canSwipeRefreshChildScrollUp() {
        return mWebview.getScrollY() > 0;
    }
}
20
hiBrianLee

FragmentまたはActivityを_ViewTreeObserver.OnScrollChangedListener_で実装し、webview.getViewTreeObserver().addOnScrollChangedListener(this);のようにリスナーを設定するだけです

onScrollChanged()メソッドではこのようにします

_    @Override
    public void onScrollChanged() {
        if (webview.getScrollY() == 0) {
            swipeLayout.setEnabled(true);
        } else {
            swipeLayout.setEnabled(false);
        }
    }
_
8
Pranav

これを解決するには、WebViewを取り込み、WebViewを使用してscrollYの位置を確認するカスタムSwipeRefreshLayoutでSwipeRefreshLayoutを拡張します。

注:これはページ全体をスクロールするには機能しますが、ネストされたスクロールでは機能しない場合があります。また、水平スクロールがある場合は、この回答で見つかったロジックを追加することもできます。 https://stackoverflow.com/a/24453194

public class CustomSwipeToRefresh extends SwipeRefreshLayout {

    private final int yScrollBuffer = 5;
    private WebView mWebView;

    public CustomSwipeToRefresh(Context context, WebView webView) {
        super(context);

        mWebView = webView;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        if (mWebView.getScrollY() > yScrollBuffer)
            return false;

        return super.onInterceptTouchEvent(event);
    }
}
2
Isaac

私は同じ質問に答えていますが、Kotlinを使用しています。 swipeRefreshLayoutのscrollYが0を取得するときにwebViewを有効にすることにより:

フラグメントまたはアクティビティでこの変数を作成します。

private val onScrollChangedListener = ViewTreeObserver.OnScrollChangedListener{ swipeRefreshLayout.isEnabled = webView.scrollY == 0 }

次にonViewCreated

swipeRefreshLayout.viewTreeObserver.addOnScrollChangedListener(onScrollChangedListener)

次にonStop

swipeRefreshLayout.viewTreeObserver.removeOnScrollChangedListener(onScrollChangedListener)

ここからはすべてうまくいきます。しかし、使用しているWebページにスクロールしない固定ヘッダーがある場合、scrollYは常に0と等しくなります。このソリューションと他のソリューションこのページでは機能しない可能性があります。

1
Xenolion

私は同様の問題に直面していましたが、ここで与えられた答えはどれも私にとってはうまくいきません。だから、私は this answerから解決策を得た。

ステップ1:クラスの作成CustomWebView

public class CustomWebView extends WebView{

private OnScrollChangedCallback mOnScrollChangedCallback;

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

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

public CustomWebView(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);
}

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 horizontal, int vertical);
}}

ステップ2xmlファイルでwebviewのように使用この-

 <com.yourpackagename.CustomWebView
        Android:id="@+id/webview"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"/>

ステップ3MainActivitysetOnScrollChangedCallbackを使用します-

  mWebView.setOnScrollChangedCallback(new CustomWebView.OnScrollChangedCallback(){
        public void onScroll(int horizontal, int vertical){
            System.out.println("=="+horizontal+"---"+vertical);
   //this is to check webview scroll behaviour
            if (vertical<50){
                swipeRefreshLayout.setEnabled(true);
            }else{
                swipeRefreshLayout.setEnabled(false);
            }
        }
    });
}

HiBrianLee almostが提供する答えは私にとってはうまくいきましたが、John Shelleyが書いたように、getScrollYは常に0を返しました(ネストされたスクロール子としてListViewを使用しました) )。ただし、すぐに機能したのは、代わりにcanScrollVerticallyを使用することでした(これはViewメソッドであるため、ListViewsとWebViewsの両方で使用できます。他の種類のスクロール子の場合)。

私のレイアウトクラスは次のようになります。

public class NestedScrollSwipeLayout extends SwipeRefreshLayout {

    private ListView scrollChild;

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

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

    public void setScrollChild(ListView child) {
        this.scrollChild = child;
    }

    @Override
    public boolean canChildScrollUp() {
        return (scrollChild != null && scrollChild.canScrollVertically(-1)) ||
            super.canChildScrollUp();
    }
}

(前述のように、canScrollVerticallyViewメソッドであるため、ListViewは一般的なViewまたはその他の特殊なビュークラスに安全に置き換えることができます。)

0
doertsch