WebViewでSwipeRefreshLayoutを使用しようとしています。
ページの中央で、ユーザーが下にスクロールすると、不要な更新が開始されるという問題に直面しています。
更新イベントを発生させる方法は、webviewのスクロール位置が一番上にある場合のみです。 (つまり、彼はページの上部を見ています)?
何も拡張することなく、なんとか解決できました。このスニペットをご覧ください(フラグメント固有):
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 に対する私の答えをご覧ください。
これを行うための推奨される方法は、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;
}
}
Fragment
またはActivity
を_ViewTreeObserver.OnScrollChangedListener
_で実装し、webview.getViewTreeObserver().addOnScrollChangedListener(this);
のようにリスナーを設定するだけです
onScrollChanged()
メソッドではこのようにします
_ @Override
public void onScrollChanged() {
if (webview.getScrollY() == 0) {
swipeLayout.setEnabled(true);
} else {
swipeLayout.setEnabled(false);
}
}
_
これを解決するには、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);
}
}
私は同じ質問に答えていますが、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
と等しくなります。このソリューションと他のソリューションこのページでは機能しない可能性があります。
私は同様の問題に直面していましたが、ここで与えられた答えはどれも私にとってはうまくいきません。だから、私は 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);
}}
ステップ2:xmlファイルでwebview
のように使用この-
<com.yourpackagename.CustomWebView
Android:id="@+id/webview"
Android:layout_width="match_parent"
Android:layout_height="match_parent"/>
ステップ3:MainActivity
でsetOnScrollChangedCallback
を使用します-
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
メソッドであるため、ListView
sとWebView
sの両方で使用できます。他の種類のスクロール子の場合)。
私のレイアウトクラスは次のようになります。
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();
}
}
(前述のように、canScrollVertically
はView
メソッドであるため、ListView
は一般的なView
またはその他の特殊なビュークラスに安全に置き換えることができます。)