2009-11-10 3 views
174

У меня есть ListView, где каждый элемент в списке содержит TextView и две разные кнопки. Что-то вроде этого:Android: Элементы ListView с несколькими кнопками с кнопками

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

С помощью этого кода я могу создать OnItemClickListener для всего элемента:

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

     } 

    } 
}); 

Однако, я не хочу, чтобы весь товар, чтобы быть интерактивными, но только две кнопки каждого элемента списка.

Так что мой вопрос, как я могу реализовать onClickListener для этих двух кнопок со следующими параметрами:

  • int button (какая кнопка элемента была нажата)
  • int position (который является элементом в списке, на котором произошло нажатие кнопки)

Обновление: Я нашел решение, как описано в моем ответе ниже. Теперь я могу щелкнуть/нажать кнопку с помощью сенсорного экрана. Однако я не могу вручную выбрать его с помощью трекбола. Он всегда выбирает весь элемент списка и оттуда переходит непосредственно к следующему элементу списка, игнорируя кнопки, хотя я установил .setFocusable(true) и setClickable(true) для кнопок в getView().

Я также добавил этот код в моем пользовательском списке адаптер:

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

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

Это приводит к тому, что ни один элемент списка не выбирается на все больше. Но это не помогло сделать выбор вложенных кнопок.

Любая идея?

+0

Эти еще нужны? –

+0

Если вы посмотрите на код BaseAdapter, вы увидите, что areAllItemsEnabled() и isEnabled() просто закодированы в true, что делает их простыми заполнителями без какой-либо логики. –

+0

Что делать, если я хочу использовать SimpleCursorAdapter? Должен ли я сделать собственный адаптер, расширяющий simplecursoradapter? – oratis

ответ

146

Решение на самом деле проще, чем я думал. Вы можете просто добавить в свой метод getView() пользовательского адаптера setOnClickListener() для кнопок, которые вы используете.

Любые данные, связанные с кнопкой должна быть добавлена ​​с myButton.setTag() в getView() и могут быть доступны в onClickListener с помощью view.getTag()

я отправил подробное решение о my blog в качестве руководства.

+10

"мой блог" URL не работает ... – vnshetty

+2

Исправлено. Спасибо за сообщение :-) – znq

+0

Насколько вы получили curItem.url из запроса, не могли бы вы уточнить? – oratis

9

Возможно, вы нашли, как сделать это, но вы можете позвонить

ListView.setItemsCanFocus(true) 

и теперь ваши кнопки будут ловить фокус

+0

Спасибо, что он работает ... спас мое время. –

60

Это своего рода ответ придаток @ znq в ...

Есть много случаев, когда вы хотите знать позицию строки для объекта с щелчком И вы хотите знать, какой вид в строке был использован. Это будет намного более важным в пользовательских интерфейсах планшета.

Вы можете сделать это с помощью следующего пользовательского адаптера:

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

или вы также можете использовать что-то вроде этого ListView mListView = (ListView) v.getParent(). GetParent(); – max4ever

+1

Как я могу получить позицию, если я использую адаптер в отдельном классе. Я просто использовал позицию внутри OnClickListener, что-то вроде this_c.get (position). Он предлагает сделать конечную позицию в методе getView адаптера. Если я сделаю это изменение, то позиция, которую я получаю, будет одинаковой для всех элементов в lisview. Не могли бы вы предложить мне, как это решить. – Manikandan

+0

Это потому, что, когда вы используете параметр позиции метода getView, он дает вам позицию элемента списка, который был недавно создан, но не тот, который вы нажали. –

22

Для будущих читателей:

Чтобы выбрать вручную кнопки с использованием трекболом:

myListView.setItemsCanFocus(true); 

И отключить сосредоточить внимание на целом списке элементов:

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

Он отлично работает для меня, я могу нажать на кнопки с сенсорным экраном, а также Alows сфокусировать щелчок с помощью клавиатуры

+2

Только этот помог мне! Большое спасибо! – Onur

+0

Спасибо, я попробовал другие ответы и не работал для меня –

+0

Что касается ExpandableListView, у меня есть несколько представлений в элементе, я просто хочу, чтобы взгляды у ребенка были интерактивными, спасибо. – twlkyao

5

Я не уверен, что будет лучший способ, но работает отлично, и весь код остается в 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; 
} 

} 
-4

Не является ли платформенным решением для этой реализации использовать контекстное меню, которое отображается при длительной печати?

Является ли автор вопроса осведомленным о контекстных меню? Укладка кнопок в списке имеет последствия для производительности, загромождает ваш пользовательский интерфейс и нарушает рекомендуемый дизайн пользовательского интерфейса для платформы.

На оборотной стороне; контекстные меню - по характеру отсутствия пассивного представления - не являются очевидными для конечного пользователя. Рассмотрим документирование поведения?

Это руководство должно дать вам хорошее начало.

http://www.mikeplate.com/2010/01/21/show-a-context-menu-for-long-clicks-in-an-android-listview/

+0

И причина для понижения? – Gusdor

12

У меня нет большого опыта работы, чем выше пользователей, но я столкнулся с этим же вопросом, и я решил эту проблему с ниже Решением

<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 Нажмите событие

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

} 
+0

интересное решение – sherpya

2

I Знайте, что это поздно, но это может помочь, это пример того, как я пишу пользовательский класс адаптера для разных действий с кликом.

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; 
    } 
} 
Смежные вопросы