State_activated on pre Honeycomb Devices

Вы не можете использовать в качестве фона для элементов списка следующее состояние:

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

На устройствах Pre Honeycomb, потому что этот селектор не поддерживается там, и версия Android не отслеживает активированные элементы.

Как можно эмулировать такое поведение? Особенно при использовании смещений (список слева в одном фрагменте и в зависимости от того, что выбрано в виде подробного просмотра справа) этот показатель очень важен.

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

Ответы

Ответ 1

Я решил проблему, используя небольшой трюк: пропустив свойство state_checked, которое существует с Android версии 1, можно эмулировать поведение state_activated. Нет необходимости изменять адаптер List или сохранять состояние самостоятельно.

Я написал подробный пример, содержащий весь код, необходимый для переопределения и публикации в репозитории github.

Ответ 2

Многое, как предложил Крис Дженкинс, я просто добавляю небольшой код к моему переопределению getView:

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    // ...

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
        convertView.setBackgroundColor(Color.WHITE);
        if (listView.isItemChecked(position)) {
            convertView.setBackgroundColor(Color.LTGRAY);
        }
    }
}

Элемент, который проверяется или нет, автоматически обрабатывается в моем случае (используя CHOICE_MODE_MULTIPLE и v7 ActionMode.Callback с setOnItemLongClickListener, вызывающим обратный вызов)

Ответ 3

Просто измените фон выбранного элемента списка в вашем адаптере на "активированный".

Итак, в моем адаптере метод просмотра может выглядеть примерно так:

getView(int pos, View convertView, ViewGroup parent){
//... etc get view etc
    if(mSelectedItemPos == pos){
        v.setBackgroundDrawable(ctx.getResources().getDrawable(R.drawable.list_item_selected_state);
        //or v.setBackgroundResource(R.drawable.list_item.....);
    } else {
        v.setBackgroundDrawable(ctx.getResources().getDrawable(R.drawable.list_item_selector);            
    }
}

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

Ответ 4

Я сделал это вручную следующим образом:

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

public static boolean selectedStatus[];  // array to hold selected state
public static View oldView;        // view to hold so we can set background back to normal after 

Конструктор инициализирует массив

public class MyCursorAdapter extends SimpleCursorAdapter {
    private LayoutInflater mInflater;
    private int layout;

    public MyCursorAdapter(Context context, int layout, Cursor c,
        String[] from, int[] to, int flags) {
            super(context, layout, c, from, to, flags);
            mInflater = LayoutInflater.from(context);
            this.layout = layout;
            selectedStatus = new boolean[c.getCount()];
            for (int i = 0; i < c.getCount(); i++) {
            selectedStatus[i] = false;  // Start with all items unselected
        }
    }
} 

getView, необходимый для того, когда ребенок прокручивается вне поля зрения

@Override 
public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null)
         convertView = View.inflate(context, layout, null);

    if(selectedStatus[position] == true){
        v.setBackgroundResource(R.color.blue);                          
    } else {
        v.setBackgroundResource(R.color.black);
    }
    return v; 
} 

onItemClick изменить выбранный элемент в массиве и на экране

lv.setOnItemClickListener(new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view,
        int position, long id) {           

        mRowId = id;
        EventDisplayFragment eventdisplay = new EventDisplayFragment();
        getFragmentManager().beginTransaction()
                .replace(R.id.rightpane, eventdisplay).commit();
        if(MyCursorAdapter.oldView != null){
            MyCursorAdapter.oldView.setBackgroundResource(R.color.black);   // change the background of the old selected item back to default black                 }
        MyCursorAdapter.oldView = v;                                        // set oldView to current view so we have a reference to change back on next selection
        for (int i = 0; i < selectedStatus.length; i++) {
            if(i == position){                              // set the current view to true and all others to false
                    selectedStatus[i] = true;
                } else {
                    selectedStatus[i] = false;
                }
            }
        }
        v.setBackgroundResource(R.color.blue);
        return true;
    }
});