有没有办法编程滚动滚动视图到特定的编辑文本?
我有一个很长的活动与滚动视图。 这是一个用户必须填写的各种领域的表单。我有一个checkbox,在用户检查时,我想滚动到视图的特定部分。 有没有办法以编程方式滚动到EditText对象(或任何其他视图对象)?
此外,我知道这是可能的使用X和Y的坐标,但我想避免这样做,因为forms可能会改变从用户到用户。
private final void focusOnView(){ your_scrollview.post(new Runnable() { @Override public void run() { your_scrollview.scrollTo(0, your_EditBox.getBottom()); } }); }
如果要将视图滚动到滚动视图的中心 ,Sherif elKhatib的答案可以大大改善。 这个可重用的方法平滑地将视图滚动到HorizontalScrollView的可见中心。
private final void focusOnView(final HorizontalScrollView scroll, final View view) { new Handler().post(new Runnable() { @Override public void run() { int vLeft = view.getLeft(); int vRight = view.getRight(); int sWidth = scroll.getWidth(); scroll.smoothScrollTo(((vLeft + vRight - sWidth) / 2), 0); } }); }
垂直ScrollView
更改smoothScroll
input的x
和y
位置。 并使用view.getTop()
而不是view.getLeft()
和view.getBottom()
而不是v.getRight()
。
🙂
这适用于我:
targetView.getParent().requestChildFocus(targetView,targetView);
公共无效RequestChildFocus(查看孩子,查看聚焦)
孩子 – 这个ViewParent想要关注的孩子。 这个视图将包含重点视图。 这不一定是真正关注的观点。
集中 – 是实际上有焦点的孩子的后裔的观点
在我看来,滚动到给定矩形的最佳方式是通过View.requestRectangleOnScreen(Rect, Boolean)
。 你应该在你想要滚动的View
上调用它,并传递一个你想在屏幕上可见的矩形。 第二个参数对于平滑滚动应该是false
,对于即时滚动应该是false
。
final Rect rect = new Rect(0, 0, view.getWidth(), view.getHeight()); view.requestRectangleOnScreen(rect, false);
你应该让你的TextView
请求焦点:
mTextView.requestFocus();
我做了一个基于来自WarrenFaith的Answer的小实用方法,如果该视图在滚动视图中已经可见,则该代码也考虑在内,不需要滚动。
public static void scrollToView(final ScrollView scrollView, final View view) { // View needs a focus view.requestFocus(); // Determine if scroll needs to happen final Rect scrollBounds = new Rect(); scrollView.getHitRect(scrollBounds); if (!view.getLocalVisibleRect(scrollBounds)) { new Handler().post(new Runnable() { @Override public void run() { scrollView.smoothScrollTo(0, view.getBottom()); } }); } }
我的EditText在我的ScrollView中嵌套了几层,它本身不是布局的根视图。 因为getTop()和getBottom()似乎要报告其包含视图中的坐标,我已经通过迭代EditText的父项来计算从ScrollView的顶部到EditText的顶部的距离。
// Scroll the view so that the touched editText is near the top of the scroll view new Thread(new Runnable() { @Override public void run () { // Make it feel like a two step process Utils.sleep(333); // Determine where to set the scroll-to to by measuring the distance from the top of the scroll view // to the control to focus on by summing the "top" position of each view in the hierarchy. int yDistanceToControlsView = 0; View parentView = (View) m_editTextControl.getParent(); while (true) { if (parentView.equals(scrollView)) { break; } yDistanceToControlsView += parentView.getTop(); parentView = (View) parentView.getParent(); } // Compute the final position value for the top and bottom of the control in the scroll view. final int topInScrollView = yDistanceToControlsView + m_editTextControl.getTop(); final int bottomInScrollView = yDistanceToControlsView + m_editTextControl.getBottom(); // Post the scroll action to happen on the scrollView with the UI thread. scrollView.post(new Runnable() { @Override public void run() { int height =m_editTextControl.getHeight(); scrollView.smoothScrollTo(0, ((topInScrollView + bottomInScrollView) / 2) - height); m_editTextControl.requestFocus(); } }); } }).start();
另一个变化是:
scrollView.postDelayed(new Runnable() { @Override public void run() { scrollView.smoothScrollTo(0, img_transparent.getTop()); } }, 2000);
或者你可以使用post()
方法。
参考: https : //stackoverflow.com/a/6438240/2624806
以下工作更好。
mObservableScrollView.post(new Runnable() { public void run() { mObservableScrollView.fullScroll([View_FOCUS][1]); } });
我想我已经find了更优雅和容易出错的解决scheme
ScrollView.requestChildRectangleOnScreen
没有涉及math,与其他提出的解决scheme相反,它将正确地处理上下滚动。
/** * Will scroll the {@code scrollView} to make {@code viewToScroll} visible * * @param scrollView parent of {@code scrollableContent} * @param scrollableContent a child of {@code scrollView} whitch holds the scrollable content (fills the viewport). * @param viewToScroll a child of {@code scrollableContent} to whitch will scroll the the {@code scrollView} */ void scrollToView(ScrollView scrollView, ViewGroup scrollableContent, View viewToScroll) { Rect viewToScrollRect = new Rect(); //coordinates to scroll to viewToScroll.getHitRect(viewToScrollRect); //fills viewToScrollRect with coordinates of viewToScroll relative to its parent (LinearLayout) scrollView.requestChildRectangleOnScreen(scrollableContent, viewToScrollRect, false); //ScrollView will make sure, the given viewToScrollRect is visible }
将它包装到postDelayed
是一个好主意,以使其更可靠,以防ScrollView
在此刻被更改
/** * Will scroll the {@code scrollView} to make {@code viewToScroll} visible * * @param scrollView parent of {@code scrollableContent} * @param scrollableContent a child of {@code scrollView} whitch holds the scrollable content (fills the viewport). * @param viewToScroll a child of {@code scrollableContent} to whitch will scroll the the {@code scrollView} */ private void scrollToView(final ScrollView scrollView, final ViewGroup scrollableContent, final View viewToScroll) { long delay = 100; //delay to let finish with possible modifications to ScrollView scrollView.postDelayed(new Runnable() { public void run() { Rect viewToScrollRect = new Rect(); //coordinates to scroll to viewToScroll.getHitRect(viewToScrollRect); //fills viewToScrollRect with coordinates of viewToScroll relative to its parent (LinearLayout) scrollView.requestChildRectangleOnScreen(scrollableContent, viewToScrollRect, false); //ScrollView will make sure, the given viewToScrollRect is visible } }, delay); }
检查Android源代码,你可以发现,已经有一个ScrollView
的成员函数 – scrollToChild(View)
– 这正是所要求的。 不幸的是,这个function是由于一些隐晦的原因被标记为private
。 基于这个函数我写了下面的函数,它查找指定为参数的上方的第一个ScrollView
,并滚动它,使其在ScrollView
可见:
private void make_visible(View view) { int vt = view.getTop(); int vb = view.getBottom(); View v = view; for(;;) { ViewParent vp = v.getParent(); if(vp == null || !(vp instanceof ViewGroup)) break; ViewGroup parent = (ViewGroup)vp; if(parent instanceof ScrollView) { ScrollView sv = (ScrollView)parent; // Code based on ScrollView.computeScrollDeltaToGetChildRectOnScreen(Rect rect) (Android v5.1.1): int height = sv.getHeight(); int screenTop = sv.getScrollY(); int screenBottom = screenTop + height; int fadingEdge = sv.getVerticalFadingEdgeLength(); // leave room for top fading edge as long as rect isn't at very top if(vt > 0) screenTop += fadingEdge; // leave room for bottom fading edge as long as rect isn't at very bottom if(vb < sv.getChildAt(0).getHeight()) screenBottom -= fadingEdge; int scrollYDelta = 0; if(vb > screenBottom && vt > screenTop) { // need to move down to get it in view: move down just enough so // that the entire rectangle is in view (or at least the first // screen size chunk). if(vb-vt > height) // just enough to get screen size chunk on scrollYDelta += (vt - screenTop); else // get entire rect at bottom of screen scrollYDelta += (vb - screenBottom); // make sure we aren't scrolling beyond the end of our content int bottom = sv.getChildAt(0).getBottom(); int distanceToBottom = bottom - screenBottom; scrollYDelta = Math.min(scrollYDelta, distanceToBottom); } else if(vt < screenTop && vb < screenBottom) { // need to move up to get it in view: move up just enough so that // entire rectangle is in view (or at least the first screen // size chunk of it). if(vb-vt > height) // screen size chunk scrollYDelta -= (screenBottom - vb); else // entire rect at top scrollYDelta -= (screenTop - vt); // make sure we aren't scrolling any further than the top our content scrollYDelta = Math.max(scrollYDelta, -sv.getScrollY()); } sv.smoothScrollBy(0, scrollYDelta); break; } // Transform coordinates to parent: int dy = parent.getTop()-parent.getScrollY(); vt += dy; vb += dy; v = parent; } }
在我的情况下,这不是EditText
,这是googleMap
。 它可以像这样成功
private final void focusCenterOnView(final ScrollView scroll, final View view) { new Handler().post(new Runnable() { @Override public void run() { int centreX=(int) (view.getX() + view.getWidth() / 2); int centreY= (int) (view.getY() + view.getHeight() / 2); scrollView.smoothScrollBy(centreX, centreY); } }); }
阙:有没有办法编程滚动滚动视图到一个特定的编辑文本?
Ans:recyclerview上一个位置的嵌套滚动视图添加了logging数据。
adapter.notifyDataSetChanged(); nested_scroll.setScrollY(more Detail Recycler.getBottom());
有没有办法编程滚动滚动视图到特定的编辑文本?
我的解决scheme是:
int[] spinnerLocation = {0,0}; spinner.getLocationOnScreen(spinnerLocation); int[] scrollLocation = {0, 0}; scrollView.getLocationInWindow(scrollLocation); int y = scrollView.getScrollY(); scrollView.smoothScrollTo(0, y + spinnerLocation[1] - scrollLocation[1]);
以下是我正在使用的:
int amountToScroll = viewToShow.getBottom() - scrollView.getHeight() + ((LinearLayout.LayoutParams) viewToShow.getLayoutParams()).bottomMargin; // Check to see if scrolling is necessary to show the view if (amountToScroll > 0){ scrollView.smoothScrollTo(0, amountToScroll); }
这将获得显示视图底部所需的滚动量,包括该视图底部的任何边距。