Androidネストスライド機構(NestedScrolling)Androidネストスライド機構(NestedScrolling)Androidネストスライド機構(NestedScrolling)
12566 ワード
Androidネストスライド機構(NestedScrolling)
効果は上図のようです【私を嫌ってはいけません】
これまで、
この配布メカニズムには、次のような脆弱性があります.
子viewがtouchイベントを処理する機会を得た場合、親viewは次の指が押されるまでこのtouchイベントを処理する機会がなくなります.
すなわち,我々がサブViewをスライドさせる場合,サブViewがこのスライドイベントを処理したくない場合,親viewに渡さずにこのtouchイベントを捨てるしかない.
しかし、Googleの新しい
NestedScrollingChild NestedScrollingParent NestedScrollingChildHelper NestedScrollingParentHelper
以上の4つのクラスは
はい、簡単ならそうすればいいです.
これらのインタフェースは、私たちが必要とするときに自分で呼び出したものです.childHelperは何をしましたか?
ここでは
では、具体的にはどのようにこのメカニズムを使用しますか?例えば、子Viewの場合、親viewにネストされたtouchイベントを共有する必要があることを通知する必要があります.では、scrollインタラクションのみを含むワークフロー全体について説明します.
一、startNestedScroll
まずサブビューはプロセス全体を開く必要があります(内部は主にnestedScrollを受け入れるのに適したparentを見つけます)、親Viewに通知します.私はあなたと協力してTouchEventを処理します.
二、dispatchNestedPreScroll
子Viewの
三、dispatchNestedScroll
親viewにスクロール状況を報告し、サブviewが消費している部分と、サブviewが消費していない部分を含む.親viewがスクロールパラメータを受け入れて一部消費した場合、この関数はtrueを返します.そうでない場合falseです.この関数は一般的にサブviewでscrollを処理した後に呼び出されます.
四、stopNestedScroll
プロセス全体を終了します.
対応プロセス全体がこうです
サブビュー
親view
startNestedScroll
onStartNestedScroll、onNestedScrollAccepted
dispatchNestedPreScroll
onNestedPreScroll
dispatchNestedScroll
onNestedScroll
stopNestedScroll
onStopNestedScroll
一般に、サブviewが呼び出しを開始し、親viewがコールバックを受信します.
最も注目すべきは
これは
NestedScrollの紹介はここまでですが、次回は
NestedScrolling
の特性はどこに現れますか?例えば、Toolbar
を使用して、次のScrollView
、上にスクロールしてToolbar
を隠し、下にスクロールしてToolbar
を表示します.ここでは論理的にNestedScrolling
です.Toolbar
を含むViewをスクロールする過程で、
が中のScrollView
をスクロールしたからです.効果は上図のようです【私を嫌ってはいけません】
これまで、
Android
対Touch
イベントの配布には独自のメカニズムがあることを知っていました.主に3つの関数があります.dispatchTouchEvent
、onInterceptTouchEvent
、onTouchEvent
です.この配布メカニズムには、次のような脆弱性があります.
子viewがtouchイベントを処理する機会を得た場合、親viewは次の指が押されるまでこのtouchイベントを処理する機会がなくなります.
すなわち,我々がサブViewをスライドさせる場合,サブViewがこのスライドイベントを処理したくない場合,親viewに渡さずにこのtouchイベントを捨てるしかない.
しかし、Googleの新しい
NestedScrolling
メカニズムはこの問題をよく解決した.このNestedScrolling
をどのように実現するかを見てみましょう.まず、いくつかのクラス(インタフェース)に注目する必要があります.NestedScrollingChild NestedScrollingParent NestedScrollingChildHelper NestedScrollingParentHelper
以上の4つのクラスは
support-v4
パッケージで提供されており、LollipopのViewデフォルトではいくつかの方法が実装されています.インタフェースの実装は簡単ですが、ここではNestedScrollingChild
シリーズの方法を一時的に使用しました(Parentはsupport-designが提供するCoordinatorLayout
なので) @Override
public void setNestedScrollingEnabled(boolean enabled) {
super.setNestedScrollingEnabled(enabled);
mChildHelper.setNestedScrollingEnabled(enabled);
}
@Override
public boolean isNestedScrollingEnabled() {
return mChildHelper.isNestedScrollingEnabled();
}
@Override
public boolean startNestedScroll(int axes) {
return mChildHelper.startNestedScroll(axes);
}
@Override
public void stopNestedScroll() {
mChildHelper.stopNestedScroll();
}
@Override
public boolean hasNestedScrollingParent() {
return mChildHelper.hasNestedScrollingParent();
}
@Override
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow);
}
@Override
public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
}
@Override
public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
}
@Override
public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
return mChildHelper.dispatchNestedPreFling(velocityX, velocityY);
}
はい、簡単ならそうすればいいです.
これらのインタフェースは、私たちが必要とするときに自分で呼び出したものです.childHelperは何をしましたか?
startNestedScroll
の方法を見てみましょう /** * Start a new nested scroll for this view. * * <p>This is a delegate method. Call it from your {@link android.view.View View} subclass * method/{@link NestedScrollingChild} interface method with the same signature to implement * the standard policy.</p> * * @param axes Supported nested scroll axes. * See {@link NestedScrollingChild#startNestedScroll(int)}. * @return true if a cooperating parent view was found and nested scrolling started successfully */
public boolean startNestedScroll(int axes) {
if (hasNestedScrollingParent()) {
// Already in progress
return true;
}
if (isNestedScrollingEnabled()) {
ViewParent p = mView.getParent();
View child = mView;
while (p != null) {
if (ViewParentCompat.onStartNestedScroll(p, child, mView, axes)) {
mNestedScrollingParent = p;
ViewParentCompat.onNestedScrollAccepted(p, child, mView, axes);
return true;
}
if (p instanceof View) {
child = (View) p;
}
p = p.getParent();
}
}
return false;
}
ここでは
NestedScrollingParent
とのインタラクションを実現するためのいくつかの方法を見ることができます.ViewParentCompat
は、親viewとインタラクティブな互換クラスであり、api versionを判断し、Lollipop以上であればviewが持参した方法を用い、そうでなければNestedScrollingParent
インタフェースが実現されたかどうかを判断し、インタフェースを呼び出す方法である.では、具体的にはどのようにこのメカニズムを使用しますか?例えば、子Viewの場合、親viewにネストされたtouchイベントを共有する必要があることを通知する必要があります.では、scrollインタラクションのみを含むワークフロー全体について説明します.
一、startNestedScroll
まずサブビューはプロセス全体を開く必要があります(内部は主にnestedScrollを受け入れるのに適したparentを見つけます)、親Viewに通知します.私はあなたと協力してTouchEventを処理します.
二、dispatchNestedPreScroll
子Viewの
onInterceptTouchEvent
またはonTouch
(一般的にMontionEvent.ACTION_MOVEイベント内)では、このメソッドを呼び出して親Viewがスライドする距離を通知する.この方法の3番目の4番目のパラメータは、親viewが消費したscroll長さとサブViewのフォームオフセット量を返します.このscrollが消費されていない場合、サブviewは残りの距離を処理し、フォームが移動したため、指の最後の位置を記録した場合、4番目のパラメータoffsetInWindow
に基づいてオフセット量を計算する必要があり、次のtouchイベントの計算が正しいことを保証することができます.親viewがスクロールパラメータを受け入れて一部消費した場合、この関数はtrueを返します.そうでない場合falseです.この関数は一般にサブviewでscrollを処理する前に呼び出されます.三、dispatchNestedScroll
親viewにスクロール状況を報告し、サブviewが消費している部分と、サブviewが消費していない部分を含む.親viewがスクロールパラメータを受け入れて一部消費した場合、この関数はtrueを返します.そうでない場合falseです.この関数は一般的にサブviewでscrollを処理した後に呼び出されます.
四、stopNestedScroll
プロセス全体を終了します.
対応プロセス全体がこうです
サブビュー
親view
startNestedScroll
onStartNestedScroll、onNestedScrollAccepted
dispatchNestedPreScroll
onNestedPreScroll
dispatchNestedScroll
onNestedScroll
stopNestedScroll
onStopNestedScroll
一般に、サブviewが呼び出しを開始し、親viewがコールバックを受信します.
最も注目すべきは
dispatchNestedPreScroll
のconsumed
パラメータである. public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) ;
これは
int
型の配列で、長さは2で、最初の要素は親viewが消費するx
方向の転がり距離です.2番目の要素は、親viewが消費するy
方向のスクロール距離であり、この2つの値が0でない場合、サブviewはスクロール量をいくつか修正する必要がある.このパラメータがあるからこそ、スクロールイベントを処理するとき、考え方がより明確になり、以前のようにスクロールパラメータの山に混同されることはありません.NestedScrollの紹介はここまでですが、次回は
CoordinatorLayout
の使用(わかりにくいBehaviorオブジェクト)とSegmentFault Android
での実践についてお話しします.応援ありがとうございます.