NestedScrollViewの小さな穴を記録します

10054 ワード

NestedScrollViewの小さな穴を記録します
  需要は、上のbannerを実現するために、下にTabLayout+Fragment+RecyclerViewのレイアウトがあり、ページがスライドするときにTabが吸い上げられ、リストがスクロールされるように要求されます.これはよくあるレイアウトのはずです.この需要を見て自然と最初の時間にNestedScrollViewを思い出し、onNestedPreScrollを書き直すだけで、中で判断して、下へのスライド距離が上部Bannerの高さより小さいとき、親のレイアウトはスライドを消費します.スライドイベントは、Bannerの高さよりも下方スライド距離が大きい場合にRecyclerViewによって消費される.
@Override
    public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
        boolean headerScrollUp = dy > 0 && getScrollY() < mNestedScrollHeight;
        boolean headerScrollDown = dy < 0 && getScrollY() > 0 && !target.canScrollVertically(-1);
        if (headerScrollUp || headerScrollDown) {
            scrollBy(0, dy);
            consumed[1] = dy;
        }
        super.onNestedPreScroll(target, dx, dy, consumed, type);
    }

  コードは上記のようにmNestedScrollHeightはBannerの高さです.それからコードを書いてRunちょっと、うん?反応してないの?有効になりませんか?what fuck?私の論理が間違っていますか?ありえないよね?思わずプログラム猿の考え込んだ.DEBUGちょっと.onNestedPreScrollでブレークポイントを打つと、実行されていないことに気づきました!これはおかしいですね.またネット上のみんなの解決策を調べてみると、みんなそうしているのではないでしょうか.そこでまた自己疑いに陥った.午後を振り回したが、まだ振り回していない.その間、他の案でネストスライドをしていたが、効果はあまり悪くなかった.実現方式は非常にuglyだった.少しコード癖のあるプログラム猿の自覚を持って、onNestedPreScrollが呼び出されなかった理由を明らかにすることにしました.究極の解決策はread the fucking source codeです!  ここでネストされたスライドのサブレイアウトはRecyclerViewなので、消費スライドのイベントはRecyclerViewから発せられ、その後RecyclerViewのonTouchEventでACTION_DOWNで発行されるstartNestedScrollは、NestedScrollingChildHelperで具体的に実装される.再びDEBUGを通じて、RecyclerViewのView Parentが確かに私がカスタマイズしたStickyNestedScrollView(NestedScrollViewから継承)であることを確認し、安心丸を食べました.そしてRecyclerViewのonTouchEventに戻り、ACTION_MOVEではdispatchNestedPreScrollが呼び出され、ネストされた親レイアウトにネストされたスライドイベントが開始され、親レイアウトに渡されて先に処理されます.dispatchNestedPreScrollの具体的な実装もNestedScrollingChildHelperで、そこでViewParentCompatを呼び出した.onNestedPreScroll、View ParentCompat.を見てください.onNestedPreScrollのソースコード.
    public static void onNestedPreScroll(ViewParent parent, View target, int dx, int dy, int[] consumed, int type) {
        if (parent instanceof NestedScrollingParent2) {
            ((NestedScrollingParent2)parent).onNestedPreScroll(target, dx, dy, consumed, type);
        } else if (type == 0) {
            if (VERSION.SDK_INT >= 21) {
                try {
                    parent.onNestedPreScroll(target, dx, dy, consumed);
                } catch (AbstractMethodError var7) {
                    Log.e("ViewParentCompat", "ViewParent " + parent + " does not implement interface " + "method onNestedPreScroll", var7);
                }
            } else if (parent instanceof NestedScrollingParent) {
                ((NestedScrollingParent)parent).onNestedPreScroll(target, dx, dy, consumed);
            }
        }

    }

NestedScrollViewはNestedScrollingParent 2を実現しているので、ここでonNestedPreScroll(target,dx,dy,consumed,type)を呼び出しましたが、ここを見ると、この方法はどうして私が書き直す方法とは違うのでしょうか.次に継承関係を見続け、NestedScrollingParent 2インタフェースはNestedScrollingParentインタフェースから継承され、同名の関数onNestedPreScrollが追加されましたが、パラメータが追加されました.NestedScrollViewはNestedScrollingParent 2インタフェースを実現しました.最終的に呼び出されるのはNestedScrollingParent 2のonNestedPreScroll(target,dx,dy,consumed,type)メソッドです.したがって、NestedScrollViewを継承し、NestedScrollingParent 2のonNestedPreScroll(target,dx,dy,consumed,type)メソッドを書き換え、中で処理する必要があります.この同名の方法のため、私は穴があいて死んで、後で似たようなことに出会ってお菓子を長くしなければなりません.