有没有办法以编程方式将滚动视图滚动到特定的编辑文本?
我有一个很长的滚动视图活动。这是一个包含用户必须填写的各种字段的表单。我的表单中间有一个复选框,当用户选中它时,我想滚动到视图的特定部分。有没有办法以编程方式滚动到 EditText 对象(或任何其他视图对象)?
另外,我知道使用 X 和 Y 坐标是可能的,但我想避免这样做,因为表单可能会因用户而异。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(27)
如果你想将视图滚动到滚动视图的中心,Sherif elKhatib 的答案可以大大改进。这种可重用的方法将视图平滑滚动到 HorizontalScrollView 的可见中心。
对于垂直
ScrollView
使用The answer of Sherif elKhatib can be greatly improved, if you want to scroll the view to the center of the scroll view. This reusable method smooth scrolls the view to the visible center of a HorizontalScrollView.
For a vertical
ScrollView
use这对我来说效果很好:
child - 需要焦点的 ViewParent 的子级。该视图将包含焦点视图。它不一定是真正具有焦点的视图。
focused - 真正具有焦点的子视图的后代
This works well for me :
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
在我看来,滚动到给定矩形的最佳方法是通过
View.requestRectangleOnScreen(矩形,布尔值)
。您应该在要滚动到的View
上调用它,并传递一个您希望在屏幕上可见的本地矩形。第二个参数应该为false
来平滑滚动,为true
来立即滚动。In my opinion the best way to scroll to a given rectangle is via
View.requestRectangleOnScreen(Rect, Boolean)
. You should call it on aView
you want to scroll to and pass a local rectangle you want to be visible on the screen. The second parameter should befalse
for smooth scrolling andtrue
for immediate scrolling.我根据 WarrenFaith 的答案制作了一个小型实用方法,此代码还考虑了该视图是否已在滚动视图中可见,无需滚动。
I made a small utility method based on Answer from WarrenFaith, this code also takes in account if that view is already visible in the scrollview, no need for scroll.
您应该使您的
TextView
请求成为焦点:You should make your
TextView
request focus:另一种变体是:
或者您可以使用
post()
方法。Another varition would be:
or you can use the
post()
method.我的 EditText 嵌套在 ScrollView 中的几层,ScrollView 本身不是布局的根视图。因为 getTop() 和 getBottom() 似乎报告其包含视图内的坐标,所以我让它通过迭代 EditText 的父级来计算从 ScrollView 顶部到 EditText 顶部的距离。
My EditText was nested several layers inside my ScrollView, which itself isn't the layout's root view. Because getTop() and getBottom() were seeming to report the coordinates within it's containing view, I had it compute the distance from the top of the ScrollView to the top of the EditText by iterating through the parents of the EditText.
如果 ScrollView 是 ChildView 的直接父级,则上述答案将正常工作。如果您的 ChildView 被包装在 ScrollView 中的另一个 ViewGroup 中,则会导致意外行为,因为 View.getTop() 获取相对于其父级的位置。在这种情况下,您需要执行以下操作:
The above answers will work fine if the ScrollView is the direct parent of the ChildView. If your ChildView is being wrapped in another ViewGroup in the ScrollView, it will cause unexpected behavior because the View.getTop() get the position relative to its parent. In such case, you need to implement this:
我知道这可能为时已晚,无法得到更好的答案,但理想的完美解决方案必须是像定位器这样的系统。我的意思是,当系统对编辑器字段进行定位时,它会将字段放置在键盘上方,因此按照 UI/UX 规则,它是完美的。
下面的代码使的是Android方式顺利定位。首先,我们将当前滚动点作为参考点。第二件事是找到编辑器的最佳定位滚动点,为此我们滚动到顶部,然后请求编辑器字段以使 ScrollView 组件进行最佳定位。嘎查!我们已经了解了最佳位置。现在,我们要做的就是从上一个点平滑滚动到我们新找到的点。如果您愿意,可以仅使用 scrollTo 而不是 smoothScrollTo 来省略平滑滚动。
注意:主容器ScrollView是一个名为scrollViewSignup的成员字段,因为我的示例是一个注册屏幕,您可能会明白很多。
如果您想将此块用于所有 EditText 实例,并快速将其与您的屏幕代码集成。您可以简单地制作一个如下所示的遍历器。为此,我将主 OnFocusChangeListener 创建为一个名为 focusChangeListenerToScrollEditor 的成员字段,并在 onCreate 期间调用它,如下所示。
其方法实现如下。
因此,我们在这里所做的就是让所有 EditText 实例子级调用焦点处的侦听器。
为了达到这个解决方案,我检查了这里的所有解决方案,并生成了一个新的解决方案以获得更好的 UI/UX 结果。
I know this may be too late for a better answer but a desired perfect solution must be a system like positioner. I mean, when system makes a positioning for an Editor field it places the field just up to the keyboard, so as UI/UX rules it is perfect.
What below code makes is the Android way positioning smoothly. First of all we keep the current scroll point as a reference point. Second thing is to find the best positioning scroll point for an editor, to do this we scroll to top, and then request the editor fields to make the ScrollView component to do the best positioning. Gatcha! We've learned the best position. Now, what we'll do is scroll smoothly from the previous point to the point we've found newly. If you want you may omit smooth scrolling by using scrollTo instead of smoothScrollTo only.
NOTE: The main container ScrollView is a member field named scrollViewSignup, because my example was a signup screen, as you may figure out a lot.
If you want to use this block for all EditText instances, and quickly integrate it with your screen code. You can simply make a traverser like below. To do this, I've made the main OnFocusChangeListener a member field named focusChangeListenerToScrollEditor, and call it during onCreate as below.
And the method implementation is as below.
So, what we've done here is making all EditText instance children to call the listener at focus.
To reach this solution, I've checked it out all the solutions here, and generated a new solution for better UI/UX result.
yourScrollView.smoothScrollTo(0, yourEditText.getTop());
就这么做吧;)
yourScrollView.smoothScrollTo(0, yourEditText.getTop());
Just Do It ;)
从我的实际项目中回答。
Answering from my practical project.
我想我已经找到了更优雅且不易出错的解决方案
不涉及数学,并且与其他建议的解决方案相反,它将正确处理向上和向下滚动。
最好将其包装到
postDelayed
中以使其更加可靠,以防当前ScrollView
发生更改I think I have found more elegant and less error prone solution using
There is no math involved, and contrary to other proposed solutions, it will handle correctly scrolling both up and down.
It is a good idea to wrap it into
postDelayed
to make it more reliable, in case theScrollView
is being changed at the moment参考:https://stackoverflow.com/a/6438240/2624806
以下效果更好。
reference : https://stackoverflow.com/a/6438240/2624806
Following worked far better.
检查 Android 源代码,您可以发现
ScrollView
已经有一个成员函数 -scrollToChild(View)
- 完全按照请求执行。不幸的是,由于某些不明原因,该函数被标记为private
。基于该函数,我编写了以下函数,该函数找到指定为参数的View
上方的第一个ScrollView
并滚动它,以便它在ScrollView 中可见:
Examining Android source code, you can find that there already is a member function of
ScrollView
–scrollToChild(View)
– that does exactly what is requested. Unfortunatelly, this function is for some obscure reason markedprivate
. Based on that function I've written following function that finds the firstScrollView
above theView
specified as a parameter and scrolls it so that it becomes visible within theScrollView
:我的解决方案是:
My solution is:
垂直滚动,适合表单。答案基于 Ahmadalibaloch 水平卷轴。
Vertical scroll, good for forms. Answer is based on Ahmadalibaloch horizontal scroll.
您可以像这样使用
ObjectAnimator
:You can use
ObjectAnimator
like this:根据 Sherif 的回答,以下内容最适合我的用例。值得注意的变化是用
getTop()
代替getBottom()
和smoothScrollTo()
代替scrollTo()
。Based on Sherif's answer, the following worked best for my use case. Notable changes are
getTop()
instead ofgetBottom()
andsmoothScrollTo()
instead ofscrollTo()
.将 postDelayed 添加到视图中,以便 getTop() 不会返回 0。
还要确保该视图是scrollView 的直接子级,否则 getTop() 会为零。示例:嵌入 TextInputLayout 中的 edittext 的 getTop() 将返回 0。因此,在这种情况下,我们必须计算 ScrollView 的直接子级 TextInputLayout 的 getTop() 。
Add postDelayed to the view so that getTop() does not return 0.
Also make sure the view is a direct child of scrollView, otherwise you would get getTop() as zero. Example: getTop() of edittext which is embedded inside TextInputLayout would return 0. So in this case, we have to compute getTop() of TextInputLayout which is a direct child of ScrollView.
就我而言,这不是
EditText
,而是googleMap
。像这样就成功了。
In my case, that's not
EditText
, that'sgoogleMap
.And it works successfully like this.
问:有没有办法以编程方式将滚动视图滚动到特定的编辑文本?
Ans:嵌套滚动视图在recyclerview最后位置添加了记录数据。
有吗一种以编程方式将滚动视图滚动到特定编辑文本的方法?
Que:Is there a way to programmatically scroll a scroll view to a specific edittext?
Ans:Nested scroll view in recyclerview last position added record data.
Is there a way to programmatically scroll a scroll view to a specific edit text?
以下是我正在使用的内容:
这获取显示视图底部所需的滚动量,包括该视图底部的任何边距。
The following is what I'm using:
This gets the scroll amount necessary to show the bottom of the view, including any margin on the bottom of that view.
如果您想在打开软键盘时滚动到某个视图,那么可能会有点棘手。
到目前为止,我得到的最佳解决方案是结合使用插入回调和 requestRectangleOnScreen 方法。
首先,您需要设置插入回调:
我们在根视图上设置回调以确保我们被调用。插图可能会在我们的相关视图收到它们之前被消耗,因此我们必须在这里做额外的工作。
现在这几乎很容易:
您可以摆脱焦点检查。它的作用是限制对
requestRectangleOnScreen
的调用次数。我使用post
在可滚动父计划滚动到焦点视图后运行操作。If you want to scroll to a view when a soft keyboard is opened, then it might get a bit tricky.
The best solution I've got so far is to use a combination of inset callbacks and
requestRectangleOnScreen
method.First, you need to setup inset callbacks:
We are setting a callback on a root view to make sure we get called. Insets could be consumed before our view in question received them, so we have to do additional work here.
Now it's almost easy:
You can get rid of a focus check. It's there to limit number of calls to
requestRectangleOnScreen
. I usepost
to run an action after scrollable parent scheduled scroll to a focused view.如果有人正在寻找 Kotlin 版本,您可以使用扩展函数来完成此操作。
有一个小回调可以让您在滚动后执行某些操作。
If anybody is looking for a Kotlin version you can do this with an extension function
There is a little callback that lets you do something after the scroll.
如果
scrlMain
是您的NestedScrollView
,则使用以下内容:If
scrlMain
is yourNestedScrollView
, then use the following:这是另一个更好的高效滚动版本:
用于滚动到滚动视图(水平)中添加的视图特定位置的 kotlin 代码
以进行垂直滚动,只需将
targetView.left
更改为 JAVA 的targetView.top
这里是示例代码:
here is another better version for efficient scrolling:
kotlin code to scroll to particular position of view added in scrollview(horizontal)
for vertical scroll just change
targetView.left
totargetView.top
for JAVA here is a sample code: