简体   繁体   中英

state_activated on pre Honeycomb Devices

You can not use the following state drawable as background for listview items.

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

On Pre Honeycomb Devices because this selector is not supported there and the android version does not keep track of the activated item(s).

How can this behaviour be emulated? Especially when using fragements (list on the left in one fragment and depending on what is selected a detail view on the right) this indicator is very important.

I know that this question was asked before here but the accepted answer there links to a blog article which states in "Step 4" that there is no possibility to have the activated indicator and instead only disables the use to prevent errors. This leads to the fact that no indicator is displayed which is what I'm searching for.

I solved the problem using a small trick: By missusing the state_checked property, which exists since Android Version 1, it is possible to emulate the state_activated behaviour. There is no need to modify the List adapter or save the state yourself.

I wrote a detailed example containing all code necessary to repoduce and published it on a github repository .

Much Like Chris Jenkins suggested, I just add a little code to my getView override:

@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);
        }
    }
}

The item being checked or not was automatically handled in my case (using CHOICE_MODE_MULTIPLE and v7 ActionMode.Callback with setOnItemLongClickListener calling the callback)

Just change the background of the selected list item in your adapter to a 'activated' drawable.

So in my adapter get view method might look a little like this:

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

Thats all i do if i want to support selected/activated states on views. Little more work but can be as flexible as you want.

I've done it manually in the following manner before:

Create an array to hold the selected state of the list, initialize it in the adapter constructor, then reference that in your getView method (in case the currently selected item scrolls out of view) and your onItemClick method (to change the current selection and turn off the old one).

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 

Constructor initialize the array

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 needed for when the child scrolls out of view

@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 change selected item in array and on screen

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM