it-swarm.com.de

Android: ListView-Elemente mit mehreren anklickbaren Schaltflächen

Ich habe ein ListView, in dem jedes Element in der Liste eine Textansicht und zwei verschiedene Schaltflächen enthält. Etwas wie das:

ListView
--------------------
[Text]
[Button 1][Button 2]
--------------------
[Text]
[Button 1][Button 2]
--------------------
... (and so on) ...

Mit diesem Code kann ich ein OnItemClickListener für den gesamten Artikel erstellen:

listView.setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> list, View view, int position, long id) {
        Log.i(TAG, "onListItemClick: " + position);

        }

    }
});

Ich möchte jedoch nicht, dass das gesamte Element anklickbar ist, sondern nur die beiden Schaltflächen jedes Listenelements.

Meine Frage ist also, wie ich einen onClickListener für diese beiden Schaltflächen mit den folgenden Parametern implementiere:

  • int button (Welche Schaltfläche des Elements angeklickt wurde)
  • int position (Das ist das Element in der Liste, auf das die Schaltfläche geklickt hat)

pdate: Ich habe eine Lösung gefunden, wie in meiner Antwort unten beschrieben. Jetzt kann ich über den Touchscreen auf die Schaltfläche klicken/tippen. Ich kann es jedoch nicht manuell mit dem Trackball auswählen. Es wird immer der gesamte Listeneintrag ausgewählt und von dort direkt zum nächsten Listeneintrag weitergeleitet, wobei die Schaltflächen ignoriert werden, obwohl ich .setFocusable(true) und setClickable(true) für die Schaltflächen in getView() festgelegt habe.

Ich habe auch diesen Code zu meinem benutzerdefinierten Listenadapter hinzugefügt:

@Override
public boolean  areAllItemsEnabled() {
    return false;           
}

@Override
public boolean isEnabled(int position) {
        return false;
}

Dies führt dazu, dass kein Listenelement mehr auswählbar ist. Es half jedoch nicht, die verschachtelten Schaltflächen auswählbar zu machen.

Hat jemand eine Idee?

181
znq

Die Lösung dafür ist tatsächlich einfacher als ich dachte. Sie können der getView() -Methode Ihres benutzerdefinierten Adapters einfach einen setOnClickListener () für die von Ihnen verwendeten Schaltflächen hinzufügen.

Alle mit der Schaltfläche verknüpften Daten müssen mit myButton.setTag() in getView() hinzugefügt werden und sind im onClickListener über view.getTag() zugänglich.

Ich habe eine detaillierte Lösung auf mein Blog als Tutorial gepostet.

150
znq

Dies ist eine Art Anhang @ znqs Antwort ...

In vielen Fällen möchten Sie die Zeilenposition für ein angeklicktes Element und wissen, welche Ansicht in der Zeile angeklickt wurde. Dies wird in Tablet-Benutzeroberflächen viel wichtiger sein.

Sie können dies mit dem folgenden benutzerdefinierten Adapter tun:

private static class CustomCursorAdapter extends CursorAdapter {

    protected ListView mListView;

    protected static class RowViewHolder {
        public TextView mTitle;
        public TextView mText;
    }

    public CustomCursorAdapter(Activity activity) {
        super();
        mListView = activity.getListView();
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        // do what you need to do
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        View view = View.inflate(context, R.layout.row_layout, null);

        RowViewHolder holder = new RowViewHolder();
        holder.mTitle = (TextView) view.findViewById(R.id.Title);
        holder.mText = (TextView) view.findViewById(R.id.Text);

        holder.mTitle.setOnClickListener(mOnTitleClickListener);
        holder.mText.setOnClickListener(mOnTextClickListener);

        view.setTag(holder);

        return view;
    }

    private OnClickListener mOnTitleClickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            final int position = mListView.getPositionForView((View) v.getParent());
            Log.v(TAG, "Title clicked, row %d", position);
        }
    };

    private OnClickListener mOnTextClickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            final int position = mListView.getPositionForView((View) v.getParent());
            Log.v(TAG, "Text clicked, row %d", position);
        }
    };
}
62
greg7gkb

Für zukünftige Leser:

Um die Tasten mit dem Trackball manuell auszuwählen, verwenden Sie:

myListView.setItemsCanFocus(true);

Und um den Fokus auf die gesamten Listenelemente zu deaktivieren:

myListView.setFocusable(false);
myListView.setFocusableInTouchMode(false);
myListView.setClickable(false);

Es funktioniert gut für mich, ich kann auf Schaltflächen mit Touchscreen klicken und kann auch einen Klick mit der Tastatur fokussieren

22
Fabricio PH

