2010-01-26 42 views
7

Liste görünümümdeki bir satırın (FrameLayout içinde bulunan) ne zaman kaydırıldığını algılayabilmem için bazı hareket algılama kodları uygulayabildim.Liste görünümünde satırın konum (konum) nasıl alınacağı

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 
    if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { 
     int itemId = MainActivity.this.getListView().pointToPosition((int) e1.getX(),(int) e1.getY()); 
     Offer order = (Offer)MainActivity.this.getListView().getAdapter().getItem(itemId); 
     View v = MainActivity.this.getListView().getChildAt(itemId); 
    } 
} 

Ben o satırın bağlam duyarlı seçenekler kümesi ile almayanlar sıranın üstünden bir görünümünü görüntülemek istiyorum.

v.getTop() 
v.getBottom() 

dönüş doğru değerler görünümü kaydırıldığını önce sadece:

Sorunlarım aşağıdaki yöntemler olmasıdır. Muhtemelen kaydırma pozisyonlarını kullanarak ofsetleri hesaplamak için bazı hesaplamalar yapabilirdim ama aynı zamanda, ekranda görünecek bir satırı kaydırdığımda sadece değerleri aldığımı fark ettim. Listeyi aşağı kaydırır ve ardından bir satırı (orijinal olarak ekran dışı olmayan) kaydırırsam, bu yöntemler boş değerleri döndürür.

Aşağıdaki yöntemler aynı sorundan muzdarip görünüyor

...

v.getLocationOnScreen(loc) 
v.getLocationInWindow(loc) 

Sonuçta, ben görünür liste görünümü üst ve almayanlar edilmiştir sıranın arasındaki mesafeyi bulmak için arıyorum. Daha sonra ana FrameLayout'a uygun yükseklik yastığına bir görünüm eklemek için bu mesafeyi kullanacağım (böylece kaydırılan satırı kaplayacak şekilde).

Herhangi bir yardım çok takdir!

cevap

17

ListView öğelerini, bağdaştırıcıdaki konumuna veya ekranda görünür bir yere göre iki farklı şekilde dizinleme yolu vardır. Bir öğe her zaman adaptörde aynı konumda olacaktır (listeyi değiştirmediğiniz sürece). View.getChildAt() 'ın içine indeks, ekranda görünenlere bağlı olarak değişecektir.

pointToPosition tarafından döndürülen konum, bağdaştırıcı içindeki konumdur. Fiziksel görünümü almak istiyorsanız, görünüm kaydırılmışsa, hesaba katılmanız gerekir. Bunu deneyin:

int adapterIndex = MainActivity.this.getListView().pointToPosition((int) e1.getX(),(int) e1.getY()); 
int firstViewItemIndex = MainActivity.this.getListView().getFirstVisiblePosition(); 
int viewIndex = adapterIndex - firstViewItemIndex; 
View v = MainActivity.this.getListView().getChildAt(viewIndex); 
+0

Cevabınız için teşekkür ederiz. Aslında, görünüm nesnelerini izlemiyorum. Çalışma zamanında, hızlıca kaydırıldığında satırdan bekletiyorum. Ardından, ekrandaki çağrıları denemek ve bulmak için yukarıdaki çağrıları yapıyorum. Satırı değiştirmiyorum sadece sıranın üst kısmındaki bir görünümü görüntülemek istiyorum. Daha sonra liste tekrar kaydırılır çekilmez yeni görünümü kaldıran bir kaydırma dinleyicim var. Özelliğin bir gösterimi, iPhone için tweetie 2'nin bu tanıtımında görülebilir: http://www.youtube.com/watch?v=Vxjj3F5MCpQ#t=1m12s – Damian

+0

Dinamik olarak bekletme şeklinizi ayrıntılı olarak açıklayabilir misiniz? Çalışma zamanı satırında, ne zaman kaydırılır? –

+0

