Android - сохранить элемент ListView выделенным после того, как на него нажали - PullRequest
36 голосов
/ 14 февраля 2012

Итак, у меня есть действие с 2 ListView виджетами, когда вы выбираете значение в первом, второе заполняется значениями, связанными с выбором в первом ListView.Этот механизм работает без проблем, но теперь я хочу, чтобы выбор пользователя оставался выделенным.Я прочитал большое количество вопросов, связанных с этой темой, и, кажется, есть множество способов, которыми можно это сделать, но после попытки 4-5 из них я все еще не могу заставить его работать.

У меня он работает на втором ListView с использованием android:listSelector="#CCCCCC" XML-атрибута, но, похоже, он стирается, как только в смесь вводится OnItemClickListener (как тот, который я использую на своем первом * 1008).*).

Пока вот что я получил:

Пользовательский OnItemClickListener Я нашел просмотр различных ответов по этой теме (слегка изменил его, чтобыдля загрузки моей информации второй ListView):

private class ItemHighlighterListener implements OnItemClickListener {

    private View oldSelection = null;

    public void clearSelection() {
        if(oldSelection != null) {
            oldSelection.setBackgroundColor(android.R.color.transparent);
        }
    }

    public void onItemClick(AdapterView<?> parent, View view, int pos, long id) {
        clearSelection();
        oldSelection = view;
        view.setBackgroundDrawable(view.getContext().getResources().getDrawable(R.drawable.list_selector));
        loadClubs(mXMLPortalOptions.getRegion(pos).getId());
        mClubList.setAdapter(new ArrayAdapter<String>(getApplicationContext(), R.layout.list_item_white, mClubs));
    }
}

Вот мой list_selector.xml файл:

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

    <item android:state_selected="true"><shape>
            <solid android:color="#CCCCCC" />
        </shape></item>

    <item android:state_selected="false"><shape>
            <solid android:color="#FFFFFF" />
        </shape></item>

</selector>

Метод (OnItemClick) вызывается и выполняется, но фон моего ListItem остается того же цвета: /

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

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

Ответы [ 11 ]

62 голосов
/ 14 февраля 2012

Поместите переменную позиции для выбранного элемента. Измените позицию в методе onItemClicked(). Проверьте выбранное положение в списке адаптеров внутри getView() и установите фон для выбранного элемента.

public class TestAdapter extends BaseAdapter
{
    private Context context;
    private ArrayList<TestList> testList;
    private int selectedIndex;
    private int selectedColor = Color.parseColor("#1b1b1b");

    public TestAdapter(Context ctx, ArrayList<TestList> testList)
    {
        this.context = ctx;
        this.testList = testList;
        selectedIndex = -1;
    }

    public void setSelectedIndex(int ind)
    {
        selectedIndex = ind;
        notifyDataSetChanged();
    }

    @Override
    public int getCount()
    {
        return testList.size();
    }

    @Override
    public Object getItem(int position)
    {
        return testList.get(position);
    }

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

    private class ViewHolder
    {
        TextView tv;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        View vi = convertView;
        ViewHolder holder;
        if(convertView == null)
        {
            vi = LayoutInflater.from(context).inflate(R.layout.test_list_item, null);
            holder = new ViewHolder();

            holder.tv = (TextView) vi;

            vi.setTag(holder);
        }
        else
        {
            holder = (ViewHolder) vi.getTag();
        }

        if(selectedIndex!= -1 && position == selectedIndex)
        {
            holder.tv.setBackgroundColor(Color.BLACK);
        }
        else
        {
            holder.tv.setBackgroundColor(selectedColor);
        }
        holder.tv.setText("" + (position + 1) + " " + testList.get(position).getTestText());

        return vi;
    }

}

Теперь установите переменную selectedIndex при нажатии элемента списка.

public class TestActivity extends Activity implements OnItemClickListener
{
    // Implemented onItemClickListener

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id)
    {
        adapter.setSelectedIndex(position);
    }
}
5 голосов
/ 11 июля 2013

Чтобы раскрыть великолепное решение Шайфула, вы можете не заставить его работать в вашей ситуации.

Если вы используете, чтобы весь ваш код был в public void onListItemClick(ListView l, View v, int index, long id), если вы используете фрагменты и вам нужно объявлять интерфейс вместо реализации OnListItemClickListener, или что бы то ни было причиной того, что ваша IDE генерирует ошибки, вам, возможно, придется обращаться к переменным и методы статически.

