滚动到滚动视图中的特定视图

Raj*_*pal 48 android scrollview

我在scrollview中添加了一个scrollview和子项.在某些时候,我需要滚动到一个特定的视图.

<scrollview>

1. <linearlayout>

    <textview></textview>
    <textview></textview>

   </linearlayout>

2. <linearlayout>

    <textview></textview>
    <textview></textview>

   </linearlayout>

3. <linearlayout>

    <textview></textview>
    <textview></textview>

   </linearlayout>

4. <linearlayout>

    <textview></textview>
    <textview></textview>

   </linearlayout>

5. <linearlayout>

    <textview></textview>
    <textview></textview>

   </linearlayout>

6. <linearlayout>

    <textview></textview>
    <textview></textview>

   </linearlayout>

7. <linearlayout>

    <textview></textview>
    <textview></textview>

   </linearlayout>

   <button>
   </button>

 </scrollview>
Run Code Online (Sandbox Code Playgroud)

上面的布局是动态创建的.所以我不能在这里发布xml文件.布局创建完全是动态的.甚至线性布局内的子视图的数量也可以变化.

所以,当我点击按钮时,我需要滚动到特定的视图说这里当我点击按钮时我需要滚动到线性布局4.我尝试使用scrollTo方法,但它滚动到滚动视图的顶部.

请提供一些建议.

Vas*_*nth 96

如果我们需要滚动到的孩子不是直接孩子,则上述解决方案不起作用

我在我的项目中使用了以下解决方案,分享它可能对其他人有帮助

/**
 * Used to scroll to the given view.
 *
 * @param scrollViewParent Parent ScrollView
 * @param view View to which we need to scroll.
 */
private void scrollToView(final ScrollView scrollViewParent, final View view) {
    // Get deepChild Offset
    Point childOffset = new Point();
    getDeepChildOffset(scrollViewParent, view.getParent(), view, childOffset);
    // Scroll to child.
    scrollViewParent.smoothScrollTo(0, childOffset.y);
}

/**
 * Used to get deep child offset.
 * <p/>
 * 1. We need to scroll to child in scrollview, but the child may not the direct child to scrollview.
 * 2. So to get correct child position to scroll, we need to iterate through all of its parent views till the main parent.
 *
 * @param mainParent        Main Top parent.
 * @param parent            Parent.
 * @param child             Child.
 * @param accumulatedOffset Accumulated Offset.
 */
private void getDeepChildOffset(final ViewGroup mainParent, final ViewParent parent, final View child, final Point accumulatedOffset) {
    ViewGroup parentGroup = (ViewGroup) parent;
    accumulatedOffset.x += child.getLeft();
    accumulatedOffset.y += child.getTop();
    if (parentGroup.equals(mainParent)) {
        return;
    }
    getDeepChildOffset(mainParent, parentGroup.getParent(), parentGroup, accumulatedOffset);
}
Run Code Online (Sandbox Code Playgroud)

  • 太棒了 (9认同)
  • 好方案! (6认同)
  • 你的解决方案非常棒@Vasanth :-) (5认同)
  • 奇迹般有效! (4认同)
  • 很好的计算. (4认同)
  • 这很好用...还进行了一些微调,以使问题视图大致保持在上下文屏幕的顶部三分之一:int contextScrollViewOffset = scrollViewParent.getHeight()/ 3; int viewYOffset = Math.max(0,childOffset.y-contextScrollViewOffset); scrollViewParent.smoothScrollTo(0,viewYOffset); (4认同)
  • 您保存了我的一天,真的是很好的解决方案!非常感谢! (2认同)
  • @Vasanth这是金,谢谢 (2认同)
  • 非常感谢,递归摇滚! (2认同)
  • java.lang.ClassCastException:android.view.ViewRootImpl无法转换为android.view.ViewGroup (2认同)
  • 爱它。谢谢 (2认同)
  • 让我开心。非常感谢 (2认同)
  • 这篇文章中唯一可行的解​​决方案。 (2认同)
  • 完美运行!谢谢您添加此行将使用户可以看到完整视图:val rHeight = scrollViewParent.height 和 scrollViewParent.smoothScrollTo(0, childOffset.y - (rHeight/3)) (2认同)

Swa*_*_99 92

这应该做的伎俩:

View targetView = findViewById(R.id.DESIRED_VIEW_ID);  
targetView.getParent().requestChildFocus(targetView,targetView);
Run Code Online (Sandbox Code Playgroud)

public void RequestChildFocus(查看子项,查看焦点)

