Android: настраиваемый элемент ListView

1

Я искал решение этой проблемы в течение нескольких дней.

Я пытаюсь создать элемент списка ListView, который можно выбрать для массового редактирования. Это было бы похоже на приложение Gmail, в котором отображается электронное письмо в вашем почтовом ящике, и вы можете выбрать набор из них для действия (удалить, переместить и т.д.).

Мои требования:

  • Должен иметь индивидуальный вид. Макеты android.R.layout.simple_list_item_ [checked | multiple_choice] не подходят для того, что я ищу.
  • Я бы хотел, чтобы он работал с данными ListView # setChoiceMode и ListView # getCheckedItemPositions. Также CheckedTextView. (Альтернативный подход к этому был бы прекрасен)
  • Я хочу, чтобы флажки отображались, когда пользователь выбирает "режим редактирования",
  • Я хотел бы изменить параметры меню, похожие на Android Selection Mode

Я попытался добавить свой собственный флажок к моему представлению и установить OnClickListener, чтобы он пометил элементы списка как выбранные/не выбранные, но это не совсем работает для меня.

Любая помощь приветствуется; даже если он получает меня только на 90%.

Пожалуйста, имейте в виду, что я пытаюсь заставить это работать на Android версии 2.1 и выше.

спасибо

  • 0
    В итоге я просмотрел свой собственный вопрос после просмотра исходного кода Android, чтобы выяснить, что ListView отслеживает свое собственное состояние проверенного элемента и флажок не требуется. Я отмечу это как ответ, когда мне позволят. Спасибо всем за ваше время.
Теги:
checkbox
listview

3 ответа

3
Лучший ответ

Поэтому я считаю, что решил основную проблему, с которой я столкнулся.

Я считаю, что проблема, с которой я столкнулась, заключалась в том, что мое представление не представляло состояние ListView. В ламинах; Я думал, что нужно установить флажок, чтобы установить, был ли проверен элемент списка или нет (это во мне веб-разработчик). Тем не менее, ListView сохраняет свое состояние того, что проверено, а что нет, независимо от того, есть ли представление (CheckBox) для представления этого или нет.

макет /list_item.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linearLayout1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <ProgressBar
        android:id="@+id/progressBar1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="5dip" />

    <LinearLayout
        android:id="@+id/linearLayout2"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Line 1"
            android:textAppearance="?android:attr/textAppearanceMedium" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Line 2" />
    </LinearLayout>

    <CheckBox
        android:id="@+id/checkBox1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="false"
        android:focusable="false"
        android:visibility="gone" />

</LinearLayout>

Меню /menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/edit_menu_item"
        android:title="KAMEHAMEHA!!!!!"/>

</menu>

Меню /edit.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/commit_menu_item"
        android:title="Commit"/>
    <item
        android:id="@+id/cancel_menu_item"
        android:title="Cancel"/>

</menu>

ListViewTestActivity.java

package com.loesak.listviewtest;

import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class ListViewTestActivity extends ListActivity {
    private static final String[] GENRES = new String[] {
        "Action", "Adventure", "Animation", "Children", "Comedy", "Documentary", "Drama",
        "Foreign", "History", "Independent", "Romance", "Sci-Fi", "Television", "Thriller"
    };

    private ListView listView = null;
    private MyArrayAdapter myArrayAdapter = null;
    private boolean editMode = false;

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

        this.listView = getListView();
        this.myArrayAdapter = new MyArrayAdapter(this, GENRES);
        this.setListAdapter(this.myArrayAdapter);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        menu.clear();

        MenuInflater inflater = this.getMenuInflater();

        if(!this.editMode) {
            inflater.inflate(R.menu.menu, menu);
        } else {
            inflater.inflate(R.menu.edit, menu);
        }

        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if(item.getItemId() == R.id.edit_menu_item) {
            Toast.makeText(this, "entering edit mode", Toast.LENGTH_SHORT).show();

            this.editMode = true;
            this.listView.setItemsCanFocus(false);
            this.listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

            this.myArrayAdapter.setEditMode(editMode);
        } else if(item.getItemId() == R.id.commit_menu_item 
                || item.getItemId() == R.id.cancel_menu_item) {
            if(item.getItemId() == R.id.commit_menu_item) {
                Toast.makeText(this, "committing changes", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, "leaving edit mode", Toast.LENGTH_SHORT).show();
            }

            this.editMode = false;
            this.listView.setItemsCanFocus(true);
            this.listView.setChoiceMode(ListView.CHOICE_MODE_NONE);
            this.listView.clearChoices();

            this.myArrayAdapter.setEditMode(editMode);
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        if(!this.editMode) {
            Toast.makeText(this, "list item selected at position " + position, Toast.LENGTH_SHORT).show();
        } else {
            String str = "";
            SparseBooleanArray wtfit = l.getCheckedItemPositions();
            for(int i = 0; i < GENRES.length; i++) {
                if(wtfit.get(i)) {
                    str += i + ", ";
                }
            }

            Toast.makeText(this, "Selected item positions: " + str, Toast.LENGTH_SHORT).show();
        }

        super.onListItemClick(l, v, position, id);
    }

    class MyArrayAdapter extends ArrayAdapter<String> {
        private Context context;
        private String[] entires;

        private boolean editMode = false;

        public MyArrayAdapter(Context context, String[] entries) {
            super(context, R.layout.list_item, entries);

            this.context = context;
            this.entires = entries;
        }

        @Override
        public View getView(final int position, View view, ViewGroup parent) {
            final ListView listView = (ListView) parent;
            final ViewHolder viewHolder;

            if(view == null) {
                LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

                view = layoutInflater.inflate(R.layout.list_item, null, true);

                viewHolder = new ViewHolder();
                viewHolder.text1 = (TextView) view.findViewById(R.id.textView1);
                viewHolder.text2 = (TextView) view.findViewById(R.id.textView2);
                viewHolder.checkbox1 = (CheckBox) view.findViewById(R.id.checkBox1);

                view.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) view.getTag();
            }

            viewHolder.text1.setText(this.entires[position] + "_1");
            viewHolder.text2.setText(this.entires[position] + "_2");
            viewHolder.checkbox1.setChecked(listView.isItemChecked(position));

            if(this.editMode) {
                viewHolder.checkbox1.setVisibility(View.VISIBLE);
            } else {
                viewHolder.checkbox1.setVisibility(View.GONE);
            }

            return view;
        }

        public void setEditMode(boolean editMode) {
            this.editMode = editMode;
            this.notifyDataSetChanged();
        }

        class ViewHolder {
            TextView text1;
            TextView text2;
            CheckBox checkbox1;
        }
    }
}

