Listactivity'de onListItemClick listedeki düğmelerle nasıl tetiklenir?


89

Listedeki görünümleri oluşturmak için özel bir ListAdapter kullanan basit bir ListActivity var. Normalde ListAdapter, görünümleri TextViews ile doldurur, ancak şimdi oraya da bir düğme koymak istiyorum.

Ancak, liste öğesine odaklanabilir bir görünüm koymanın, liste öğesi tıklandığında ListActivity'deki onListItemClick () öğesinin tetiklenmesini engellediğini anladığım ve deneyimledim. Düğme liste öğesi içinde normal şekilde çalışmaya devam eder, ancak düğmenin yanı sıra bir şeye basıldığında onListItemClick'in tetiklenmesini istiyorum.

Bunu nasıl çalıştırabilirim?


5
soyundan gelen Odaklanabilirlik ile çözümünüz gerçekten yardımcıdır, yanıt olarak eklemeli ve kabul etmelisiniz!
Maksym Gontar

@Max Bunu yapmamamın nedeni gerçekten kötü bir uygulama, bir çözüm. Kalıcı ve sağlıklı bir çözüm
bulursam

Ayrıca sahip olduğunuz geçici çözümü de görmek isterim. Alt odağı ayarlamaya çalışıyorum ve düğmelerle çalışmasını sağlayamıyorum. Ayrıca liste satırına GridView (ImageViews ile) koymaya çalışıyorum ve benzer sorunları var.
MrPurpleStreak

Verdiğim IMHO cevabı, problem için Ramps ve Praveen tarafından önerilen çok daha zarif bir çözüm. Ps Burada unutulan soruyu canlandırmaya çalışmıyorum ama henüz hiçbir cevabı kabul etmediğini görüyorum; D
Ewoks

@CodeFusionMobile Ewoks'un cevabını kabul eder misiniz? En yüksek oyu alan yanıt kusurludur çünkü ListView öğesi için onclick animasyonunu devre dışı bırakır (maviye döner). Bu, diğer geliştiricilere en iyi cevabı denemek, hatalı olduğunu bulmak ve ardından Ewoks's'a gitmek için harcanan zamandan tasarruf sağlayacaktır.
1 "

Yanıtlar:


99

Önceki yorum çözümünde yazdığım gibi ImageButton üzerinde setFocusable (false).

Liste öğesinin android:descendantFocusability="blocksDescendants" kök düzenine eklemek için daha zarif bir çözüm var . Bu, onListItem tıklamalarını mümkün kılar ve ayrıca Button veya ImageButton tıklamalarını yönetebilirsiniz.

Umarım yardımcı olur ;)

Şerefe


3
android:descendantFocusability="blocksDescendants"mükemmeldi.
Matthew Mitchell

1
sen, arkadaşım, benim kişisel kahramanımsın. en çok oy alan siz olmalısınız! bu neredeyse her durum için çok daha iyi!
OschtärEi

Kabul edilen cevap bu olmalıdır. Benim için mükemmel çalıştı. Görünüşe göre liste öğesindeki tüm görünümlerin odaklanmamış olması gerekiyor ve bu, her birini ayrı ayrı ayarlamadan bunu yapıyor.
2013

