2009-11-30 3 views
89

Ich habe eine einfache ListActivity, die einen benutzerdefinierten ListAdapter verwendet, um die Ansichten in der Liste zu generieren. Normalerweise würde der ListAdapter nur die Ansichten mit TextViews füllen, aber jetzt möchte ich auch einen Button dort einfügen.Wie onListItemClick in Listactivity mit Schaltflächen in der Liste auslösen?

Es ist jedoch mein Verständnis und Erfahrung, dass das Setzen einer fokussierbaren Ansicht in das Listenelement das Auslösen von onListItemClick() in der ListActivity verhindert, wenn auf das Listenelement geklickt wird. Die Schaltfläche funktioniert immer noch normal innerhalb des Listenelements, aber wenn etwas neben der Schaltfläche gedrückt wird, möchte ich onListItemClick ausgelöst werden.

Wie kann ich das schaffen?

+5

Ihre Lösung hinzufügen mit Nachfahre Focusability ist wirklich hilfreich, du solltest es als Antwort hinzufügen und akzeptieren! –

+0

@Max Der Grund, warum ich nicht ist, weil es wirklich schlechte Übung ist, ein Workaround. Wenn ich jemals eine dauerhafte gesunde Lösung gefunden habe, würde ich eine Antwort geben (wenn ich mich erinnere, dass ich diese Frage vor einem Jahr geschrieben habe :)) – CodeFusionMobile

+0

Ich möchte auch die Problemumgehung sehen, die Sie haben. Ich habe versucht, den Nachkommafokus einzustellen und kann nicht mit Tasten arbeiten. Ich habe auch versucht, eine GridView (mit ImageViews) in der Liste Zeile und ähnliche Probleme haben. – MrPurpleStreak

Antwort

59

Ich hoffe, ich kann hier helfen. Ich nehme an, dass Sie ein benutzerdefiniertes Layout für listView-Elemente haben, und dieses Layout besteht aus Schaltflächen und einigen anderen Ansichten - wie TextView, ImageView oder was auch immer. Jetzt möchten Sie ein anderes Ereignis ausgelöst haben, wenn Sie auf einen Klick klicken und ein anderes Ereignis ausgelöst wird.

Sie können das erreichen, ohne onListItemClick() Ihrer ListActivity zu verwenden.
Hier ist, was Sie tun müssen:

Sie verwenden benutzerdefinierte Layout, so wahrscheinlich überschreiben Sie getView() -Methode von Ihrem benutzerdefinierten Adapter. Der Trick besteht darin, die verschiedenen Listener für Ihre Schaltfläche und für die gesamte Ansicht (Ihre Zeile) unterschiedlich festzulegen. Werfen Sie einen Blick auf das Beispiel:

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

Ihre OnItemClickListener Klasse wie hier erklärt werden könnte:

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

Natürlich werden Sie wahrscheinlich fügen Sie einige weitere Parameter OnItemClickListener Konstruktor.
Und eine wichtige Sache - Implementierung von getView, die oben gezeigt wird, ist ziemlich hässlich, normalerweise sollten Sie das ViewHolder-Muster verwenden, um findView.ById-Aufrufe zu vermeiden .. aber Sie wissen das wahrscheinlich schon.
Meine custom_row.xml Datei ist RelativeLayout mit Button von id "button", TextView von id "text" und ImageView von id "image" - nur um Dinge klar zu stellen.
Grüße!

+9

Meine Lösung ging in eine andere Richtung. Ich löste das Problem, indem ich die Eigenschaft Focusability des List-Zeilen-Layouts auf Nachfahren setzte und plötzlich funktionierte es. Jetzt benutze ich einen simpleCursorAdapter mit einem eigenen Viewbinder, um die Ereigniseinrichtung und andere mit den Buttons verbundene Dinge zu erledigen. – CodeFusionMobile

+3

Ich habe diese Lösung verwendet. Eine Warnung: Wenn Ihr onClick-Handler den Inhalt der Liste ändert, was dazu führt, dass getView AND aufgerufen wird und Ihr Widget statusbehaftet ist (wie ein ToggleButton oder CheckBox) und AND getView diesen Status setzt, möchten Sie vielleichtOnClickListener setzen (null), bevor Sie den Status in onView ändern, um einen Schleifeneffekt zu vermeiden. –

+0

arbeitete für mich ... – SaKet

1

Ich hatte das gleiche Problem mit ToggleButton. Nachdem ich einen halben Tag mit dem Kopf gegen eine Wand geschlagen hatte, löste ich es endlich. Es ist so einfach, die fokussierbare Ansicht mit "android: focusable" nicht fokussierbar zu machen. Sie sollten es auch vermeiden, mit der Fokussierbarkeit und Klickbarkeit (ich habe gerade Wörter erfunden) der Listenzeile zu spielen, lassen Sie sie einfach mit dem Standardwert.

