Список с множественным выбором с пользовательским видом? - PullRequest
34 голосов
/ 16 апреля 2010

Я видел пример com.example.android.apis.view.List11 от ApiDemos. В этом примере каждая строка принимает представление android.R.simple_list_item_multiple_choice . Каждый такой вид имеет TextView и CheckBox.

Теперь я хочу, чтобы каждое представление имело 2 TextView s и 1 CheckBox, что немного похоже на пример List3 . Я попытался создать собственный файл макета row.xml, например:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <CheckBox
        android:id="@+id/checkbox"
        android:layout_alignParentRight="true"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent" />
    <TextView
        android:id="@+id/text_name"
        android:textSize="13px"
        android:textStyle="bold"
        android:layout_toLeftOf="@id/checkbox"
        android:layout_alignParentLeft="true"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/text_phone"
        android:textSize="9px"
        android:layout_toLeftOf="@id/checkbox"
        android:layout_below="@id/text_name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" /> 
</RelativeLayout>

Тогда в Activity onCreate() я делаю так:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Query the contacts
    mCursor = getContentResolver().query(Phones.CONTENT_URI, null, null, null, null);
    startManagingCursor(mCursor);

    ListAdapter adapter = new SimpleCursorAdapter(this,
            R.layout.row,
            mCursor, 
            new String[] { Phones.NAME, Phones.NUMBER}, 
            new int[] { R.id.text_name, R.id.text_phone });
    setListAdapter(adapter);
    getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
}

Результат выглядит так, как я хочу, но похоже, что список не знает, какой элемент выбран. Также мне нужно точно нажать на CheckBox. В примере List11 мне нужно только щелкнуть строку товара.

Итак, что мне нужно сделать, чтобы создать список с множественным выбором с моим настраиваемым представлением для каждой строки? Большое спасибо.

Ответы [ 9 ]

17 голосов
/ 17 февраля 2011

Вы должны создать свой собственный RelativeLayout, который реализует интерфейс Checkable и имеет ссылку на CheckBox или CheckedTextView (или список, если это режим с несколькими вариантами выбора).

Посмотрите на этот пост: http://www.marvinlabs.com/2010/10/29/custom-listview-ability-check-items/

7 голосов
/ 19 января 2011

Ответ Рахула Гарга хорош в первый раз, когда список загружается, если вы хотите, чтобы некоторые строки проверялись в зависимости от данных модели, но после этого вы должны обрабатывать события check / uncheck самостоятельно.

Вы можете переопределить onListItemCLick() из ListActivity, чтобы проверять / снимать отметки со строк

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);
    ViewGroup row = (ViewGroup)v;
 CheckBox check = (CheckBox) row.findViewById(R.id.checkbox);            
    check.toggle();
}

Если вы это сделаете, не устанавливайте ListView в CHOICE_MODE_MULTIPLE, потому что это вызывает странные вещи при вызове функции.

Чтобы получить список проверенных строк, вы должны реализовать метод самостоятельно, вызов getCheckItemIds() для ListView не работает:

ListView l = getListView();
int count = l.getCount();
for(int i=0; i<count; ++i) {
   ViewGroup row = (ViewGroup)l.getChildAt(i);
   CheckBox check = (Checked) row.findViewById(R.id.ck1);
   if( check.isChecked() ) {
      // do something
   }
}
5 голосов
/ 08 февраля 2013

Решение заключается в создании пользовательского представления, реализующего интерфейс Clickable.

public class OneLineCheckableListItem extends LinearLayout implements Checkable {

    public OneLineCheckableListItem(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    private boolean checked;


    @Override
    public boolean isChecked() {
        return checked;
    }

    @Override
    public void setChecked(boolean checked) {
        this.checked = checked; 

        ImageView iv = (ImageView) findViewById(R.id.SelectImageView);
        iv.setImageResource(checked ? R.drawable.button_up : R.drawable.button_down);
    }

    @Override
    public void toggle() {
        this.checked = !this.checked;
    }
}

И создайте пользовательский макет для элементов списка, используя новый виджет.

<?xml version="1.0" encoding="utf-8"?>
<ax.wordster.OneLineCheckableListItem xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="4dp"
    android:background="@drawable/selector_listitem"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/SelectImageView"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:src="@drawable/button_friends_down" />

    <TextView
        android:id="@+id/ItemTextView"
        android:layout_width="fill_parent"
        android:layout_height="60dp"
        android:gravity="center"
        android:text="@string/___"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textColor="@color/text_item" />

</ax.wordster.OneLineCheckableListItem>

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

5 голосов
/ 16 апреля 2010

Каждый такой вид имеет TextView и CheckBox.

Нет, это не так. Имеет CheckedTextView.

Так что мне нужно сделать, чтобы сделать список с множественным выбором с моим заказом просмотр каждой строки?

Попробуйте сделать значение CheckBox android:id равным "@android:id/text1" и посмотрите, поможет ли это. Это идентификатор, используемый Android для CheckedTextView in simple_list_item_multiple_choice.

1 голос
/ 22 декабря 2014

Мне очень пригодился этот маленький код: http://alvinalexander.com/java/jwarehouse/apps-for-android/RingsExtended/src/com/example/android/rings_extended/CheckableRelativeLayout.java.shtml

Это отличное дополнение к контенту @ ferdy182 http://www.marvinlabs.com/2010/10/29/custom-listview-ability-check-items/.

1 голос
/ 08 февраля 2013

Простой пример того, как заставить пользовательский макет работать как пользовательский флажок:

private class FriendsAdapter extends ArrayAdapter<WordsterUser> {
    private Context context;

    public FriendsAdapter(Context context) {
        super(context, R.layout.listitem_oneline);

        this.context = context;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final int pos = position;

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View rv = inflater.inflate(R.layout.listitem_oneline, parent, false);
        rv.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean checked = friendsListView.isItemChecked(pos); 
                friendsListView.setItemChecked(pos, !checked);
            }
        });

        WordsterUser u = getItem(position);

        TextView itw = (TextView) rv.findViewById(R.id.ItemTextView);
        itw.setText(u.userName + " (" + u.loginName + ")");

        ImageView iv = (ImageView) rv.findViewById(R.id.SelectButton);

        if (friendsListView.isItemChecked(position)) {
            iv.setImageResource(R.drawable.downbutton);
        } else {
            iv.setImageResource(R.drawable.upbutton);
        }

        return rv;
    }
}
1 голос
/ 22 ноября 2010

Это возможно по какой-то хитрости

в вашем ListActivtyClass в методе

protected void onListItemClick(ListView l, View v, int position, long id) {
//just set
<your_model>.setSelected(true);
}

теперь в вашем собственном адаптере

public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(textViewResourceId, parent, false);
        }       
        if (<your_model>.isSelected()) {
            convertView.setBackgroundColor(Color.BLUE);
        } else {
            convertView.setBackgroundColor(Color.BLACK);
        }
        return convertView;
    }

таким образом вы можете настроить вид в адаптере, когда элемент выбран в списке.

0 голосов
/ 09 февраля 2011

Я хочу подтвердить, что ответ Притама правильный. Вам нужно onClickListener для каждого элемента списка (определите его в getView() адаптера).

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

Опираясь на список onItemClickListener() - как кто-то посоветовал в другом потоке - не будет работать, поскольку CheckBox будет перехватывать событие щелчка, поэтому список не получит его.

И, наконец, @Rahul и JVitella:

Ситуация такова, что CheckBox в элементе списка должен быть активируемым и проверяемым независимо от самого элемента списка. Поэтому решение, как я только что описал выше.

0 голосов
/ 20 декабря 2010

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

...