Navigation drawer selector disable not working

630 views Asked by At

I need to disable the second element in my navigation drawer until a certain task is finished. Here is how I disable the second element:

nav_item_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/dark_green"
        android:state_pressed="true" />
    <item android:drawable="@android:color/transparent"
        android:state_enabled="true" />
    <item android:drawable="@android:color/darker_gray"
        android:state_enabled="false" />
</selector>

nav_fragment.xml (wrapped in a DrawerLayout)

<ListView
    android:id="@+id/left_drawer"
    android:layout_width="@dimen/nav_drawer_width"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:cacheColorHint="#0000"
    android:background="@drawable/gradient_radial_backround"
    android:choiceMode="singleChoice"
    android:divider="@color/green_light"
    android:dividerHeight="1dp" />

nav_list_item.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/nav_list_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/nav_item_selector"
    android:orientation="horizontal"
    android:padding="@dimen/standard_padding">

    <ImageView
        android:id="@+id/nav_list_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="@null"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:id="@+id/nav_list_text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fontFamily="sans-serif-light"
        android:gravity="center_vertical"
        android:minHeight="@dimen/listPreferredItemHeightSmall"
        android:paddingLeft="@dimen/activity_horizontal_small_margin"
        android:text="List Item"
        android:textSize="@dimen/text_nav_list_entry"
        android:textColor="@color/dark_green" />
</LinearLayout>

Activity:

public class NavItemAdapter extends ArrayAdapter<String> {
        LayoutInflater inflater;
        private String[] listItems;

        public NavItemAdapter(Context context, int textViewResourceId, String[] listItems) {
            super(context, textViewResourceId, listItems);
            this.listItems = listItems;
            inflater = LayoutInflater.from(context);
        }

        @Override
        public boolean isEnabled(int position)
        {
            if(position == 1)
                return false;
            else
                return true;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null)
                convertView = new NavItemView(getContext());

            NavItemView navItemView = (NavItemView) convertView;

            switch (position) {
                case 0:
                    navItemView.setUpItem(R.drawable.ic_nav_1_checked, listItems[position], R.drawable.ic_nav_1);
                    break;
                case 1:
                    navItemView.setUpItem(R.drawable.ic_nav_2_checked, listItems[position], R.drawable.ic_nav_2);
                    break;
                case 2:
                    navItemView.setUpItem(R.drawable.ic_nav_3_checked, listItems[position], R.drawable.ic_nav_3);
                    break;
                case 3:
                    navItemView.setUpItem(R.drawable.ic_nav_4_checked, listItems[position], R.drawable.ic_nav_4);
                    break;
                case 4:
                    navItemView.setUpItem(R.drawable.ic_nav_5_checked, listItems[position], R.drawable.ic_nav_5);
                    break;
                case 5:
                    navItemView.setUpItem(R.drawable.ic_nav_6_checked, listItems[position], R.drawable.ic_nav_6);
                    break;
            }

            return convertView;
        }
    }

    class NavItemView extends LinearLayout implements Checkable {

        private View v;
        private ImageView iconView;
        private TextView textView;
        private Boolean checked = false;
        private int mImageChecked;
        private int mImage;

        public NavItemView(Context context) {
            super(context);

            LayoutInflater inflater = LayoutInflater.from(context);
            v = inflater.inflate(R.layout.list_item_navdrawer, this, true);
            assert v != null;
            iconView = (ImageView) v.findViewById(R.id.nav_list_icon);
            textView = (TextView) v.findViewById(R.id.nav_list_text);
        }

        @Override
        public boolean isChecked() {
            return checked;
        }

        @Override
        public void setChecked(boolean checked) {
            this.checked = checked;

            if (isChecked()) {
                setBackgroundColor(getResources().getColor(R.color.transparent));
                textView.setTextColor(getResources().getColor(R.color.light_pink));
                iconView.setImageResource(mImageChecked);
            } else {
                //Reset to default
                setBackgroundColor(getResources().getColor(R.color.transparent));
                textView.setTextColor(getResources().getColor(R.color.green_lighter));
                iconView.setImageResource(mImage);
            }
        }

        @Override
        public void toggle() {
            checked = !checked;
        }

        private void setUpItem(int imageChecked, String title, int image) {
            mImageChecked = imageChecked;
            mImage = image;
            textView.setText(title);
            iconView.setImageResource(image);
        }

    }

What happens is the item is disabled, but the selector does not kick in (it stays the same colour). Not only that but that item's divider disappears which is even worse! What is happening here?

1

There are 1 answers

0
Daniel Wilson On BEST ANSWER

I actually can't believe this but the only solution seems to be a bit of a weird hack. There are several threads on this question but the only solid answer I've found is from user Jason Lin located here.

It seems there were two pieces of the puzzle missing, the first is that returning false for the item I want to disable in isEnabled() merely makes the item unclickable and unfocusable. To actually disable it I need to perform the same check in getView() and call setEnabled(false) on the item...

if(position == 1)
   convertView.setEnabled(false);

AND

Set android:duplicateParentState="true" on the linear layout of the row.

This was the most important part as obviously I tried to called setEnabled(false) in getView() first of all, but it took me all day to learn I need the combination of all 3 of these things - returning false in isEnabled(), setting enabled to false in getView(), and setting duplicateParentState to true :)