Чтобы флажок отображал фактический выбранный режим элемента списка:

viewHolder.checkbox1.setChecked(listView.isItemChecked(position));

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

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

  • 0
    следуя вашей инструкции, по-прежнему получить нулевой элемент путем вызова getCheckedItemPositions .
  • 0
    @zionpi Это двухлетний ответ для более ранней версии Android, поэтому он, вероятно, не подходит для используемой версии Android.
6

Взгляните на эту ссылку

Это ресурс, который я прочитал, чтобы реализовать собственное собственное представление списка. Это было очень полезно для меня. Я думаю, вам нужно добавить флажок в файле list_item.xml и изменить атрибуты макета.

Вам также необходимо добавить слушателя к объекту CheckBox onCheckedChanged внутри настраиваемого адаптера.

Вот пример кода для пользовательского адаптера;

public class EntryAdapter extends ArrayAdapter<Entry> {

private Activity context;
private LayoutInflater inflater;
private ArrayList<Entry> entries;

public EntryAdapter(Activity context, ArrayList<Entry> objects) {
    super(context, R.layout.entry_item, objects);
    // TODO Auto-generated constructor stub
    this.context = context;
    this.entries = objects;
}

public View getView (int position,  View convertView, ViewGroup parent)
{
    View viewRow = convertView;
    if(viewRow == null)
    {                   
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);          
        viewRow = inflater.inflate(R.layout.entry_item , null, true);                       
    }

    Entry e = entries.get(position);
    if(e != null)
    {
        TextView aka = (TextView) viewRow.findViewById(R.id.authorTextView);
        TextView content = (TextView) viewRow.findViewById(R.id.entryContentTextView);

        if(aka != null && content != null){

            aka.setText(e.getAka());
            content.setText(e.getContent());
        }

    }


    return viewRow;

}

}

В этом коде нет прослушивателей событий. То, что вы должны в первую очередь сделать, это добавить arraylist boolean like

ArrayList<boolean> selectedItems;

после этого внутри метода getView вы должны добавить следующее:

CheckBox cb = (CheckBox) findViewById(R.id.checkBoxId);

после этого вы должны добавить слушателя onCheckStateChanged внутри метода getView()

cb.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
    {
        if ( isChecked )
        {
          // find out the item is selected or not and add to selected arraylist by using the position of the element
        }

}
});

и, наконец, у вас должен быть getSelectedMethod, который возвращает arraylist выбранных элементов в отношении их позиций.

Надеюсь, я пойму вопрос, и это будет полезно для вас.

  • 0
    Спасибо @arascanakin за ваш ответ. Я прошу прощения, если я не четко сформулировал проблему, которая у меня возникла. Моя проблема не в создании пользовательского представления списка. На самом деле, я уже этого не делаю (многострочный текст, изображения, флажки и т. Д.). Моя проблема с добавлением флажка и работой с уже встроенным ListView в режиме множественного выбора. Добавление флажка недостаточно для того, чтобы ListView знал, что был выбран определенный элемент.
  • 0
    @Ioesak проверить мой пост.
Показать ещё 5 комментариев
0

Как и в предыдущем посте:

Всякий раз, когда вы хотите выполнять обработку с помощью представлений в ListView, вам необходимо создать настраиваемый адаптер, который будет обрабатывать вашу логическую реализацию и передавать эту информацию в представлениях по мере необходимости.

Это отправная точка для того, что вам нужно. Каждая строка должна быть четко определена по мере создания ваших представлений. При нажатии на определенное представление вы обрабатываете определенную строку. Одна вещь, которую вы можете сделать, это нажать кнопку редактирования, вы должны взять все данные в этой строке и скрыть ее до другого представления, которое, как представляется, доступно для редактирования. Затем при подтверждении вы обновите эту строку и преобразуете ее обратно в исходное представление.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню