Steve Kamau
Steve Kamau

Reputation: 2785

How to place two recyclerviews in a navigation drawer fragment

So i have a recyclerview on my fragment in a navigation drawer and it works jus fine. However i would like to add a second recyclerview listing more items. This is achievable but the hard part is making the whole layout scroll together.

I have google it up an havent found anything helpful.I thought maybe one of you might have a work around.

Is this possible?

FragmentDrawer.java

public class FragmentDrawer extends Fragment {

    private static String TAG = FragmentDrawer.class.getSimpleName();

    private RecyclerView recyclerView;
    private ActionBarDrawerToggle mDrawerToggle;
    private DrawerLayout mDrawerLayout;
    private NavigationDrawerAdapter adapter;
    private View containerView;
    private static String[] titles = null;
    private FragmentDrawerListener drawerListener;

    public FragmentDrawer() {

    }

    public void setDrawerListener(FragmentDrawerListener listener) {
        this.drawerListener = listener;
    }

    public static List<NavDrawerItem> getData() {
        List<NavDrawerItem> data = new ArrayList<>();
        int[] icons = {R.drawable.home, R.drawable.ic_upcoming, R.drawable.ic_eventsaved, R.drawable.ic_wehappened, R.drawable.ic_persons};

        // preparing navigation drawer items
        for (int i = 0; i < titles.length && i < icons.length; i++) {
            NavDrawerItem navItem = new NavDrawerItem();
            navItem.setTitle(titles[i]);
            navItem.setIcon(icons[i]);
            data.add(navItem);
        }
        return data;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // drawer labels
        titles = getActivity().getResources().getStringArray(R.array.nav_drawer_labels);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflating view layout
        View layout = inflater.inflate(R.layout.fragment_navigation_drawer, container, false);
        recyclerView = (RecyclerView) layout.findViewById(R.id.drawerList);

        adapter = new NavigationDrawerAdapter(getActivity(), getData());
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new ClickListener() {
            @Override
            public void onClick(View view, int position) {
                drawerListener.onDrawerItemSelected(view, position);
                mDrawerLayout.closeDrawer(containerView);
            }

            @Override
            public void onLongClick(View view, int position) {

            }
        }));

        return layout;
    }


    public void setUp(int fragmentId, DrawerLayout drawerLayout, final Toolbar toolbar) {
        containerView = getActivity().findViewById(fragmentId);
        mDrawerLayout = drawerLayout;
        mDrawerToggle = new ActionBarDrawerToggle(getActivity(), drawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) {
            @Override
            public void onDrawerOpened(View drawerView) {
                super.onDrawerOpened(drawerView);
                getActivity().invalidateOptionsMenu();
            }

            @Override
            public void onDrawerClosed(View drawerView) {
                super.onDrawerClosed(drawerView);
                getActivity().invalidateOptionsMenu();
            }

            @Override
            public void onDrawerSlide(View drawerView, float slideOffset) {
                super.onDrawerSlide(drawerView, slideOffset);
                toolbar.setAlpha(1 - slideOffset / 2);
            }
        };

        mDrawerLayout.setDrawerListener(mDrawerToggle);
        mDrawerLayout.post(new Runnable() {
            @Override
            public void run() {
                mDrawerToggle.syncState();
            }
        });

    }

    public static interface ClickListener {
        public void onClick(View view, int position);

        public void onLongClick(View view, int position);
    }

    static class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {

        private GestureDetector gestureDetector;
        private ClickListener clickListener;

        public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ClickListener clickListener) {
            this.clickListener = clickListener;
            gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
                @Override
                public boolean onSingleTapUp(MotionEvent e) {
                    return true;
                }

                @Override
                public void onLongPress(MotionEvent e) {
                    View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
                    if (child != null && clickListener != null) {
                        clickListener.onLongClick(child, recyclerView.getChildPosition(child));
                    }
                }
            });
        }

        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {

            View child = rv.findChildViewUnder(e.getX(), e.getY());
            if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
                clickListener.onClick(child, rv.getChildPosition(child));
            }
            return false;
        }

        @Override
        public void onTouchEvent(RecyclerView rv, MotionEvent e) {
        }

        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

        }


    }

    public interface FragmentDrawerListener {
        public void onDrawerItemSelected(View view, int position);
    }

NavigationDrawerAdapter.java

public class NavigationDrawerAdapter extends RecyclerView.Adapter<NavigationDrawerAdapter.MyViewHolder> {
    List<NavDrawerItem> data = Collections.emptyList();
    private LayoutInflater inflater;
    private Context context;

    public NavigationDrawerAdapter(Context context, List<NavDrawerItem> data) {
        this.context = context;
        inflater = LayoutInflater.from(context);

        this.data = data;
    }

