我有一个非常长的带有滚动视图的活动。这是一个表单,用户必须填写各种字段。我在表单中间有一个复选框,当用户选中它时,我想要滚动到视图中的特定部分。是否有任何方法可以通过程序滚动到EditText对象(或任何其他视图对象)?
此外,我知道可以使用X和Y坐标来实现这一点,但我希望避免这样做,因为表单可能因用户而异。
我有一个非常长的带有滚动视图的活动。这是一个表单,用户必须填写各种字段。我在表单中间有一个复选框,当用户选中它时,我想要滚动到视图中的特定部分。是否有任何方法可以通过程序滚动到EditText对象(或任何其他视图对象)?
此外,我知道可以使用X和Y坐标来实现这一点,但我希望避免这样做,因为表单可能因用户而异。
private final void focusOnView(){
yourScrollView.post(new Runnable() {
@Override
public void run() {
yourScrollView.scrollTo(0, yourEditText.getBottom());
}
});
}
your_scrollview.post(...
- Sherif elKhatibgetBottom()
而不是 getTop()
? - Vadim KotovSherif 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
,请使用
...
int vTop = view.getTop();
int vBottom = view.getBottom();
int sHeight = scroll.getBottom();
scroll.smoothScrollTo(0, ((vTop + vBottom - sHeight) / 2));
...
这对我很有效:
targetView.getParent().requestChildFocus(targetView,targetView);
public void RequestChildFocus (View child, View focused)
child - 请求获取焦点的该ViewParent的子视图。该视图将包含具有焦点的视图,但不一定是实际具有焦点的视图。
focused - 子视图child中实际具有焦点的视图。
在我看来,滚动到指定矩形的最佳方法是通过View.requestRectangleOnScreen(Rect, Boolean)
。您应该在要滚动到的 View
上调用它,并传递一个本地矩形,您希望在屏幕上可见。第二个参数应为false
以进行平稳滚动,而应为true
以进行即时滚动。
final Rect rect = new Rect(0, 0, view.getWidth(), view.getHeight());
view.requestRectangleOnScreen(rect, false);
scrollview.smoothScrollTo
将无法工作。(在 Android 模拟器上尝试,使用的 SDK 版本是 26)。 - Sonynew Handler().post()
包装吗? - Johnny Fivepublic 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());
}
});
}
}
scrollBounds
应该是scrollView.getHitRect
方法的参数。 - Vijay C你需要让你的TextView
请求获取焦点:
mTextView.requestFocus();
scrollView.postDelayed(new Runnable()
{
@Override
public void run()
{
scrollView.smoothScrollTo(0, img_transparent.getTop());
}
}, 200);
post()
方法。我的EditText嵌套在ScrollView中的几层,而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();
public static void scrollToInvalidInputView(ScrollView scrollView, View view) {
int vTop = view.getTop();
while (!(view.getParent() instanceof ScrollView)) {
view = (View) view.getParent();
vTop += view.getTop();
}
final int scrollPosition = vTop;
new Handler().post(() -> scrollView.smoothScrollTo(0, scrollPosition));
}
我知道现在回答可能有点晚了,但理想的完美解决方案必须是像定位器一样的系统。我的意思是当系统为编辑器字段进行定位时,它将字段放置在键盘的正上方,因此根据UI / UX规则,这是完美的。
以下代码实现的是Android平台的平滑定位方法。首先,我们将当前滚动点作为参考点。第二件事是找到编辑器最佳定位滚动点,为此,我们先向上滚动,然后请求编辑器字段使ScrollView组件做出最佳定位。咔嚓!我们学到了最佳位置。现在,我们要做的是从以前的点平滑地滚动到我们新找到的点。如果您愿意,您可以只使用scrollTo而不是smoothScrollTo来省略平滑滚动。
注意:主容器ScrollView是名为scrollViewSignup的成员字段,因为我的示例是一个注册屏幕,你可能已经想象到了很多。
view.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(final View view, boolean b) {
if (b) {
scrollViewSignup.post(new Runnable() {
@Override
public void run() {
int scrollY = scrollViewSignup.getScrollY();
scrollViewSignup.scrollTo(0, 0);
final Rect rect = new Rect(0, 0, view.getWidth(), view.getHeight());
view.requestRectangleOnScreen(rect, true);
int new_scrollY = scrollViewSignup.getScrollY();
scrollViewSignup.scrollTo(0, scrollY);
scrollViewSignup.smoothScrollTo(0, new_scrollY);
}
});
}
}
});
如果你想将这个块用于所有EditText实例,并快速集成到你的屏幕代码中,你可以像下面这样简单地创建一个遍历器。为此,我已经将主要的OnFocusChangeListener命名为focusChangeListenerToScrollEditor成为成员字段,并在onCreate期间调用它。
traverseEditTextChildren(scrollViewSignup, focusChangeListenerToScrollEditor);
以下是该方法的实现。
private void traverseEditTextChildren(ViewGroup viewGroup, View.OnFocusChangeListener focusChangeListenerToScrollEditor) {
int childCount = viewGroup.getChildCount();
for (int i = 0; i < childCount; i++) {
View view = viewGroup.getChildAt(i);
if (view instanceof EditText)
{
((EditText) view).setOnFocusChangeListener(focusChangeListenerToScrollEditor);
}
else if (view instanceof ViewGroup)
{
traverseEditTextChildren((ViewGroup) view, focusChangeListenerToScrollEditor);
}
}
}
mEditView.getTop()
。 - nebkat