child - 此ViewParent的子项需要焦点.该视图将包含焦点视图.实际上并不一定是关注焦点的观点.

专注 -这是孩子的后代,实际上有焦点的视图

  • 这次真是万分感谢.为什么Android没有scrollView.scrollTo(viewId)让我感到困惑. (7认同)
  • 这对我有用,其他所有答案都失败了。 (2认同)

Dev*_*Dev 24

试试这个:

ScrollView sv = // your scrollview
View insideView = // find the View that you need to scroll to which is inside this ScrollView
sv.scrollTo(0, (int)insideView.getY());
Run Code Online (Sandbox Code Playgroud)

insideView.getY()将无法在API级别11以下工作,对于低于11的API级别,您可以替换insideView.getY()insideView.getTop()

  • 尝试 insideView.getTop() (2认同)
  • 可以工作,但添加了这个 - 我必须在 handler.post() 中使用此代码才能使其工作。 (2认同)

Šta*_*rke 9

我想我已经找到了更优雅,更容易出错的解决方案

ScrollView.requestChildRectangleOnScreen

不涉及数学,与其他提议的解决方案相反,它将正确处理向上和向下滚动两种方式.

void scrollToRow(ScrollView scrollView, LinearLayout linearLayout, TextView textViewToShow) {
    Rect textRect = new Rect(); //coordinates to scroll to
    textViewToShow.getHitRect(textRect); //fills textRect with coordinates of TextView relative to its parent (LinearLayout) 
    scrollView.requestChildRectangleOnScreen(linearLayout, textRect, false); //ScrollView will make sure, the given textRect is visible
}
Run Code Online (Sandbox Code Playgroud)

如果正在进行更改,最好将其包装起来postDelayed以使其更可靠ScrollView

private void scrollToRow(final ScrollView scrollView, final LinearLayout linearLayout, final TextView textViewToShow) {
    long delay = 100; //delay to let finish with possible modifications to ScrollView
    scrollView.postDelayed(new Runnable() {
        public void run() {
            Rect textRect = new Rect(); //coordinates to scroll to
            textViewToShow.getHitRect(textRect); //fills textRect with coordinates of TextView relative to its parent (LinearLayout) 
            scrollView.requestChildRectangleOnScreen(linearLayout, textRect, false); //ScrollView will make sure, the given textRect is visible
        }
    }, delay);
}
Run Code Online (Sandbox Code Playgroud)

好不好吗?


小智 8

经过大量研究并尝试了多种方法后,以下方法对我来说非常有效。

考虑到您的主要父级是 ScrollView,子视图是 LinearLayout 或relativelayout,其中可能有更多视图,可以有两种方法-

情况 1:您想要将焦点集中在 childView 之上。使用以下代码 -

public void scrollToViewTop(ScrollView scrollView, View childView) {
    long delay = 100; //delay to let finish with possible modifications to ScrollView
    scrollView.postDelayed(new Runnable() {
        public void run() {
            scrollView.smoothScrollTo(0, childView.getTop());
        }
    }, delay);
}
Run Code Online (Sandbox Code Playgroud)

情况 2:关注 childView 的底部。使用以下代码 -

public void scrollToViewBottom(ScrollView scrollView, View childView) {
    long delay = 100; //delay to let finish with possible modifications to ScrollView
    scrollView.postDelayed(new Runnable() {
        public void run() {
            scrollView.smoothScrollTo(0, childView.getBottom());
        }
    }, delay);
}
Run Code Online (Sandbox Code Playgroud)

要使用这些函数,只需像这样调用它们 -

scrollToViewTop(scrollView, childView);
scrollToViewBottom(scrollView, childView);
Run Code Online (Sandbox Code Playgroud)

希望它能拯救你的一天。快乐编码!


mid*_*nhk 7

既然你可以知道LinearLayout你需要滚动到的孩子,那么尝试这个怎么样.

ScrollView sv = // your scrollview
View highlightedItem = // find the LinearLayout or View that you need to scroll to which is inside this ScrollView
sv.scrollTo(0, highlightedItem.getY());
Run Code Online (Sandbox Code Playgroud)

有关scrollTo以及smoothScrollTo的更多信息


sye*_*gir 5

Kotlin:试试这个,它对我来说就像魅力一样!

parentScrollView.post(object : Runnable {
        override fun run() {
            parentScrollView.smoothScrollTo(0, targetView.bottom)
        }

    })
Run Code Online (Sandbox Code Playgroud)