Ich habe nicht viel Erfahrung als die oben genannten Benutzer, aber ich hatte das gleiche Problem und habe es mit der folgenden Lösung gelöst

<Button
        Android:id="@+id/btnRemove"
        Android:layout_width="0dp"
        Android:layout_height="wrap_content"
        Android:layout_toRightOf="@+id/btnEdit"
        Android:layout_weight="1"
        Android:background="@drawable/btn"
        Android:text="@string/remove" 
        Android:onClick="btnRemoveClick"
        />

btnRemoveClick Click-Ereignis

public void btnRemoveClick(View v)
{
    final int position = listviewItem.getPositionForView((View) v.getParent()); 
    listItem.remove(position);
    ItemAdapter.notifyDataSetChanged();

}
12
Bhavin Chauhan

Wahrscheinlich haben Sie gefunden, wie es geht, aber Sie können anrufen

ListView.setItemsCanFocus(true)

und jetzt werden Ihre Tasten den Fokus fangen

9
Rafal

Ich bin mir nicht sicher, ob es der beste Weg ist, aber er funktioniert einwandfrei und der gesamte Code verbleibt in Ihrem ArrayAdapter.

package br.com.fontolan.pessoas.arrayadapter;

import Java.util.List;

import Android.content.Context;
import Android.text.Editable;
import Android.text.TextWatcher;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.View.OnClickListener;
import Android.view.ViewGroup;
import Android.widget.ArrayAdapter;
import Android.widget.EditText;
import Android.widget.ImageView;
import br.com.fontolan.pessoas.R;
import br.com.fontolan.pessoas.model.Telefone;

public class TelefoneArrayAdapter extends ArrayAdapter<Telefone> {

private TelefoneArrayAdapter telefoneArrayAdapter = null;
private Context context;
private EditText tipoEditText = null;
private EditText telefoneEditText = null;
private ImageView deleteImageView = null;

public TelefoneArrayAdapter(Context context, List<Telefone> values) {
    super(context, R.layout.telefone_form, values);
    this.telefoneArrayAdapter = this;
    this.context = context;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.telefone_form, parent, false);

    tipoEditText = (EditText) view.findViewById(R.id.telefone_form_tipo);
    telefoneEditText = (EditText) view.findViewById(R.id.telefone_form_telefone);
    deleteImageView = (ImageView) view.findViewById(R.id.telefone_form_delete_image);

    final int i = position;
    final Telefone telefone = this.getItem(position);
    tipoEditText.setText(telefone.getTipo());
    telefoneEditText.setText(telefone.getTelefone());

    TextWatcher tipoTextWatcher = new TextWatcher() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void afterTextChanged(Editable s) {
            telefoneArrayAdapter.getItem(i).setTipo(s.toString());
            telefoneArrayAdapter.getItem(i).setIsDirty(true);
        }
    };

    TextWatcher telefoneTextWatcher = new TextWatcher() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void afterTextChanged(Editable s) {
            telefoneArrayAdapter.getItem(i).setTelefone(s.toString());
            telefoneArrayAdapter.getItem(i).setIsDirty(true);
        }
    };

    tipoEditText.addTextChangedListener(tipoTextWatcher);
    telefoneEditText.addTextChangedListener(telefoneTextWatcher);

    deleteImageView.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            telefoneArrayAdapter.remove(telefone);
        }
    });

    return view;
}

}
5
mFontolan

Ich weiß, dass es spät ist, aber das kann helfen. Dies ist ein Beispiel dafür, wie ich eine benutzerdefinierte Adapterklasse für verschiedene Klickaktionen schreibe

 public class CustomAdapter extends BaseAdapter {

    TextView title;
  Button button1,button2;

    public long getItemId(int position) {
        return position;
    }

    public int getCount() {
        return mAlBasicItemsnav.size();  // size of your list array
    }

    public Object getItem(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {

        if (convertView == null) {
            convertView = getLayoutInflater().inflate(R.layout.listnavsub_layout, null, false); // use sublayout which you want to inflate in your each list item
        }

        title = (TextView) convertView.findViewById(R.id.textViewnav); // see you have to find id by using convertView.findViewById 
        title.setText(mAlBasicItemsnav.get(position));
      button1=(Button) convertView.findViewById(R.id.button1);
      button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //your click action 

           // if you have different click action at different positions then
            if(position==0)
              {
                       //click action of 1st list item on button click
        }
           if(position==1)
              {
                       //click action of 2st list item on button click
        }
    });

 // similarly for button 2

   button2=(Button) convertView.findViewById(R.id.button2);
      button2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //your click action 

    });



        return convertView;
    }
}
3
Manohar Reddy