Search code examples
androidselectionmaster-detailgetview

Master Detail Flow .. selection on rotate broken after override of getView


I'm trying to user the standard Master Detail Flow from Android Studio but I want to replace the List items on the left with a custom View.

I'm able to do this just fine by creating my own adapter and then overriding the getView() method and returning the custom Layout that I want to represent each item.

As soon as I do this though, the listSelector doesn't remember the selected item when I rotate the device. I'm obviously not implementing something correctly when I override the getView() method for the Adapter but I can't seem to figure out what.


Solution

  • You can save current position and restore it from onCreateView.

       private int currentCheckedPosition = 0;
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        ...
        listView.setOnItemClickListener(menuListener);
        listView.setItemChecked(currentCheckedPosition, true);
        ...
    }
    
    private AdapterView.OnItemClickListener menuListener = new AdapterView.OnItemClickListener()
    {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                listView.setItemChecked(currentCheckedPosition = position, true);
                ...
        }
    };
    


    UPD
    This should work. Replace code in ItemListFragment

    public class ItemListFragment extends Fragment
    {
    //    private int mActivatedPosition = ListView.INVALID_POSITION; //if you want to nothing selected on activity start
        private int mActivatedPosition = 0;//if you want to first item selected on activity start
        private ListView listView;
    
        @Override
        public void onAttach(Activity activity) {
            setRetainInstance(true);
            super.onAttach(activity);
            if (!(activity instanceof Callbacks)) {
                throw new IllegalStateException("Activity must implement fragment's callbacks.");
            }
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            ContentAdapter mAdapter = new ContentAdapter(getActivity(), android.R.layout.simple_list_item_activated_1, android.R.id.text1, DummyContent.ITEMS);
            View view = inflater.inflate(R.layout.fancy_activity_list, container, false);
            listView = (ListView) view.findViewById(android.R.id.list);
            listView.setAdapter(mAdapter);
            listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
            listView.setItemChecked(mActivatedPosition, true);
            listView.setOnItemClickListener(itemClickListener);
            return view;
        }
        private AdapterView.OnItemClickListener itemClickListener = new AdapterView.OnItemClickListener()
        {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                listView.setItemChecked(mActivatedPosition = position, true);
                if (getActivity() instanceof Callbacks) {
                    ((Callbacks) getActivity()).onItemSelected(DummyContent.ITEMS.get(position).id);
                }
            }
        };
    
        public interface Callbacks
        {
            void onItemSelected(String id);
        }
    }
    

    layout/fancy_activity_list_item

    <?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="match_parent"
        android:background="?android:attr/activatedBackgroundIndicator"
        android:orientation="vertical">
    
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Some Content Here"/>
    
    </LinearLayout>
    

    ContentAdapter

    public class ContentAdapter extends ArrayAdapter<DummyContent.DummyItem>
    {
        private LayoutInflater mInflater;
    
        public ContentAdapter(Context context, int resource, int textViewResourceId, List<DummyContent.DummyItem> objects) {
            super(context, resource, textViewResourceId, objects);
            mInflater = LayoutInflater.from(getContext());
        }
    
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view;
            if (convertView == null) {
                view = mInflater.inflate(R.layout.fancy_activity_list_item, parent, false);
            } else {
                view = convertView;
            }
            DummyContent.DummyItem dummyItem = getItem(position);
            TextView textView = (TextView) view.findViewById(R.id.textView);
            textView.setText(dummyItem.content);
            return view;
        }
    }
    

    And you need to set minSdkVersion 14 in build.gradle
    It needed to set android:background="?android:attr/activatedBackgroundIndicator" to list Item layout.