Android: ListView'dan alt görünümlere erişin


108

Kullanılarak görüntülenen bir listedeki bir öğenin piksel konumunu bulmam gerekiyor ListView. Görünüşe göre TextView'lardan birini almalı ve sonra kullanmalıyım getTop(), ancak a ListView.

Güncelleme: Bir ViewGroupiçin listedeki öğelerle 1'e 1 karşılık gelmeyen alt öğeleri ListView. Bunun yerine, ViewGroupçocukları yalnızca şu anda görünen görüşlere karşılık gelir. Bu nedenle getChildAt(), içsel olan ViewGroupve kullanılan listedeki konumla hiçbir ilgisi olmayan bir indeks üzerinde çalışır ListView.

Yanıtlar:


215

Bakınız: Android ListView: görünür öğenin veri dizinini alın ve yukarıdaki Feet'in cevabının bir kısmı ile birleştirin, size aşağıdaki gibi bir şey verebilir:

int wantedPosition = 10; // Whatever position you're looking for
int firstPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount(); // This is the same as child #0
int wantedChild = wantedPosition - firstPosition;
// Say, first visible position is 8, you want position 10, wantedChild will now be 2
// So that means your view is child #2 in the ViewGroup:
if (wantedChild < 0 || wantedChild >= listView.getChildCount()) {
  Log.w(TAG, "Unable to get view for desired position, because it's not being displayed on screen.");
  return;
}
// Could also check if wantedPosition is between listView.getFirstVisiblePosition() and listView.getLastVisiblePosition() instead.
View wantedView = listView.getChildAt(wantedChild);

Bunun yararı, ListView'ın alt öğelerini yinelememenizdir, bu da bir performans düşüşü yaşayabilir.


10
Harika yanıt, ancak listenizde başlık görünümleri olduğunda pek işe yaramıyor. Görev, firstPositionbunu int firstPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount();düzeltmek olmalıdır .
pospi

@pospi: teşekkürler, iyi nokta! Cevabımı bunun hesabına güncelledim.
Joe

İyi yanıt ve çoğu durumda işe yarıyor, ancak neden çocuk görüşlerinin çocuk görüşleri dizisindeki sırayla göründüğüne inandığınızı anlamıyorum. Görünümler yeniden kullanılabileceğine göre, ilk görüntünün son görünür görünümü temsil etmediğinden nasıl emin olabiliriz?
Victor Denisov

2
@VictorDenisov: bu yalnızca UI iş parçacığında olabilir; bu nedenle, bu kod yürütülürken UI iş parçacığı engellenecektir, bu nedenle alt görünümler sabittir ve değiştirilmeyecektir. ListViewZaten işleyen etrafında eski geri dönüşüm sonra çocuk görünümleri "hareketli" convertViewBunu, vb s, olabilir yani garanti ListView.getChildAt(0) olan adaptörden ilk ekli görünümü aslında. Tamamen görünmeyebilir (ve ListView"görünümün dışına kaydırılmış" olduğunu düşündüğü bir görünümü geri dönüştürmeden önce "görünürlük" eşiğine bağlı olarak hiç görünmeyebilir )
Joe

1
@Matheus, Android ListView böyle çalışmıyor. Liste öğesi kapalı ekran varsa, onun görünüm zaten geri dönüşümlü ve diğer liste öğelerinden biri için yeniden yapılmış olan ekranda. Bu bir gereklilikse, ListView'ı nasıl kullandığınızı yeniden düşünmelisiniz.
Joe

17

Bu kodun kullanımı daha kolaydır:

 View rowView = listView.getChildAt(viewIndex);//The item number in the List View
    if(rowView != null)
        {
           // Your code here
        }

9
her zaman çalışmıyor. getChildAt, verilerin üstünden değil, görünür ilk satırdan sayar.
SteelBytes

13
ViewID argümanı kafa karıştırıcı. Bu bir indeks (veya konum). Görünüm kimliği, aapt aracı tarafından oluşturulan tamamen rastgele bir tamsayıdır.
Johan Pelgrim

6

ListView sınıfı için belgelerde hızlı bir arama, ViewGroup'tan miras alınan getChildCount () ve getChildAt () yöntemlerini ortaya çıkardı. Bunları kullanarak bunları yineleyebilir misiniz? Emin değilim ama denemeye değer.

Buldum burada


1
Bunu seçimler yapmak için denedim. Genellikle işe yarıyor, ancak bazen tek tek hatalar oluyor ve güvenilir değil. Bunu tavsiye etmem.
Timmmm

Teşekkürler Timmmm, aslında denemedim, sadece belgelerde buldum.
Feet

5
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, final View view, int position, long id) {
        View v;
        int count = parent.getChildCount();
        v = parent.getChildAt(position);
        parent.requestChildFocus(v, view);
        v.setBackground(res.getDrawable(R.drawable.transparent_button));
        for (int i = 0; i < count; i++) {
            if (i != position) {
                v = parent.getChildAt(i);
                v.setBackground(res.getDrawable(R.drawable.not_clicked));
            }
        }
    }
});

Temel olarak, biri şeffaf, diğeri istenen renk olmak üzere iki Çekilebilir Tablo oluşturun . Tıklanan konumda ( int positiontanımlandığı gibi) odak isteyin ve söz konusu satırın rengini değiştirin. Sonra ebeveynin üzerinden yürüyün ListViewve diğer tüm satırları buna göre değiştirin. Bu, bir kullanıcının listviewbirden çok kez tıklamasını hesaba katar. Bu, içindeki her satır için özel bir düzen ile yapılır ListView. (Çok basit, sadece yeni bir düzen dosyası oluşturun TextView- odaklanabilir veya tıklanabilir olarak ayarlamayın!).

Özel adaptör gerekmez - kullanın ArrayAdapter


getChildAt, geçerli kaydırılan öğelere bağlıdır. Listenizi biraz kaydırırsanız bu çalışmayı durduracaktır.
nurettin

4
int position = 0;
listview.setItemChecked(position, true);
View wantedView = adapter.getView(position, null, listview);

1
Biraz detaylandırın
innoSPG

-9

Bu, ListView'daki öğenin konumunu bildiğinizi varsayar:

  View element = listView.getListAdapter().getView(position, null, null);

Daha sonra ekran konumundaki öğeleri belirlemek için getLeft () ve getTop () işlevlerini çağırabilmeniz gerekir.


43
getView()liste doldurulurken ListView tarafından dahili olarak çağrılır. Sen olmamalıdır çağırarak olarak listede bu pozisyonda görünüm elde için kullanabilirsiniz getView()için null convertViewadaptörünün düzeni kaynaktan yeni bir görünüm şişirmek için adaptör neden olur (zaten görüntülenmekte olduğunu görünüm elde etmez).
Joe

1
Eşit konum, adaptörün veri kaynağı konumuna değil, görsel ekranda bir konum olacaktır.
Vikas

@jasonhudgins En iyisi olduğunu düşündüğüm için kullandığım yöntem bu ama çocuk görünümünde bir ilerleme çubuğunu görünmez yapmaya çalıştığımda, bunun yerine listvew'deki tüm ilerleme çubuklarını görünmez yaptı ........ hepsi içinde kabul edilen tüm cevaplar hile yaptı
Edijae Crusar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.