HorizontalScrollView:自动滚动到添加新视图时结束?
我有一个包含LinearLayout的HorizontalScrollView。 在屏幕上,我有一个button,将在运行时将新的视图添加到LinearLayout,我想滚动视图滚动到列表的末尾添加一个新的视图时。
我几乎有它的工作 – 除了它总是滚动一个视图短的最后一个视图。 它似乎是滚动,而不是首先计算包含新视图。
在我的应用程序中,我使用了一个自定义的View对象,但是我做了一个使用ImageView并且具有相同症状的小型testing应用程序。 我尝试了各种东西像requestLayout()布局和ScrollView,我试图scrollTo(Integer.MAX_VALUE),它滚动到netherverse :)我违反了UI线程问题或什么?
- 干草堆
======
public class Main extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button b = (Button) findViewById(R.id.addButton); b.setOnClickListener(new AddListener()); add(); } private void add() { LinearLayout l = (LinearLayout) findViewById(R.id.list); HorizontalScrollView s = (HorizontalScrollView) findViewById(R.id.scroller); ImageView i = new ImageView(getApplicationContext()); i.setImageResource(android.R.drawable.btn_star_big_on); l.addView(i); s.fullScroll(HorizontalScrollView.FOCUS_RIGHT); } private class AddListener implements View.OnClickListener { @Override public void onClick(View v) { add(); } } }
布局XML:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <HorizontalScrollView android:id="@+id/scroller" android:layout_width="wrap_content" android:layout_height="wrap_content" android:scrollbarSize="50px"> <LinearLayout android:id="@+id/list" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="4px"/> </HorizontalScrollView> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center"> <Button android:id="@+id/addButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:paddingLeft="80px" android:paddingRight="80px" android:paddingTop="40px" android:paddingBottom="40px" android:text="Add"/> </LinearLayout> </LinearLayout>
我认为有一个时间问题。 添加视图时布局没有完成。 这是要求和做一段时间后。 在添加视图后立即调用fullScroll时,linearlayout的宽度没有机会展开。
尝试更换:
s.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
有:
s.postDelayed(new Runnable() { public void run() { s.fullScroll(HorizontalScrollView.FOCUS_RIGHT); } }, 100L);
短暂的延迟应该给系统足够的时间来解决。
PS直接在UI循环的当前迭代之后延迟滚动可能就足够了。 我没有testing过这个理论,但是如果这是正确的,那就足够了:
s.post(new Runnable() { public void run() { s.fullScroll(HorizontalScrollView.FOCUS_RIGHT); } });
我更喜欢这个,因为引入一个任意的延迟对我来说似乎很难(尽pipe这是我的build议)。
只是另一个消化,因为这个问题帮了我很多:)。
当视图完成其布局阶段后,您可以放置一个侦听器,在完成fullScroll之后,尽pipe您需要扩展该类。
我只是这样做,因为我想滚动到onCreate()之后的部分,以避免从起点闪烁到滚动点。
就像是:
public class PagerView extends HorizontalScrollView { private OnLayoutListener mListener; ///... private interface OnLayoutListener { void onLayout(); } public void fullScrollOnLayout(final int direction) { mListener = new OnLayoutListener() { @Override public void onLayout() { fullScroll(direction) mListener = null; } }; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if(mListener != null) mListener.onLayout(); } }
我同意@monxalo和@ granko87,更好的方法是用一个监听器,而不是假设布局将会完成,如果我们让任意的时间过去。
如果像我一样,你不需要使用一个自定义的HorizontalScrollView子类,你可以添加一个OnLayoutChangeListener来保持简单:
mTagsScroller.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View view, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { mTagsScroller.removeOnLayoutChangeListener(this); mTagsScroller.fullScroll(View.FOCUS_RIGHT); } });
使用View方法smoothScrollTo
postDelayed(new Runnable() { public void run() { scrollView.smoothScrollTo(newView.getLeft(), newView.getTop()); } }, 100L);
你需要放入一个可运行的,所以你给布局过程的时间来定位新的视图
这就是我所做的。
//Observe for a layout change ViewTreeObserver viewTreeObserver = yourLayout.getViewTreeObserver(); if (viewTreeObserver.isAlive()) { viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { yourHorizontalScrollView.fullScroll(HorizontalScrollView.FOCUS_RIGHT); } }); }
我认为最好的方法是由monxalo发布,因为你不知道要花多less时间才能完成布局。 我试了一下,它完美的作品。 唯一的区别是,我只添加了一行到我的自定义水平滚动视图:
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); this.fullScroll(HorizontalScrollView.FOCUS_RIGHT); }
使用下面的代码水平滚动视图{ 滚动到右侧 }
view.post(new Runnable() { @Override public void run() { ((HorizontalScrollView) Iview .findViewById(R.id.hr_scroll)) .fullScroll(HorizontalScrollView.FOCUS_RIGHT); } });