Da Ihre fokussierbaren Ansichten in der Listenzeile jetzt nicht fokussierbar sind, können Benutzer, die die Tastatur verwenden, Probleme haben. Es ist wahrscheinlich kein Problem, aber nur für den Fall, dass Sie 100% fehlerfreie Apps schreiben möchten, können Sie das onItemSelected-Ereignis verwenden, um die Elemente der ausgewählten Zeile fokussierbar und die Elemente der zuvor ausgewählten Zeile nicht fokussierbar zu machen.

+0

Ich habe diesen Ansatz verwendet. Es ist der einfachste Weg, wenn Sie das Problem vermeiden können, sich auf einzelne Dinge konzentrieren zu können. Dadurch werden auch die Zustandssymbole für die Listenelemente so beibehalten, wie sie sein sollten, was bei einigen anderen Problemumgehungen nicht der Fall ist. –

18

Wenn eine benutzerdefinierte ListView fokussierbare Elemente enthält, funktioniert onListItemClick nicht (ich denke, es ist das erwartete Verhalten). Gerade den Fokus von der benutzerdefinierten Ansicht entfernen, wird es den Trick:

Zum Beispiel:

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

Ich mag Ihre Lösung: Wenn es nur ein "klickbares" Widget pro Zeile gibt, dann ist es eine elegante Lösung, die Fokussierbarkeit zu verweigern. Es bedeutet, dass ein Tippen irgendwo in der Zeile übereinstimmt, aber das ist ein nützliches Verhalten, wenn das Widget ein Radio oder ein Kontrollkästchen ist. Das gleiche kann in XML mit Android erreicht werden: focusable = "false" und android: focusableInTouchMode = "false". –

+1

der XML-Weg scheint nicht zu funktionieren, wenn Sie die Sichtbarkeit ändern, so muss man es durch Code nach der Einstellung der "Ansicht" zu sichtbar machen – max4ever

13

ich das gleiche Problem haben: OnListItemClick nicht gefeuert![gelöst]
das ist auf Klasse passiert, dass ListActivity erweitern,
mit einem Layout für ListActivity, dass der Inhalt TextBox und Listview in Linearlayout verschachtelt
und ein anderes Layout für die Zeilen (CheckBox und TextBox in LineraLayout verschachtelt).

Das ist Code:

res/layout/configpage.xml (Haupt für ListActivity)

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

Diese beginnen zu arbeiten, wenn ich in row.xml

hinzugefügt
  • android:focusable="false"
  • android:focusableInTouchMode="false"

Ich benutze Eclipse-3.5.2
Android SDK 10.0.1
min SDK Version: 3

Ich hoffe, dass dies hilfreich ist
... und Entschuldigung für mein Englisch :(

+0

Gud Arbeit Mann ........ es löst mein Problem –

+0

@ Die Falken wissen nicht warum, aber es hat nicht für mich funktioniert. Mein onListItemClick wird nicht aufgerufen. – likejiujitsu

+0

Haben Sie den Eigenschaftencode android hinzugefügt: focusable = "false" und android: focusableInTouchMode = "false" code? – rfellons

-1

Ich benutzte den getListAdapter () .getItem (Position), um ein Objekt zu instanziieren, die meine Werte innerhalb des Elements

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

dann verwendet, um die Getter-Methode aus dem myPojo hält sie ihre richtigen Werte in der Position nennen werden.

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

wie ich in previous comment Lösung geschrieben hat, ist zu setFocusable (false) auf Image.

Es gibt noch elegantere Lösung versuchen, android:descendantFocusability="blocksDescendants"im Root-Layout des Listenelements hinzuzufügen. Das macht Klicks onListItem möglich und können separat u Griff-Taste oder Imagebutton klickt

Hoffe, es hilft;)

Prost

+3

'android: descendantFocusability =" blocksDescendants "' war perfekt. –

+1

Sie, mein Freund, sind mein persönlicher Held. Du solltest der Beste sein! das ist viel viel besser für fast alle Fälle! –

+0

Dies sollte die akzeptierte Antwort sein. Es hat perfekt für mich funktioniert. Es sieht so aus, als ob alle Ansichten in dem Listenelement unfokussierbar sein müssen, und dies tut dies nur, ohne jedes einzeln einzustellen. – rushinge

2

nur android:focusable="false" als eines der Attribute Ihrer Schaltfläche

Verwandte Themen