    public void delete(int position) {
        data.remove(position);
        notifyItemRemoved(position);
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = inflater.inflate(R.layout.nav_drawer_row, parent, false);
        MyViewHolder holder = new MyViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        NavDrawerItem current = data.get(position);
        holder.title.setText(current.getTitle());
        holder.imgViewIcon.setImageResource(current.getIcon());
    }

    @Override
    public int getItemCount() {
        return data.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder {
        TextView title;
        public ImageView imgViewIcon;

        public MyViewHolder(View itemView) {
            super(itemView);
            title = (TextView) itemView.findViewById(R.id.title);
            imgViewIcon = (ImageView) itemView.findViewById(R.id.item_icon);
        }
    }
}

strings.xml

<resources>

    <string name="nav_item_home">Home</string>
    <string name="nav_item_friends">Upcoming</string>
    <string name="nav_item_notifications">Saved</string>
    <string name="nav_item_main">weHappened</string>
    <string name="nav_item_planners">Event planners</string>

    <!-- navigation drawer item labels  -->
    <string-array name="nav_drawer_labels">
        <item>@string/nav_item_home</item>
        <item>@string/nav_item_friends</item>
        <item>@string/nav_item_notifications</item>
        <item>@string/nav_item_main</item>
        <item>@string/nav_item_planners</item>
    </string-array>

    <string name="title_messages">Events saved</string>
    <string name="title_friends">Upcoming events</string>
    <string name="title_home">Home</string>
    <string name="title_happened">Events weHappened</string>
    <string name="title_planners">Event planners</string>

</resources>

Upvotes: 1

Views: 751

Answers (1)

Mike
Mike

Reputation: 4570

Use a single RecyclerView if you like to list more items in the same list. There is no point in using 2 different RecyclerViews and you can't make them scroll together if these are one below the other.

If you want to add more items to the list dynamically, build an "update" method in your Adapter and call that method when you'd like to add more items and call notifyItemRangeChanged() (or the most appropriate methods given the the RecyclerView.Adapter class)

EDIT:

Assuming you have a RecyclerView set and you know how to initialize and set it up with a basic LinearLayoutManager, I would like to focus only on the adapter.

So if you'd like to separate 2 categories like "Main options" and "Other options" you may want to consider implementing your adapter for 2 view types. Here is a short code snippet on how to achieve that but this highlights only the idea of how to use multiple view types. You may want to modify it to your needs:

public class DrawerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private static final int VIEW_TYPE_HEADER = 0;
    private static final int VIEW_TYPE_REGULAR_ITEM = 1;

    private LayoutInflater mInflater;
    private List<Object> mItems;

    public DrawerAdapter(Context context) {
        mInflater = LayoutInflater.from(context);
        mItems = new ArrayList<>();
        mItems.add("Main options");
        mItems.add(new Item("Option1", R.drawable.icons_for_option_1))
        mItems.add(new Item("Option2", R.drawable.icons_for_option_2))
        mItems.add(new Item("Option2", R.drawable.icons_for_option_2))
        mItems.add(new Item("Option3", R.drawable.icons_for_option_3))
        mItems.add("Secondary options")
        mItems.add(new Item("Option4", R.drawable.icons_for_option_4))
        // And so on...whatever the logic is.
    }

    @Override
    public int getItemCount() {
        return mItems.size();
    }

    @Override
    public int getItemViewType(int position) {
        if (position == 0 || position == 5) { // Assuming that the topmost item and the 5th item are the section headers. This if statement can be simplified too.
            return VIEW_TYPE_HEADER;
        } else {
            return VIEW_TYPE_REGULAR_ITEM;
        }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == VIEW_TYPE_HEADER) {
            return new HeaderViewHolder(mInflater.inflate(R.layout.list_item_header, parent, false));
        } else {
            return new RegularItemViewHolder(mInflater.inflate(R.layout.list_item_regular, parent, false));
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof HeaderViewHolder) {
            ((HeaderViewHolder) holder).setup(mItems.get(position));
        } else if (holder instanceof RegularItemViewHolder) {
            ((RegularItemViewHolder) holder).setup(mItems.get(position));
        }
    }


    private static class RegularItemViewHolder extends RecyclerView.ViewHolder {

        private RegularItemViewHolder(View convertView) {
            super(convertView);
            // Initialize your views here. Let's say you will have a TextView and an icon here or whatever else.
        }

        public void setup(Item item) {
            // Update your views here, etc.
        }
    }

    private static class HeaderViewHolder extends RecyclerView.ViewHolder {

        TextView titleTextView;

        private HeaderViewHolder(View convertView) {
            super(convertView);
            titleTextView = convertView.findViewById(R.id.section_header);
        }

        public void setup(String sectionHeaderTitle) {
            yourTextView.setText(title);
        }
    }
}

And this would be it. Sorry for eventual mistakes, I didn't test the code.

Cheers!

Upvotes: 1

Related Questions