public static int selectedPosition = 0;
ArrayAdapter<Your_obj> adapter = null;

@Override
public void onListItemClick(ListView l, View v, int index, long id) {
    super.onListItemClick(l, v, index, id);

        selectedPosition = index;
        Your_adapter.setSelectedIndex(selectedPosition);
        adapter.notifyDataSetChanged();
}

А в Your_adapter:

private static int selectedIndex;

//public Your_adapter...

public static void setSelectedIndex(int ind) {
    selectedIndex = ind;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    WellHolder holder = null;

    if (null == convertView) {

                //set up your "holder"
    }

    if (position == selectedIndex) {
        convertView.setBackgroundColor(convertView.getResources().getColor(R.color.cyan));
    }
    else {
        convertView.setBackgroundColor(convertView.getResources().getColor(R.color.silver));
    }

    return convertView;
}

Некоторые другие различия заключаются в том, что вам не нужно инициализировать какие-либо переменные как «0» или «-1», а в вашей деятельности вызывается notifyDataSetChanged ().

Еще раз, спасибо за ваше решение @Shaiful. Это, безусловно, помогло мне сэкономить время, пытаясь настроить то, что по умолчанию в iOS работает на Android, при этом избегая выбора / элемента / фокусировки / нажатия / и т. Д.

4 голосов
/ 15 марта 2015

Я столкнулся с подобной проблемой. Это мое решение:

Сначала добавьте пользовательский селектор списка в список:

<ListView
    android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="fill_parent"
    android:listSelector="@drawable/listselector" />

Внутри listselector.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_accelerated="false"
        android:drawable="@drawable/bg" />
</selector>

И, наконец, нарисованный файл bg.xml с цветом вашего выделения:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#33b5e6"/>
</shape>
3 голосов
/ 15 января 2017

Я думаю, что самое лучшее и простое решение - это.Вам не нужно устанавливать какие-либо значения android:listSelector в самом ListView или вносить какие-либо изменения в адаптер.Вы не даже должны вызывать любой setSelection(position) в OnItemClickListener, так как он обрабатывается автоматически.

  1. Установите в свой ListView:

    android:choiceMode="singleChoice"
    
  2. Установить фон самого элемента списка:

    android:background="?android:attr/activatedBackgroundIndicator"
    
  3. То естьit.

Таким образом, вы получите поведение системы по умолчанию.Вот как это делается в стандартном макете android.R.layout.simple_list_item_activated_1.

2 голосов
/ 24 мая 2015
//create a list_itemselectorin drawable folder
//you will get the list item selected background color change once you select //the item

    <selector xmlns:android="http://schemas.android.com/apk/res/android">

        <!-- Focused State -->
        <item android:state_focused="true"><shape>
                <solid android:color="#66FFFFFF" />
            </shape></item>
        <!-- Pressed State -->

        <item android:state_pressed="true"><shape>
                <solid android:color="@color/Black" />
            </shape></item>

        <!-- Default State -->
        <item><shape>
                <solid android:color="@color/Black" />
            </shape></item>

    </selector>


    //create a list in layout folder
      <ListView
            android:id="@+id/mySlidingList"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:choiceMode="singleChoice"
            android:divider="@color/GrayHot"
            android:dividerHeight="1dip"
            android:listSelector="@drawable/list_itemselector"
            android:scrollbars="none" />

// И видим вывод.

2 голосов
/ 16 апреля 2013

lv.setSelector(R.drawable.highlighter);

положить highlighter.png изображение в папку для рисования
простейший способ выделить выбранный элемент в виде списка.

2 голосов
/ 14 февраля 2012

Я искал его две недели назад, и результат невозможен с помощью селектора с возможностью рисования.Для получения дополнительной информации читайте этот пост в блоге разработчиков Android: Сенсорный режим

В резюме: Только когда ваш палец находится на экране, элемент выбран.

Другая возможность заключается в том, чтобы сохранить выбранный элемент в переменной var и рисовать по-другому, используя ваш пользовательский адаптер, как говорит Шайфул.

0 голосов
/ 13 августа 2016

Чтобы подвести итог этого поста и, возможно, помочь кому-то еще в будущем, я предлагаю ответ:)

