親がCardView
であるNestedScrollView
内に拡張可能なビューがあります。展開アニメーションが終了したときに子へのスムーズなスクロールを作成しようとしています。しかし、私はただ1つの解決策を見つけました:
scrollView.requestChildFocus(someView, someView);
このコードは正常に機能しますが、requestChildFocus
を呼び出すとすぐにスクロールするため、少し面倒です。子までスムーズにスクロールできますか?
スクロールしたいchildView
にはCardView
parrentがあるため、childView.getTop()
はCardView
ではなくScrollView
に関連する値を返します。 var] _。したがって、ScrollView
に対してトップを取得するには、childView.getParent().getParent()
を取得し、それをView
にキャストして、getTop()
を呼び出す必要があります。
スクロール位置は次のように計算されます
int scrollTo = ((View) childView.getParent().getParent()).getTop() + childView.getTop();
nestedScrollView.smoothScrollTo(0, scrollTo);
あなたは私のライブラリを使うことができます ViewPropertyObjectAnimator
そのために。
mNestedScrollView
がNestedScrollView
であり、mChildView
がスクロール先の子View
であるとすると、次のことができます。
_ViewPropertyObjectAnimator.animate(mNestedScrollView).scrollY(mChildView.getTop()).start();
_
mChildView.getTop()
を呼び出すときに、.animate(...)
が_0
_でないことを確認してください。
編集:
私が言ったように:CALL .animate(...)
のときは、_View's
_トップがゼロ以外であることを確認してください。言い換えると、子View
にすでにディメンションがある場合にのみ.animate(...)
を呼び出します。どうすればそれを判断できますか?たとえば、次のようになります。
_mChildView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int width = mChildView.getWidth();
int height = mChildView.getHeight();
if (width > 0 && height > 0) {
if (Android.os.Build.VERSION.SDK_INT >= Android.os.Build.VERSION_CODES.JELLY_BEAN) {
mChildView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
mChildView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
ViewPropertyObjectAnimator.animate(mNestedScrollView)
.scrollY(mChildView.getTop())
.start();
}
}
});
_
ソースコードを読んでみてください。
svMain.setSmoothScrollingEnabled(true);
Rect rect = new Rect();
rect.top = 0;
rect.left = 0;
rect.right = tv4.getWidth();
rect.bottom =tv4.getHeight();
svMain.requestChildRectangleOnScreen(tv4,rect,false);
rect
は、ビューを画面に表示する場所です。
@ jerry-shaからの回答の詳細
fun NestedScrollView.smoothScrollTo(view: View) {
var distance = view.top
var viewParent = view.parent
//traverses 10 times
for (i in 0..9) {
if ((viewParent as View) === this) break
distance += (viewParent as View).top
viewParent = viewParent.getParent()
}
smoothScrollTo(0, distance)
}
これで作業が完了します。ここで、childViewはスクロール先のビューです。
public static void scrollToView(final NestedScrollView nestedScrollView, final View viewToScrollTo) {
final int[] xYPos = new int[2];
viewToScrollTo.getLocationOnScreen(xYPos);
final int[] scrollxYPos = new int[2];
nestedScrollView.getLocationOnScreen(scrollxYPos);
int yPosition = xYPos[1];
if (yPosition < 0) {
yPosition = 0;
}
nestedScrollView.scrollTo(0, scrollxYPos[1] - yPosition);
}
スクロールビューとは異なるレベルの子ビューがあったので、受け入れられた回答に基づいてこの関数を作成し、距離とスクロールを計算しました
private int findDistanceToScroll(View view){
int distance = view.getTop();
ViewParent viewParent = view.getParent();
//traverses 10 times
for(int i = 0; i < 10; i++) {
if (((View) viewParent).getId() == R.id.journal_scrollview) {
return distance;
}
distance += ((View) viewParent).getTop();
viewParent = viewParent.getParent();
}
Timber.w("scrollview not found");
return 0;
}
次に、を使用してスクロールします
journal_scrollview.smoothScrollTo(0, distance);