ListView'de GestureDetector ve GestureListener'ı kullanma. Yukarıdaki kod snippet'ini, bir kullanıcı listesindeki parmaklarını kaydırdığında çağrılan onFling yöntemini (ve params) içerecek şekilde güncelledim. Bazı basit matematikler kullanıcının soldan sağa doğru kaydırdığını kontrol etmek için kullanılır, daha sonra tokatın hangi sıranın karşılık geldiğini bulmak için pointToPosition kullanılır. – Damian

1

Bunu çözdüm ama biraz kesmek gibi geliyor ve muhtemelen en verimli uygulama değil. Elbette, Android API'larını kullanarak bunu yapmanın daha temiz bir yolu olmalı? Aşağıdaki kodda

, ben yapılan

tüm değişiklikleri (listeyi kaydırırken bu geri dönüşümlü olduğundan dolayı) hangi satırların tutan ekran görünümlerinde izlemek için benim ArrayAdaptor bir HashMap eklemiş orijinal adaptörüm aşağıda açıklanmıştır.

class RestaurantAdapter extends ArrayAdapter<Offer> { 
      Map hash = null; //HashMap to keep track of rowId and on screen View 

      RestaurantAdapter() { 
       super(MainActivity.this, android.R.layout.simple_list_item_1, model); 
       hash = new HashMap(); //instantiate HashMap in constructor 
      } 

      //method to return correct View on screen for row id 
      public View getViewOnScreen(int rowId) { 
       return (View)hash.get(rowId); 
      } 

      public View getView(int position, View convertView, 
                ViewGroup parent) { 
       View row=convertView; 
       hash.put(position, convertView); // add/update view for row position as it is recycled 

       RestaurantWrapper wrapper=null; 

       if (row==null) {              
        LayoutInflater inflater=getLayoutInflater(); 

        row=inflater.inflate(R.layout.row, parent, false); 
        wrapper=new RestaurantWrapper(row); 
        row.setTag(wrapper); 
       } 
       else { 
        wrapper=(RestaurantWrapper)row.getTag(); 
       } 

       wrapper.populateFrom(model.get(position)); 

       return(row); 
      } 


     } 
+0

Bu çözümü denedim ve benim için çalışmadı. Döndürülmüş görünümü değiştiremedim. Neyse, getChildAt kullanarak çalışma yaptım listede benim durumumda çalıştı. Bu yöntemi kullanarak neden döndürülen görünümü değiştiremediğimi bilmiyorum. – Andy

+0

Aslında benim için işe yaramadı aynı sebepten dolayı benim için işe yaramadıChildAt, bu yüzden bu sayfadaki diğer cevap kullanarak bitti ve işe yaradı. – Andy

1

Bu, hangi satıra dokunulduğunu saptamayı bulmamın en iyi yoludur.

  Rect rect = new Rect(); 
      int childCount = mListView.getChildCount(); 
      int[] listViewCoords = new int[2]; 
      mListView.getLocationOnScreen(listViewCoords); 
      int listX = (int) event.getRawX() - listViewCoords[0]; 
      int listY = (int) event.getRawY() - listViewCoords[1]; 

      View child; 
      for (int i = 0; i < childCount; i++) { 
       child = mListView.getChildAt(i); 
       child.getHitRect(rect); 
       if (rect.contains(listX, listY)) { 
        mDownView = child; 
        break; 
       } 
      } 

Bunu ACTION_DOWN olayında onTouch yönteminde kullanabilirsiniz. Selamlar.

+0

Teşekkürler. Ancak, getChildAt() ilk ** görünür ** çocuğu döndürür (ve listedeki ilk çocuk değil). Sonra dokundu eleman pozisyonunda "i mListView.getFirstVisiblePosition +, -, bu size yönelik kullanabilirsiniz çalışmasını sağlamak için (++ i mListView.getFirstVisiblePosition() i mListView.getLastVisiblePosition() Zach