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

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

上面的布局是dynamic创build的。 所以我不能有这里张贴的XML文件。 布局创build是完全dynamic的。 即使在线性布局中子视图的数量也可能有所不同。

所以,当我点击button,我需要滚动到一个特定的观点说,当我点击button,我需要滚动到线性布局4.我试着用scrollTo方法,但它滚动到scrollview的顶部。

请提供一些build议。

Solutions Collecting From Web of "滚动到滚动视图中的特定视图"

这应该做的伎俩:

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

公共无效RequestChildFocus(查看孩子,查看聚焦)

孩子 – 这个ViewParent想要关注的孩子。 这个视图将包含重点视图。 这不一定是真正关注的观点。

集中 – 是实际上有焦点的孩子的后裔的观点

如果我们需要滚动到的孩子不是一个直接的孩子,那么上面的解决scheme不起作用

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

 /** * 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 Accumalated 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); } 

尝试这个:

 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()在API Level 11以下不起作用,对于低于11的API Level,您可以用insideView.getY()replaceinsideView.getTop()

我想我已经find了更优雅和容易出错的解决scheme

ScrollView.requestChildRectangleOnScreen

没有涉及math,与其他提出的解决scheme相反,它将正确地处理上下滚动。

 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 } 

将它包装到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); } 

只是好的不是吗?

既然你可以知道你需要滚动的子代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()); 

有关scrollTo以及smoothScrollTo的更多信息

如果目标视图不是您的ScrollView的直接子对象,则可以使用以下解决scheme:

 public int findYPositionInView (View rootView, View targetView) { return findYPositionInView (rootView, targetView, 0); } // returns -1 if targetView not found private int findYPositionInView (View rootView, View targetView, int yCumulative) { if (rootView == targetView) return yCumulative; if (rootView instanceof ViewGroup) { ViewGroup parentView = (ViewGroup)rootView; for (int i = 0; i < parentView.getChildCount (); i++) { View child = parentView.getChildAt (i); int yChild = yCumulative + (int)child.getY (); int yNested = findYPositionInView (child, targetView, yChild); if (yNested != -1) return yNested; } } return -1; // not found } 

像这样使用它:

 int yScroll = findYPositionInView (scrollView, targetView); scrollView.scrollTo (0, yScroll); 

此外,如果你想设置重点,做到这一点:

 targetView.requestFocus (); 

而且,如果你想要键盘显示,请执行以下操作:

 if (targetView instanceof EditText) { targetView.post (new Runnable () { @Override public void run () { InputMethodManager imm = (InputMethodManager)context.getSystemService (Context.INPUT_METHOD_SERVICE); imm.showSoftInput (targetView, InputMethodManager.SHOW_FORCED); } }); } 

使用 :

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

尝试在您要滚动的视图上调用view.requestFocus()