Сначала нам нужно создать файл res/drawable/list_item_background.xml со следующим содержимым:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:state_activated="true"
        android:drawable="@color/list_item_activated" />
    <item
        android:drawable="@color/list_item_default" />
</selector>

Конечно, укажите свои ресурсы для рисования.И вы также можете добавить другие <item> элементы с различными состояниями, такими как state_pressed, state_focused и т. Д.

Затем мы должны установить параметр background для нашего элемента элемента списка ViewGroup element (fires/layout/list_item_layout.xml) вот так:

android:background="@drawable/list_item_background"

Следующий шаг - изменение нашего пользовательского класса Adapter.Вот следующий фрагмент кода:

public class CustomAdapter extends BaseAdapter {
    private List<Item> items;
    private LayoutInflater itemInflater;        
    private int selectedIndex; // add this

    public CustomAdapter(Context c, List<Item> items) {
        this.items = items;
        this.itemInflater = LayoutInflater.from(c);
        selectedIndex = -1; // add this
    }

    /* add this */
    public void setSelectedIndex(int index) {
        selectedIndex = index;
        notifyDataSetChanged();
    }

    /* other adapter's stuff */

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if(convertView == null) {
            convertView = itemInflater.inflate(R.layout.list_item_layout, parent, false);
        }

        // add this
        convertView.setActivated(selectedIndex != -1 && position == selectedIndex);

        /* do some stuff */

        return convertView;
    }
}

Наконец, мы должны вызвать метод адаптера setSelectedIndex(position) в onItemClick(...) методе AdapterView.OnItemClickListener.

public class YourActivity extends Activity
        implements AdapterView.OnItemClickListener {

    private CustomAdapter mCustomAdapter;

    /* activity implementation */

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        mCustomAdapter.setSelectedIndex(position);
    }
}

Теперь мы можембудьте удовлетворены правильной подсветкой пунктов списка:)

PS Если мы хотим включить режим множественного выбора в нашем списке, мы просто поместим следующую строку в наш класс деятельности, где хранится экземпляр listView:

listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

Таким образом, мы получим правильное выделение нескольких элементов.

- надеюсь, это кому-нибудь поможет:)

0 голосов
/ 20 мая 2016

Чтобы сохранить элементы списка (множественный выбор) выделенными, при щелчке (активировании) следуйте инструкциям.

1. Установить фон для макета элемента списка как нарисованного.

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:background="@drawable/list_item_selector">

        <ImageView
            android:id="@+id/icon"
            android:layout_width="22px"
            android:layout_height="22px"
            android:layout_marginLeft="4px"
            android:layout_marginRight="10px"
            android:layout_marginTop="4px"
            android:src="@mipmap/ic_launcher" >
        </ImageView>

        <TextView
            android:id="@+id/label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@+id/label"
            android:textSize="20px" >
        </TextView>
    </LinearLayout>

2. селектор для рисования

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

<item android:state_pressed="true"     android:drawable="@android:color/holo_red_light" />

<item android:state_activated="true" android:drawable="@android:color/holo_orange_dark" />

</selector>

3. Режим просмотра списка множественного выбора

getListView () setChoiceMode (ListView.CHOICE_MODE_MULTIPLE);.

При нажатии : enter image description here

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

При активации : enter image description here

0 голосов
/ 01 февраля 2016

Существует простое полностью XML-решение, которое сработало для меня.Во-первых, определите XML-drawable с помощью кода селектора, в котором «нормальное» состояние будет соответствовать «выбранному неотжатому» визуальному состоянию элемента списка, а state_pressed = true для «нажатого» визуального состояния.Пример файла "custom_item_selector.xml", напоминающего выделение Holo blue:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <solid
                android:color="#643292ff">
            </solid>
            <stroke
                android:width="1dp"
                android:color="#c83292ff">
            </stroke>
        </shape>
    </item>
    <item>
        <shape android:shape="rectangle">
            <solid
                android:color="#323292ff">
            </solid>
            <stroke
                android:width="1dp"
                android:color="#783292ff">
            </stroke>
        </shape>
    </item>
</selector>

(также может установить фокусное состояние).Во-вторых, примените этот xml-drawable в качестве ListSelector ListView и установите его желаемый choiceMode:

<ListView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/listView"
            android:choiceMode="singleChoice"
            android:listSelector="@drawable/custom_item_selector"/>

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

...