HorizontalScrollView: авто-прокрутка до конца при добавлении новых просмотров?

У меня есть HorizontalScrollView, содержащий LinearLayout. На экране у меня есть кнопка, которая добавит новые виды в LinearLayout во время выполнения, и я хотел бы, чтобы прокрутка просматривала прокрутку до конца списка при добавлении нового представления.

Я почти работаю – за исключением того, что он всегда прокручивает один вид до последнего представления. Кажется, что это прокрутка без предварительного расчета включения нового представления.

В моем приложении я использую пользовательский объект View, но я сделал небольшое тестовое приложение, которое использует ImageView и имеет тот же самый симптом. Я пробовал различные вещи, такие как requestLayout () как в Layout, так и в ScrollView, я пробовал scrollTo (Integer.MAX_VALUE), и он прокручивался в netherverse 🙂 Я нарушаю проблему с потоком пользовательского интерфейса или что-то еще?

  • стог

======

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> 

Solutions Collecting From Web of "HorizontalScrollView: авто-прокрутка до конца при добавлении новых просмотров?"

Я думаю, что есть проблема времени. Макет не выполняется при добавлении представления. Он запрашивается и выполняется через некоторое время. Когда вы вызываете fullScroll сразу после добавления представления, ширина linearlayout не имеет возможности расширяться.

Попробуйте заменить:

 s.fullScroll(HorizontalScrollView.FOCUS_RIGHT); 

с:

 s.postDelayed(new Runnable() { public void run() { s.fullScroll(HorizontalScrollView.FOCUS_RIGHT); } }, 100L); 

Небольшая задержка должна дать системе достаточно времени для ее урегулирования.

PS Возможно, достаточно просто отложить прокрутку до текущей итерации петли пользовательского интерфейса. Я не тестировал эту теорию, но если это правильно, достаточно было бы сделать следующее:

 s.post(new Runnable() { public void run() { s.fullScroll(HorizontalScrollView.FOCUS_RIGHT); } }); 

Мне это нравится лучше, потому что введение произвольной задержки кажется мне взломанным (хотя это было мое предложение).

Еще одно утверждение, так как этот вопрос мне очень помог :).

Вы можете поместить слушателя, когда представление закончило свою фазу макета, и сразу же после выполнения fullScroll вы должны расширить класс для этого.

Я сделал это только потому, что мне захотелось перейти к разделу сразу после 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); } }); 

Использовать метод просмотра smoothScrollTo

 postDelayed(new Runnable() { public void run() { scrollView.smoothScrollTo(newView.getLeft(), newView.getTop()); } }, 100L); 

Вам нужно запустить runnable, чтобы вы выделили время для компоновки, чтобы разместить новый вид

Это то, что я сделал.

 //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, потому что вы не можете знать, сколько времени потребуется, пока макет не будет выполнен. Я попробовал, и он отлично работает. Единственное отличие состоит в том, что я добавил только одну строку в свой собственный горизонтальный вид прокрутки:

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