1
Bu benim için çalışmıyor gibi görünüyor. Kök düzeni derken, satır düzenini mi yoksa liste görünümünün nerede tanımlandığını mı kastediyorsunuz? Her neyse, tüm olası kombinasyonları denedim .. çalışmıyor :(
GreenBee

"Liste elemanının kök düzeni" yazdığım gibi .. Diyelim ki bir listeniz var ve birkaç Button, ImageButton, TextVeiw içeren düzenlerden oluşan düzenleriniz var (bunlara liste elemanının kök düzeni diyelim).
Ewoks

59

Umarım burada yardımcı olabilirim. ListView öğeleri için özel bir düzeniniz olduğunu varsayıyorum ve bu düzen, düğme ve diğer bazı görünümlerden - TextView, ImageView veya her neyse. Şimdi, düğme tıklandığında farklı olayın ve tıklanan her şeyde farklı olayın tetiklenmesini istiyorsunuz.

Bunu, ListActivity'nizin onListItemClick () işlevini kullanmadan elde edebilirsiniz.
İşte yapmanız gerekenler:

Özel düzen kullanıyorsunuz, bu nedenle muhtemelen özel adaptörünüzden getView () yöntemini geçersiz kılıyorsunuz. İşin püf noktası, düğmeniz için farklı dinleyiciler ayarlamak ve tüm görünüm (sıranız) için farklı olmaktır. Örneğe bir göz atın:

private class MyAdapter extends ArrayAdapter<String> implements OnClickListener {

    public MyAdapter(Context context, int resource, int textViewResourceId,
            List<String> objects) {
        super(context, resource, textViewResourceId, objects);
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        String text = getItem(position);
        if (null == convertView) {
            convertView = mInflater.inflate(R.layout.custom_row, null);
        }
        //take the Button and set listener. It will be invoked when you click the button.
        Button btn = (Button) convertView.findViewById(R.id.button);
        btn.setOnClickListener(this);
        //set the text... not important     
        TextView tv = (TextView) convertView.findViewById(R.id.text);
        tv.setText(text);
        //!!! and this is the most important part: you are settin listener for the whole row
        convertView.setOnClickListener(new OnItemClickListener(position));
        return convertView;
    }

    @Override
    public void onClick(View v) {
        Log.v(TAG, "Row button clicked");
    }
}

OnItemClickListener sınıfınız şu şekilde bildirilebilir:

private class OnItemClickListener implements OnClickListener{       
    private int mPosition;
    OnItemClickListener(int position){
        mPosition = position;
    }
    @Override
    public void onClick(View arg0) {
        Log.v(TAG, "onItemClick at position" + mPosition);          
    }       
}

Elbette, muhtemelen OnItemClickListener yapıcısına daha fazla parametre ekleyeceksiniz.
Ve önemli bir şey - yukarıda gösterilen getView uygulaması oldukça çirkin, normalde findViewById çağrılarından kaçınmak için ViewHolder kalıbını kullanmalısınız .. ama muhtemelen bunu zaten biliyorsunuzdur.
Custom_row.xml dosyam RelativeLayout, Button of id "button", TextView id "text" ve ImageView id "image" - sadece işleri netleştirmek için.
Saygılarımızla!


9
Çözümüm başka bir yöne gitti. Liste satırı düzeninin altsoy Odaklanabilirlik özelliğini torunları engelleyecek şekilde ayarlayarak sorunu çözdüm ve aniden işe yaradı. Şimdi, olay kurulumunu ve düğmelerle ilişkili diğer süslü şeyleri yapmak için kendisine özel bir görüntüleyici eklenmiş bir simpleCursorAdapter kullanıyorum.
CodeFusionMobile

3
Bu çözümü kullandım. Bununla birlikte, bir uyarı: onClick işleyiciniz listenin içeriğinin değişmesine neden olursa, bu da getView'in çağrılmasına neden olur VE widget'ınız durum bilgisine sahipse (ToggleButton veya CheckBox gibi) VE getView bu durumu ayarlarsa, setOnClickListener'ı ayarlamak isteyebilirsiniz. (null) bir döngü efekti almaktan kaçınmak için onView'daki durumu değiştirmeden önce.
Pierre-Luc Paour

3
benim çözümüm ne olacak? Daha zarif ve ihtiyaç duyduğumuzda daha kolay uygulanabilecek bir izlenimim var ..
Ewoks

ilk yorum cevap olarak kabul edilmeli, böylece benim gibi insanların onu bulmak için saatlere ihtiyacı olmayacak
keybee

Teşekkürler! Bu faydalı oldu. Odaklanmaya daha yerelleştirilmiş bir alternatif olarak hoşuma gidiyor: diğer iş parçacıklarında açıklanan blockDescendants yaklaşımı.
Yoav Shapira

18

Özel bir ListView odaklanabilir öğeler içerdiğinde, onListItemClick çalışmaz (bunun beklenen davranış olduğunu düşünüyorum). Odağı özel görünümden kaldırmanız yeterli olacaktır:

Örneğin:

public class ExtendedCheckBoxListView extends LinearLayout {

    private TextView mText;
    private CheckBox mCheckBox;

    public ExtendedCheckBoxListView(Context context, ExtendedCheckBox aCheckBoxifiedText) {
         super(context);
         …
         mText.setFocusable(false);
         mText.setFocusableInTouchMode(false);

         mCheckBox.setFocusable(false);
         mCheckBox.setFocusableInTouchMode(false);
        …       
    }
}

3
Çözümünüzü beğendim: Satır başına yalnızca bir "tıklanabilir" pencere öğesi varsa, bunların odaklanabilirliğini reddetmek şık bir çözümdür. Bu, satırın herhangi bir yerine bir dokunmanın eşleşeceği anlamına gelir, ancak bu, widget bir radyo veya onay kutusu olduğunda yararlı bir davranıştır. Aynısı, android: focusable = "false" ve android: focusableInTouchMode = "false" kullanılarak XML'de de elde edilebilir.
Pierre-Luc Paour

1
Görünürlüğü değiştirirseniz xml yöntemi işe yaramıyor gibi görünüyor, bu nedenle "Görünüm" öğesini görünür olarak ayarladıktan sonra bunu kod aracılığıyla yapmak
zorundasınız

13

Bende de aynı sorun var: OnListItemClick ateşlenmedi! [ÇÖZÜLDÜ]
Bu,
TextBox ve ListView için LinearLayout'a yuvalanmış ListActivity
için bir düzen ve satırlar için başka bir düzen (LineraLayout'a yuvalanmış bir CheckBox ve TextBox) ile ListActivity'yi genişleten sınıfta gerçekleşir.

Bu kod:

res / layout / configpage.xml (ListActivity için ana)

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent" > 
    <TextView  
        android:id="@+id/selection"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:text="pippo" /> 
    <ListView  
        android:id="@android:id/list"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:drawSelectorOnTop="false"  
        android:background="#aaFFaa" > 
    </ListView> 
<LinearLayout> 

res/layout/row.xml (layout for single row)  
<LinearLayout  
  xmlns:android="http://schemas.android.com/apk/res/android"  
  android:layout_width="fill_parent"  
  android:layout_height="wrap_content"> 
  <CheckBox  
      android:id="@+id/img"  
      android:layout_width="wrap_content"  
      android:layout_height="wrap_content"  
      **android:focusable="false"**  
      **android:focusableInTouchMode="false"** /> 

  <TextView  
      android:id="@+id/testo"  
      android:layout_width="wrap_content"  
      android:layout_height="wrap_content"  
      **android:focusable="false"**  
      **android:focusableInTouchMode="false"** /> 
</LinearLayout> 

src /.../.../ ConfigPage.java

public class ConfigPage extends ListActivity
{
    TextView selection;

    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.configpage);  
        // loaded from res/value/strings  
        String[] azioni = getResources().getStringArray(R.array.ACTIONS);  
        setListAdapter(new ArrayAdapter&lt;String&gt;(this, R.layout.row, 
                R.id.testo,   azioni));  
        selection = (TextView) findViewById(R.id.selection);  
    }       

    public void onListItemClick(ListView parent, View view, int position, long id)
    {
        selection.setText(" " + position);
    }
}

