55

アプリケーションに新しいSwipeRefreshLayoutコンポーネントを実装しましListViewた。GridViewScrollView

のような水平ビューでは非常に悪い動作をしますHorizontalScrollView。右または左にスクロールすると、SwipeRefreshLayoutビューはタッチをキャッシュし、 がタッチHorizontalScrollViewを受信しないようにし、垂直方向のスクロールを開始して更新を実行します。

ScrollView以前に垂直方向とViewPager内側の問題を解決したので、この問題を解決しようとしrequestDisallowInterceptTouchEventましたが、うまくいきませんでした。SwipeRefreshLayoutまた、このメソッドがスーパーを返さずに元のクラスでオーバーライドされていることにも気付きました。Google の開発者は代わりにコメントを残しました " //Nope." :)

コンポーネントは比較的新しいためSwipeRefreshLayout、スワイプでビューを更新して垂直スクロールを追跡および処理できるようにしながら、水平スクロールの問題を修正するソリューションを見つけることができませんでした。または2つ。

4

5 に答える 5

165

を拡張SwipeRefreshLayoutしてオーバーライドすることで解決しましたonInterceptTouchEvent。内部では、ユーザーが移動した X 距離がタッチ スロップよりも大きいかどうかを計算します。そうであれば、ユーザーが水平方向にスワイプしていることを意味するためfalse、子ビュー (HorizontalScrollViewこの場合は ) がタッチ イベントを取得できるようにします。


public class CustomSwipeToRefresh extends SwipeRefreshLayout {

    private int mTouchSlop;
    private float mPrevX;

    public CustomSwipeToRefresh(Context context, AttributeSet attrs) {
        super(context, attrs);

        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mPrevX = MotionEvent.obtain(event).getX();
                break;

            case MotionEvent.ACTION_MOVE:
                final float eventX = event.getX();
                float xDiff = Math.abs(eventX - mPrevX);

                if (xDiff > mTouchSlop) {
                    return false;
                }
        }

        return super.onInterceptTouchEvent(event);
    }
}
于 2014-06-02T08:07:02.383 に答える
27

ACTION_MOVE イベントを既に辞退したという事実を覚えていない場合、ユーザーが最初の mPrevX の近くに戻った場合に、最終的にそれを受け取ることになります。

ブール値を追加して記憶するだけです。

public class CustomSwipeToRefresh extends SwipeRefreshLayout {

    private int mTouchSlop;
    private float mPrevX;
    // Indicate if we've already declined the move event
    private boolean mDeclined;

    public CustomSwipeToRefresh(Context context, AttributeSet attrs) {
        super(context, attrs);

        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mPrevX = MotionEvent.obtain(event).getX();
                mDeclined = false; // New action
                break;

            case MotionEvent.ACTION_MOVE:
                final float eventX = event.getX();
                float xDiff = Math.abs(eventX - mPrevX);

                if (mDeclined || xDiff > mTouchSlop) {
                    mDeclined = true; // Memorize
                    return false;
                }
        }

        return super.onInterceptTouchEvent(event);
    }
}
于 2014-06-27T13:34:56.477 に答える
0

Tim Roes EnhancedListView を使用する場合

この問題を参照してください。スワイプの開始時とスワイプの終了時を検出する機能が追加されているので、私にとって非常に便利でした。

スワイプの開始時に SwipeRefreshLayout を無効にし、スワイプの終了時に swipeRefreshLayout を有効にします。

于 2014-08-29T08:31:21.923 に答える