سؤال

I'm trying to add a selector to my expandable listview

I have a background, text color and and image that I need to change state when the item is selected

here's my layout for the group item

<?xml version="1.0" encoding="utf-8"?>
<com.example.views.CheckedRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="48dp"
    android:background="@color/selector_menu_item_bg"
    android:minHeight="48dp"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/ic_menu"
        android:layout_width="24dp"
        android:layout_height="24dp"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:layout_marginLeft="15dp"
        android:background="@color/selector_menu_item_pic" />

    <com.example.views.CheckedTextView
        android:id="@+id/txt_menu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="15dp"
        android:layout_toRightOf="@+id/ic_menu"
        android:text="Dashboard"
        android:textColor="@color/selector_menu_item_txt"
        android:textSize="16dp" />

    <ImageView
        android:id="@+id/ic_drop_down_arrow"
        android:layout_width="16dp"
        android:layout_height="16dp"
        android:layout_centerVertical="true"
        android:layout_marginRight="20dp"
        android:layout_alignParentRight="true"
        android:src="@drawable/ic_play_down" />

</com.example.views.CheckedRelativeLayout>

here are my selectors :

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

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:color="@color/turquoise"/>
    <item android:state_selected="true" android:color="@color/turquoise"/>
    <item android:state_checked="true" android:color="@color/turquoise"/>
    <item android:state_activated="true" android:color="@color/turquoise"/>
    <item android:color="@color/blue_grey"/>
</selector>

and for the imageView I use this:

private StateListDrawable getStatesForPageId(PageId pageId) {
        StateListDrawable states = new StateListDrawable();
        switch (pageId) {
        case HOME:
            states.addState(
                    new int[] { android.R.attr.state_pressed },
                    context.getResources().getDrawable(
                            R.drawable.ic_menu_dashboard_active));
            states.addState(
                    new int[] { android.R.attr.state_activated },
                    context.getResources().getDrawable(
                            R.drawable.ic_menu_dashboard_active));
            states.addState(
                    new int[] { android.R.attr.state_checked },
                    context.getResources().getDrawable(
                            R.drawable.ic_menu_dashboard_active));
            states.addState(
                    new int[] {},
                    context.getResources().getDrawable(
                            R.drawable.ic_menu_dashboard));
            break;

        case PAGE_1:
            states.addState(
                    new int[] { android.R.attr.state_pressed },
                    context.getResources().getDrawable(
                            R.drawable.ic_menu_transfer_active));
            states.addState(
                    new int[] { android.R.attr.state_activated },
                    context.getResources().getDrawable(
                            R.drawable.ic_menu_transfer_active));
            states.addState(
                    new int[] { android.R.attr.state_checked },
                    context.getResources().getDrawable(
                            R.drawable.ic_menu_transfer_active));
            states.addState(
                    new int[] {},
                    context.getResources().getDrawable(
                            R.drawable.ic_menu_transfer));
            break; 
 }
}

The pressed state works however it doesn't keep the state when pressed.

For the moment I use

listMenu.setItemChecked(selectedMenuItem, true);

but with no luck, on android 4.4 I have the background that stays highlighted but not the textview nor the imageView. On api 8, not even the background is hightlighted.

I've had a look at this https://github.com/theomega/ActivatedStateDemo However I couldn't get it to work with an expandable listview

هل كانت مفيدة؟

المحلول

Setting up the adapter

        ArrayList<MenuRow> menu = new ArrayList<MenuRow>();
    menu.add(new MenuChild(MenuPosition.DASHBOARD, getString(R.string.dashboard)));
    menu.add(new MenuChild(MenuPosition.HISTORY, getString(R.string.history)));
    MenuGroup group= new MenuGroup(MenuPosition.MY_GROUP,
            getString(R.string.my_group));
    group.items.add(new MenuChild(MenuPosition.CHILD_ITEM,
            getString(R.string.child_item)));
    group.items.add(new MenuChild(MenuPosition.CHILD_ITEM_2,
            getString(R.string.child_item2)));
    menu.add(group);
    menu.add(new MenuChild(MenuPosition.SETTINGS, getString(R.string.settings)));

    adapter = new MenuAdapter(context, menu);
    myExpandableListView.setAdapter(adapter);

The adapter

public class MenuAdapter extends BaseExpandableListAdapter {

    private Context context;
    private ArrayList<MenuRow> menu;
    private int selectedGroupIndex = 0;
    private int selectedChildIndex = 0;

    public MenuAdapter(Context context, ArrayList<MenuRow> menu) {
        this.context = context;
        this.menu = menu;
    }

    public void setSelectedGroupIndex(int selectedGroupIndex) {
        this.selectedGroupIndex = selectedGroupIndex;
        notifyDataSetChanged();
    }

    public boolean isGroupSelected(int position) {
        return position == selectedGroupIndex;
    }

    public int getSelectedGroupIndex() {
        return selectedGroupIndex;
    }

    public void setSelectedChildIndex(int selectedChildIndex) {
        this.selectedChildIndex = selectedChildIndex;
        notifyDataSetChanged();
    }

    public boolean isChildSelected(int position) {
        return position == selectedChildIndex;
    }

    public int getSelectedItemIndex() {
        return selectedChildIndex;
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        MenuRow row = menu.get(groupPosition);
        if (row.isShownAsGroup()) {
            ArrayList<MenuChild> childs = ((MenuGroup) row).getItems();
            return childs.get(childPosition);
        } else {
            return null;
        }
    }

    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

