2011-01-18 26 views
44

LinearLayout içeren bir HorizontalScrollView var. Ekranda, çalışma zamanında LinearLayout'a yeni Görünümler ekleyecek bir Düğme var ve yeni bir Görünüm eklendiğinde kaydırma görünümünün listenin sonuna kaydırılmasını istiyorum.HorizontalScrollView: Yeni Görünümler eklendiğinde sona ermek için otomatik olarak kaydır?

Neredeyse çalışıyorum - bununla birlikte her zaman son görünümün bir görüntüsünü kaydırır. İlk bakışta, yeni görünümün dahil edilmesini hesaplamaksızın kayıyor gibi görünüyor.

Uygulamamda özel bir Görüntüleme nesnesi kullanıyorum, ancak ImageView kullanan ve aynı belirtiye sahip küçük bir deneme uygulaması yaptım. Layout ve ScrollView hem de requestLayout() gibi çeşitli şeyler denedim, ben scrollTo (Integer.MAX_VALUE) çalıştı ve netherverse :) kaydırdı Ben bir UI iş parçacığı sorunu veya bir şey ihlal ediyor muyum?

  • Rick

======

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

Düzen 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> 

cevap

113

Bir zamanlama sorunu olduğunu düşünüyorum. Görünüm eklendiğinde düzen yapılmaz. Kısa bir süre sonra istenir ve yapılır. Görünümü ekledikten hemen sonra fullScroll'u çağırdığınızda, doğrusal yayının genişliğinin genişletme şansı olmadı. değiştirilmesi

Dene: ile

s.fullScroll(HorizontalScrollView.FOCUS_RIGHT); 

:

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

kısa bir gecikme sistemi yerleşmek için yeterli zamanı vermelidir.

P.S. Kaydırma işlemini, UI döngüsünün geçerli yinelemesinden sonraya kadar ertelemek yeterli olabilir. Bu teoriyi test değil, ama doğru olmadığını, şu işlemleri yapmanız yeterli olacaktır:

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

Sevdiğim bu daha iyi (benim önerim olsa bile) keyfi bir gecikmeye yol bana hacky görünüyor çünkü.

+5

, çok teşekkürler, bu gün beni rahatsız eden! :) –

+0

Teşekkürler Ted hopp – praveenb

+1

+1 Bu bana yardımcı oldu :) –

12

Sadece bir başka sıkışıklık, çünkü bu soru bana çok yardımcı oldu :).

Sen görünümü bunun için sınıfını genişletmek gerekir Hintçe fullScroll do hemen sonra kendi düzenini aşaması bitmiş ve bir dinleyici koyabilirsiniz. ben sağ onCreate sonra bölümüne gidin istedim çünkü

Ben sadece bunu() noktasını kaydırmak için başlangıç ​​noktası oluşan titremeyi önlemek için.

şey gibi:

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(); 
    } 
} 
4

Sen yeni bir Görünüm konumlandırmak için düzen süreci için zaman vermek, böylece bir çalıştırılabilir koymak gerekir Görünüm yöntemi smoothScrollTo

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

kullanın

+0

Merhaba .. teşekkürler. Bu kod benim için çok faydalı .. çok teşekkürler. – RVG

1

Bence en iyi yaklaşım monxalo tarafından gönderilen mesajdır, çünkü plan yapılıncaya kadar ne kadar zaman alacağını bilemezsiniz. Denedim ve mükemmel çalışıyor.

view.post(new Runnable() { 
       @Override 
       public void run() { 
        ((HorizontalScrollView) Iview 
          .findViewById(R.id.hr_scroll)) 
          .fullScroll(HorizontalScrollView.FOCUS_RIGHT); 
       } 
      }); 
+0

Zamanın ilgili olduğunu düşünmüyorum. Sorun, UI iş parçacığı döngüsünün geçerli yinelemesinde kaydırma yapılmaması gerektiğidir. Mevcut yineleme tamamlandığında, görünüm hiyerarşisi güncel olmalı ve ortaya konmalıdır. –

2

Kullanımı: Tek fark benim özel yatay kaydırma görünümüne yalnızca bir satır ilave yani, .

//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); 
      } 
    }); 
    } 
3

Bu benim yaptığım budur yatay Scrollview {sağ için gelin} için kodunun altına

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

Ben @monxalo ve @ granko87 iyi bir yaklaşım yerine biz zaman geçmek bazı keyfi miktarda izin verirsek düzeni tamamlanmış olacaktır varsayılabilir bir dinleyici ile olduğunu kabul ediyorum. View hemen ViewGroup ilave edilmeyebilir

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); 
    } 
}); 
+0

Bu benim de ortaya koyduğum çözüm. Daha az kod, iş yaptı. –

+0

Bu, sorunun doğru cevabıdır. Herhangi bir rastgele süre beklemek saçmadır. Düzen motorunun işini yapmasını beklemek uygun olanıdır. – DrAL3X

0

çocuk:

durumda, benim gibi, sadece basit tutmak için bir OnLayoutChangeListener ekleyebileceğiniz bir özel HorizontalScrollView alt sınıfı kullanmak gerekmez . Bu nedenle, diğer bekleyen görevler tamamlandıktan sonra çalışacak olan Runnable'u göndermeniz gerekir. Yani View ekledikten sonra

kullanın: Tam olarak Ted did it

horizontalScrollView.post(new Runnable() { 
    @Override 
    public void run() { 
     horizontalScrollView.fullScroll(View.FOCUS_RIGHT); 
    } 
}); 
İlgili konular