Bu, row.xml dosyasına eklediğimde çalışmaya başlıyor

  • android:focusable="false"
  • android:focusableInTouchMode="false"

Eclipse 3.5.2
Android SDK 10.0.1
dk. SDK sürümünü kullanıyorum: 3

Umarım bu yardımcı olmuştur
... ve ingilizcem için özür dilerim :(


@ fellons neden bilmiyor, ama benim için işe yaramadı. OnListItemClick çağrılmıyor.
likejudo

Android: focusable = "false" ve android: focusableInTouchMode = "false" kodu özellik kodunu eklediniz mi?
rfellons

2

android:focusable="false"düğmenizin özelliklerinden biri olarak ekleyin


1

ToggleButton ile aynı sorunu yaşadım. Yarım gün kafamı duvara vurduktan sonra nihayet çözdüm. Odaklanabilir görünümü 'android: odaklanabilir' kullanarak odaklanılamaz hale getirmek kadar basit. Ayrıca liste satırının odaklanabilirliği ve tıklanabilirliği ile oynamaktan da kaçınmalısınız (ben sadece kelimeleri uydurdum), onları varsayılan değerde bırakın.

Elbette, artık liste satırındaki odaklanabilir görünümlerinize odaklanılamadığına göre, klavyeyi kullanan kullanıcılar bunlara odaklanmada sorun yaşayabilir. Muhtemelen bir problem olmayacaktır, ancak% 100 kusursuz uygulamalar yazmak istemeniz durumunda, onItemSelected olayını, seçilen satırın öğelerini odaklanabilir ve önceden seçilen satırın öğelerini odaklanamaz hale getirmek için kullanabilirsiniz.


Bu yaklaşımı kullandım. Tek tek öğelere odaklanamama sorununu aşabilmeniz en basit yoludur. Bu ayrıca liste öğeleri için durum çekilebilirlerini olması gerektiği gibi tutar, diğer bazı geçici çözümlerde bunu yapmaz.
Jonathan S.

1
 ListView lv = getListView();
lv.setTextFilterEnabled(true);

lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
    int position, long id) {
  // When clicked, show a toast with the TextView text
  Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
      Toast.LENGTH_SHORT).show();
}
});

-1

Değerlerimi öğe içinde tutan bir Object örneğini oluştururken getListAdapter (). GetItem (position) 'ı kullandım

MyPojo myPojo = getListAdapter().getItem(position);

sonra myPojo'dan alıcı yöntemini kullandı, öğe içindeki uygun değerlerini çağıracak.

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.