Scroll to a specific view in scroll view

前端 未结 15 1401
醉梦人生
醉梦人生 2020-12-04 14:08

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



1. 

        
相关标签:
15条回答
  • 2020-12-04 14:31

    For me, the best way to achieve this is to use the requestRectangleOnScreen() function. It is available from View that you want to scroll. You don't need access to the ScrollView and you don't need to calculate the childOffset. It does not change the focus and does not seems to be a hack in code. (I would never guess that requestChildFocus() is used for scrolling)

    Also in kotlin you can add some small extension functions to make it's usage a way simpler:

    1. Add two extension functions for View:
    fun View.requestOnScreen() = post {
        requestRectangleOnScreen(getDrawingRect())
    }
        
    fun View.getDrawingRect() = Rect().also(::getDrawingRect)
    
    1. Use that functions whenether you need:

    view.requestOnScreen()

    And that's all.

    0 讨论(0)
  • 2020-12-04 14:36

    This should do the trick:

    View targetView = findViewById(R.id.DESIRED_VIEW_ID);  
    targetView.getParent().requestChildFocus(targetView,targetView);
    

    public void RequestChildFocus (View child, View focused)

    child - The child of this ViewParent that wants focus. This view will contain the focused view. It is not necessarily the view that actually has focus.

    focused - The view that is a descendant of child that actually has focus

    0 讨论(0)
  • 2020-12-04 14:39

    Use :

    final  ScrollView scrollView= (ScrollView) 
    int speed=1000;
    findViewById(R.id.main_scrollView);
    final View view = findViewById(R.id.your_view); 
    ViewTreeObserver vto = view.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() { view.getViewTreeObserver().removeOnGlobalLayoutListener(this);   
                    ObjectAnimator.ofInt(scrollView, "scrollY",  (int) view.getY()).setDuration(speed).start();
                }
            }); 
    
    0 讨论(0)
  • 2020-12-04 14:42

    I got the desired result using requestChildFocus() as suggested by Swas_99's answer above.

    However since it doesn't do smooth scrolling, I looked into the source code for requestChildFocus which calls scrollToChild which calls offsetDescendantRectToMyCoords. From there I got the idea to use the following C#/Xamarin code which gives a similar effect to using requestChildFocus() but with smooth scrolling:

    private static void ScrollToView(View ArgTarget) {
        var CurParent = ArgTarget.Parent;
    
        while (CurParent != null) {
          var ScrollArea = CurParent as ScrollView;
    
          if (ScrollArea != null) {
            var ViewRect = new Rect();
            ArgTarget.GetDrawingRect(ViewRect);
    
            ScrollArea.OffsetDescendantRectToMyCoords(ArgTarget, ViewRect);
            ScrollArea.SmoothScrollTo(ViewRect.Left, ViewRect.Top);
    
            break;
          }
    
          CurParent = CurParent.Parent;
       }
    }
    

    The basic idea is to find the target view's containing ScrollView. Then get the target view's drawing rectangle, adjust its coordinates so they are understood by the ScrollView then ask the ScrollView to scroll to smooth-scroll to that position. The end effect is that the view you want to scroll to always ends up being fully visible near the top of the screen (you can play around with ViewRect.Top if you want to center the view on the screen instead).

    0 讨论(0)
  • 2020-12-04 14: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

    0 讨论(0)
  • 2020-12-04 14:43

    Kotlin: Try this, it works for me like charm !

    parentScrollView.post(object : Runnable {
            override fun run() {
                parentScrollView.smoothScrollTo(0, targetView.bottom)
            }
    
        })
    
    0 讨论(0)
提交回复
热议问题