    public View getChildView(int groupPosition, int childPosition,
            boolean isLastChild, View view, ViewGroup parent) {
        MenuChild child = (MenuChild) getChild(groupPosition, childPosition);
        if (view == null) {
            LayoutInflater infalInflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = infalInflater.inflate(R.layout.menu_child_item, null);
        }

        TextView txtMenu = (TextView) view.findViewById(R.id.txt_menu);
        txtMenu.setText(child.getTitle());

        if (groupPosition == selectedGroupIndex
                && childPosition == selectedChildIndex) {
            txtMenu.setTextColor(context.getResources().getColor(
                    R.color.turquoise));
        } else {
            txtMenu.setTextColor(context.getResources().getColor(
                    R.color.blue_grey));
        }
        return view;
    }

    public int getChildrenCount(int groupPosition) {
        MenuRow row = menu.get(groupPosition);
        if (row.isShownAsGroup()) {
            return ((MenuGroup) row).items.size();
        } else {
            return 0;
        }
    }

    public Object getGroup(int groupPosition) {
        return menu.get(groupPosition);
    }

    public int getGroupCount() {
        return menu.size();
    }

    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    @SuppressWarnings("deprecation")
    @SuppressLint("NewApi")
    public View getGroupView(int groupPosition, boolean isLastChild, View view,
            ViewGroup parent) {
        MenuRow row = menu.get(groupPosition);
        MenuPosition menuPosition = row.getMenuPosition();

        if (view == null) {
            LayoutInflater inf = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inf.inflate(R.layout.menu_group_item, null);
        }
        RelativeLayout rootLayout = (RelativeLayout) view
                .findViewById(R.id.root_layout);
        TextView txtMenuItem = (TextView) view.findViewById(R.id.txt_menu);
        ImageView icon = (ImageView) view.findViewById(R.id.ic_menu);
        ImageView dropDownMenuIndicator = (ImageView) view
                .findViewById(R.id.ic_drop_down_arrow);

        txtMenuItem.setText(row.getTitle());



        if (row.isShownAsGroup()) {
            dropDownMenuIndicator.setVisibility(View.VISIBLE);
        } else {
            dropDownMenuIndicator.setVisibility(View.GONE);
        }

        StateListDrawable iconStates;
        if (groupPosition == selectedGroupIndex) {
            boolean isActive = true;

                // Needed for correct images onPressedStates
            txtMenuItem.setTextColor(getTextStates(isActive));
            iconStates = getIconStates(menuPosition, isActive);

            rootLayout.setBackgroundColor(context.getResources().getColor(
                    R.color.light_grey));

        } else {
            boolean isActive = false;

                // Needed for correct images onPressedStates
            txtMenuItem.setTextColor(getTextStates(isActive));
                    iconStates = getIconStates(menuPosition, isActive);


            rootLayout.setBackgroundColor(context.getResources().getColor(
                    R.color.white));

        }

        if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) {
            icon.setBackgroundDrawable(iconStates);
        } else {
            icon.setBackground(iconStates);
        }

        return view;
    }

    public boolean hasStableIds() {
        return true;
    }

    public boolean isChildSelectable(int arg0, int arg1) {
        return true;
    }

    private ColorStateList getTextStates(boolean isActive) {

        int ressourceId = 0;
        if (isActive) {
            ressourceId = R.color.selector_menu_item_txt_selected;
        } else {
            ressourceId = R.color.selector_menu_item_txt;
        }

        return context.getResources().getColorStateList(ressourceId);
    }

    private StateListDrawable getIconStates(MenuPosition menuPosition,
            boolean isActive) {
        StateListDrawable states = new StateListDrawable();
        switch (menuPosition) {
        case DASHBOARD:
            states.addState(
                    new int[] { android.R.attr.state_pressed },
                    context.getResources().getDrawable(
                            R.drawable.ic_menu_dashboard_active));
            if (isActive) {
                states.addState(new int[] {}, context.getResources()
                        .getDrawable(R.drawable.ic_menu_dashboard_active));
            } else {
                states.addState(new int[] {}, context.getResources()
                        .getDrawable(R.drawable.ic_menu_dashboard));
            }

            break;

        case HISTORY:
            states.addState(
                    new int[] { android.R.attr.state_pressed },
                    context.getResources().getDrawable(
                            R.drawable.ic_menu_history_active));
            if (isActive) {
                states.addState(new int[] {}, context.getResources()
                        .getDrawable(R.drawable.ic_menu_history_active));
            } else {
                states.addState(new int[] {}, context.getResources()
                        .getDrawable(R.drawable.ic_menu_history));
            }
            break;
        case SETTINGS:
            states.addState(
                    new int[] { android.R.attr.state_pressed },
                    context.getResources().getDrawable(
                            R.drawable.ic_menu_settings_active));
            if (isActive) {
                states.addState(new int[] {}, context.getResources()
                        .getDrawable(R.drawable.ic_menu_settings_active));
            } else {
                states.addState(new int[] {}, context.getResources()
                        .getDrawable(R.drawable.ic_menu_settings));
            }
            break;
        default:
            break;
        }
        return states;

    }

}

MenuPosition Enum

public enum MenuPosition {
    DASHBOARD(0, -1), HISTORY(1, -1), SETTINGS(2, -1);

    private final int childPosition;
    private final int groupPosition;

    MenuPosition(int groupPosition, int childPosition) {
        this.groupPosition = groupPosition;
        this.childPosition = childPosition;
    }

    public int getGroupIndex() {
        return groupPosition;
    }

    public int getChildIndex() {
        return childPosition;
    }

}

The getIconStates and getTextStates are for if you want to add other states than just selected/unselected, in my case I wanted to add state_pressed

I tried using a ColorStateList but with no avail so I used this workaround

selector_menu_item_txt

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:color="@color/turquoise"/>
    <item android:color="@color/blue_grey"/>

</selector>

selector_menu_item_txt_selected

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/turquoise"/>
</selector>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top