Android: Elementy ListView z wieloma klikalnymi przyciskami
Mam ListView
gdzie każdy element na liście zawiera Widok tekstu i dwa różne przyciski. Coś takiego:
ListView
--------------------
[Text]
[Button 1][Button 2]
--------------------
[Text]
[Button 1][Button 2]
--------------------
... (and so on) ...
Za pomocą tego kodu mogę utworzyć OnItemClickListener
dla całego elementu:
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> list, View view, int position, long id) {
Log.i(TAG, "onListItemClick: " + position);
}
}
});
Jednak nie chcę, aby cały element był klikalny, ale tylko dwa przyciski każdego elementu listy.
Więc moje pytanie brzmi, jak zaimplementować onClickListener dla tych dwóch przycisków o następujących parametrach:
-
int button
(który przycisk elementu został kliknięty) -
int position
(który jest elementem listy, na której nastąpiło kliknięcie przycisku)
Update: znalazłem rozwiązanie opisane w mojej Odpowiedzi poniżej. Teraz mogę kliknąć / stuknąć przycisk za pomocą ekranu dotykowego. Nie mogę jednak ręcznie wybrać go za pomocą trackballa. Zawsze wybiera cały element listy i stamtąd przechodzi bezpośrednio do następnego elementu listy ignorując przyciski, mimo że ustawiłem .setFocusable(true)
i setClickable(true)
dla przycisków w getView()
.
Dodałem również ten kod do mojej niestandardowej listy adapterów:
@Override
public boolean areAllItemsEnabled() {
return false;
}
@Override
public boolean isEnabled(int position) {
return false;
}
To powoduje, że żaden element listy nie jest już wybierany. Ale nie pomogło to w wyborze zagnieżdżonych przycisków.
Ktoś ma pomysł?8 answers
Rozwiązanie tego problemu jest łatwiejsze niż myślałem. Możesz po prostu dodać w swojej niestandardowej metodzie adaptera getView()
setOnClickListener() dla używanych przycisków.
Wszelkie dane związane z przyciskiem muszą być dodane z myButton.setTag()
w getView()
i mogą być dostępne w onClickListener poprzez view.getTag()
Umieściłem szczegółowe rozwiązanie na mój blog jako tutorial.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-14 01:44:34
To jest jakby dodatek @ znq ' s odpowiedź...
Istnieje wiele przypadków, w których chcesz znać pozycję wiersza dla klikniętego elementu i chcesz wiedzieć, który widok w wierszu został stuknięty. Będzie to o wiele ważniejsze w interfejsie użytkownika tabletu.
Możesz to zrobić za pomocą następującego niestandardowego adaptera:
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);
}
};
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-18 00:24:38
Dla przyszłych czytelników:
Aby ręcznie wybrać przyciski z trackballem użyj:
myListView.setItemsCanFocus(true);
I aby wyłączyć fokus na całej liście elementów:
myListView.setFocusable(false);
myListView.setFocusableInTouchMode(false);
myListView.setClickable(false);
To działa dobrze dla mnie, mogę klikać na przyciski Z Ekranem dotykowym, a także alows focus kliknięcie za pomocą klawiatury
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-23 14:39:03
Nie mam większego doświadczenia niż powyżej użytkowników, ale spotkałem się z tym samym problemem i rozwiązałem to z poniższym rozwiązaniem
<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 event
public void btnRemoveClick(View v)
{
final int position = listviewItem.getPositionForView((View) v.getParent());
listItem.remove(position);
ItemAdapter.notifyDataSetChanged();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-01 00:41:31
Pewnie już wiesz jak to zrobić, ale możesz zadzwonić
ListView.setItemsCanFocus(true)
And now your buttons will catch focus
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-03 01:09:25
Nie jestem pewien być najlepszym sposobem, ale działa dobrze i cały kod pozostaje w 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;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-19 11:35:35
Wiem, że jest późno, ale to może pomóc, to jest przykład jak piszę niestandardową klasę adaptera dla różnych akcji klikania
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;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-14 09:20:38
Czy rozwiązaniem platformy dla tej implementacji nie jest użycie menu kontekstowego, które wyświetla się po długim naciśnięciu?
Czy autor pytania zna menu kontekstowe? Układanie przycisków w widoku listy ma wpływ na wydajność, zaśmieci interfejs użytkownika i naruszy zalecany projekt interfejsu użytkownika dla platformy.
Na flipside; menu kontekstowe-z natury nie posiadające pasywnej reprezentacji-nie są oczywiste dla użytkownika końcowego. Rozważasz udokumentowanie zachowania?
Ten poradnik powinno ci to dać dobry początek.
Http://www.mikeplate.com/2010/01/21/show-a-context-menu-for-long-clicks-in-an-android-listview/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-19 11:38:59