Scroll to a specific view in scroll view

2019-01-16 18:06发布

I have added a scrollview and the subchilds inside the scrollview. At some point i need to scroll to a specific view.

<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>

The above layout was created dynamically. so i can't have the xml file posted here. Layout creation is completely dynamic. Even the number of child view inside the linearlayout may also vary.

So when i click on the button i need to get scrolled to a particular view say here when i click on button i need to scroll to the linear layout 4. I tried with the scrollTo method but it scrolls to the top of the scrollview.

Please provide some suggestions.

11条回答
姐就是有狂的资本
2楼-- · 2019-01-16 18:39

try this:

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());

insideView.getY() will not work below API Level 11, for API Level below 11 you can replace insideView.getY() with insideView.getTop()

查看更多
走好不送
3楼-- · 2019-01-16 18:43

I think I have found more elegant and error prone solution using

ScrollView.requestChildRectangleOnScreen

No math involved, and contrary to other proposed solutions, it will handle correctly scrolling both ways up and down.

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
}

It is a good idea to wrap it into postDelayed to make it more reliable, in case the ScrollView is being changed at the moment

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);
}

Just nice isn`t?

查看更多
淡お忘
4楼-- · 2019-01-16 18:43

Since you can know the child LinearLayout that you need to scroll to, how about trying this.

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());

More information on scrollTo as well as smoothScrollTo

查看更多
冷血范
5楼-- · 2019-01-16 18:48

You can use method smoothScrollTo to scroll to specific view in scroll view. - Example:

my_scroll_View.smoothScrollTo(0, editText.getBottom());

Good luck!

查看更多
戒情不戒烟
6楼-- · 2019-01-16 18:48

Try to call view.requestFocus() on the view you want to scroll to.

查看更多
别忘想泡老子
7楼-- · 2019-01-16 18:49

If child that we need to scroll to is not a direct child then above solutions don't work

I have used below solution in my project, sharing it may be helpful to others

/**
 * 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);
}
查看更多
登录 后发表回答