16

我在CardView父级内部有可扩展的视图NestedScrollView。当展开动画结束时,我正在尝试为子项创建平滑滚动。但我只找到了一种解决方案:

 scrollView.requestChildFocus(someView, someView);

这段代码工作正常,但是,当调用requestChildFocus它时,它会立即滚动,这让我有点恼火。是否可以顺利滚动到孩子?

4

8 回答 8

29

childView我想滚动到的 , 具有父CardView级,因此childView.getTop()将相对于CardViewnot 的值返回给ScrollView. 因此,要获得相对于我的最高水平,ScrollView我应该childView.getParent().getParent()将其转换为View并调用getTop().

滚动位置计算如下

int scrollTo = ((View) childView.getParent().getParent()).getTop() + childView.getTop();
nestedScrollView.smoothScrollTo(0, scrollTo);
于 2015-11-05T08:08:11.620 回答
5

更多来自@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)
}
于 2020-02-25T01:15:42.290 回答
4

我有不同级别的子视图到滚动视图,所以根据接受的答案制作了这个函数来计算距离和滚动

  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("view not found");
    return 0;
}

然后滚动使用

journal_scrollview.smoothScrollTo(0, distance);
于 2019-02-22T01:01:44.023 回答
1

你可以使用我的图书馆ViewPropertyObjectAnimator

假设mNestedScrollView是您的NestedScrollView并且是您要滚动到mChildView的孩子,您可以执行以下操作:View

ViewPropertyObjectAnimator.animate(mNestedScrollView).scrollY(mChildView.getTop()).start();

只要确保mChildView.getTop()不是0在调用的那一刻.animate(...)

编辑:

正如我所说:确保View'sCALL 时您的顶部不为零.animate(...)。换句话说:.animate(...)只有当您的孩子View已经有了尺寸时才打电话。你怎么能确定呢?例如像这样:

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();
        }
    }
});
于 2015-11-04T17:25:09.980 回答
1

尝试阅读源代码。

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是您希望在屏幕上显示视图的地方。

于 2015-11-04T13:08:15.680 回答
0

这应该可以完成工作,其中 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);
    }
于 2018-11-13T02:44:10.803 回答
0

我发现公认的答案是可行的,但它目前特定于他们的视图结构,它不能用作静态方法来用于具有不同视图结构的所有类似滚动。我在一个实用程序类中制作了各种它,直到它发现它是 ScrollView 或 NestedScrollView 父级。我这样做是为了让 scrollToView(View,View) 方法可以同时与 ScrollView 和 NestedScrollView 一起使用,以防我稍后会更新使用的内容或其他方式。您当然可以直接调用正确的“子方法”。

public static void scrollToView(View scrollView, View scrollToView) {
    if (scrollToView == null) {
        Log.d(TAG, "scrollToView() failed due to scrollToView == NULL!");
        return;
    }
    if (scrollView instanceof NestedScrollView) {
        scrollToInNestedView((NestedScrollView) scrollView, scrollToView);
    } else if (scrollView instanceof ScrollView) {
        scrollToInScrollView((ScrollView) scrollView, scrollToView);
    } else {
        Log.d(TAG, "scrollToView() failed due to scrollView not appearing to be any kind of scroll view!");
    }
}

public static void scrollToInNestedView(NestedScrollView scrollView, View scrollToView) {
    if (scrollView == null || scrollToView == null) {
        return;
    }
    scrollView.post(() -> {
        int startY = scrollView.getScrollY();
        int requiredY = scrollToView.getTop();
        View parent = (View) scrollToView.getParent();
        while (parent != null && !(parent instanceof NestedScrollView)) {
            requiredY += parent.getTop();
            parent = (View) parent.getParent();
        }
        if (requiredY != startY) {
            scrollView.smoothScrollTo(0, requiredY);
        }
    });
}

public static void scrollToInScrollView(ScrollView scrollView, View scrollToView) {
    if (scrollView == null || scrollToView == null) {
        return;
    }
    scrollView.post(() -> {
        int startY = scrollView.getScrollY();
        int requiredY = scrollToView.getTop();
        View parent = (View) scrollToView.getParent();
        while (parent != null && !(parent instanceof ScrollView)) {
            requiredY += parent.getTop();
            parent = (View) parent.getParent();
        }
        if (requiredY != startY) {
            scrollView.smoothScrollTo(0, requiredY);
        }
    });
}
于 2021-09-29T03:52:08.623 回答
0

主要问题是计算对于嵌套滚动视图的正确 x/y 位置。但是,这里的大多数答案都试图通过在层次结构中导航并硬编码所需视图的层次结构级别来提出解决方案。恕我直言,如果您更改视图组层次结构,这很容易出错。

因此,我建议使用更简洁的方法,它基于 a 计算相对位置Rect。然后,您可以使用nestedscrollview 的smoothScrollTo(..)方法滚动到所需位置。

于 2020-07-21T16:09:16.817 回答