9

I am using a RecyclerView to display my drawer list item in my Navigation Drawer. OnClick of the drawer list item, I am able to open different activities, however I would like to be able to open fragments which will be replacing the main activity layout.

Is there a way to do this?

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

    public AdapterClass(Context context, List<Information> data) {
        this.context = context;

        inflater = LayoutInflater.from(context);
        this.data = data;
    }

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

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        Information current = data.get(position);
        holder.title.setText(current.title);
        holder.icon.setImageResource(current.iconId);

    }

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

    class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        TextView title;
        ImageView icon;

        public MyViewHolder(View itemView) {
            super(itemView);
            context = itemView.getContext();
            title = (TextView) itemView.findViewById(R.id.listText);
            icon = (ImageView) itemView.findViewById(R.id.listIcon);
            itemView.setClickable(true);
            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {

            final Intent intent;
            switch (getPosition()) {
                case 0:
                    intent = new Intent(context, next.class);
                    break;

                case 1:
                    intent = new Intent(context, next.class);
                    break;

                case 2:
                    intent = new Intent(context, next.class);
                    break;
                default:
                    intent = new Intent(context, next.class);
                    break;
            }
            context.startActivity(intent);
        }
    }
};

MainActivity.java

public class MainActivity extends ActionBarActivity {

    private Toolbar toolbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        toolbar = (Toolbar) findViewById(R.id.app_bar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayShowHomeEnabled(true);
        NavigationDrawerFragment drawerFragment = (NavigationDrawerFragment)
                getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
        drawerFragment.setUp(R.id.fragment_navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout), toolbar);
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

NavigationDrawerFragment.java

public class NavigationDrawerFragment extends Fragment {
    private ActionBarDrawerToggle mDrawerToggle;
    private DrawerLayout mDrawerLayout;
    private boolean mUserLearnedDrawer;
    private boolean mFromSavedInstanceState;
    public static final String PREF_FILE_NAME = "testpref";
    public static final String KEY_USER_LEARNED_DRAWER = "user_learned_drawer";
    private View containerView;
    private AdapterClass adapter;
    private RecyclerView recyclerView;

    public NavigationDrawerFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mUserLearnedDrawer = Boolean.valueOf(readFromPreferences(getActivity(), KEY_USER_LEARNED_DRAWER, "false"));
        if (savedInstanceState != null) {
            mFromSavedInstanceState = true;
        }
    }

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

        adapter = new AdapterClass(getActivity(), getData());
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        return layout;
    }

    public static List<Information> getData() {
        List<Information> data = new ArrayList<>();
        int[] icons = {R.drawable.ic_menu_check, R.drawable.ic_menu_check, R.drawable.ic_menu_check, R.drawable.ic_menu_check};
        String[] titles = {"My Cart", "Lotion", "Deodorants", "Gels"};

        for (int i = 0; i < titles.length && i < icons.length; i++) {
            Information current = new Information();
            current.iconId = icons[i];
            current.title = titles[i];
            data.add(current);
        }
        return data;
    }

    public void setUp(int fragmentId, DrawerLayout drawerLayout, 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);
                if (!mUserLearnedDrawer) {
                    mUserLearnedDrawer = true;
                    saveToPreferences(getActivity(), KEY_USER_LEARNED_DRAWER, mUserLearnedDrawer + "");
                }

            }


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


            }

        };
        if (!mUserLearnedDrawer && !mFromSavedInstanceState) {
            mDrawerLayout.openDrawer(containerView);
        }
        mDrawerLayout.setDrawerListener(mDrawerToggle);
        mDrawerLayout.post(new Runnable() {
            @Override
            public void run() {
                mDrawerToggle.syncState();
            }
        });
    }


    @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    public static void saveToPreferences(Context context, String preferenceName, String preferenceValue) {
        SharedPreferences sharedPreferences = context.getSharedPreferences(PREF_FILE_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString(preferenceName, preferenceValue);
        editor.apply();
    }

    public static String readFromPreferences(Context context, String preferenceName, String defaultValue) {
        SharedPreferences sharedPreferences = context.getSharedPreferences(PREF_FILE_NAME, Context.MODE_PRIVATE);
        return sharedPreferences.getString(preferenceName, defaultValue);
    }
}
Satan Pandeya
  • 3,747
  • 4
  • 27
  • 53
Steve Kamau
  • 2,755
  • 10
  • 42
  • 73
  • Replace your existing `onClick()` logic to start an activity with corresponding logic to `commit()` a `FragmentTransaction`. See the sample apps here: https://github.com/commonsguy/cw-omnibus/tree/master/NavDrawer – CommonsWare Mar 11 '15 at 11:04
  • @CommonsWare your example is implementing the OnitemclickListener in the main Activity and i am doing it in my adapter.Is it the same thing done differently? – Steve Kamau Mar 11 '15 at 11:14
  • My example is using `ListView`, not `RecyclerView`. The difference does not really matter. Somewhere, you have a method that is will be invoked when the user clicks on the desired thing. In there, if you want to change fragments, you need to `commit()` a `FragmentTransaction`. – CommonsWare Mar 11 '15 at 11:16
  • are you facing the error in onClick method? where you are trying to navigate to different classes? – keshav kowshik Mar 11 '15 at 11:41
  • @Kesh1234 the OnClick method works fine when opening different classes.However i am trying to open different fragments to be replacing the main activity.Does that make sense to you? – Steve Kamau Mar 11 '15 at 11:45
  • @SteveKamau Yes, Have you written code for replacing different fragments to Main Activity. I cannot see that in your post. like the nextFragment method in answer1 – keshav kowshik Mar 11 '15 at 11:50
  • @Kesh1234 That's where i am stuck.I have tried the code below from answer 1 and i am getting canot be resolved on `getActivity()` which requires i make a getter or a property for it – Steve Kamau Mar 11 '15 at 11:57
  • @SteveKamau http://stackoverflow.com/questions/20176999/how-to-switch-between-fragments-during-onclick.. check this and let me know this can help you. – keshav kowshik Mar 11 '15 at 12:27
  • @SteveKamau Hi, what did you do with this problem? I'm currently facing it right now, hope you can help. Thank you! – Lendl Leyba May 20 '15 at 23:52
  • @LeiLeyba i am sorry but i didnt manage to get a work around it. – Steve Kamau May 25 '15 at 05:06
  • @SteveKamau i did. do you still need me to post my answer? – Lendl Leyba May 25 '15 at 06:40
  • @LeiLeyba yes please – Steve Kamau May 25 '15 at 07:37

4 Answers4

27

So simplified version, here's my onbindVH:

 @Override
    public void onBindViewHolder(FeedsViewHolder holder, int position) {
        final Feed item = mFeeds.get(position);

        holder.textView1.setText(item.getText());
        holder.imageView.setImageDrawable(mContext.getResources().getDrawable(item.getImage));
        holder.imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                fragmentJump(item);
            }
        });
    }

here's fragmentJump:

private void fragmentJump(Feed mItemSelected) {
    mFragment = new Fragment2();
    mBundle = new Bundle();
    mBundle.putParcelable("item_selected_key", mItemSelected);
    mFragment.setArguments(mBundle);
    switchContent(R.id.frag1, mFragment);
}

here's switchContent on the adapter:

public void switchContent(int id, Fragment fragment) {
    if (mContext == null)
        return;
    if (mContext instanceof MainActivity) {
        MainActivity mainActivity = (MainActivity) mContext;
        Fragment frag = fragment;
        mainActivity.switchContent(id, frag);
    }

}

and lastly, here's the switchContent on MainActivity:

public void switchContent(int id, Fragment fragment) {
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    ft.replace(id, fragment, fragment.toString());
    ft.addToBackStack(null);
    ft.commit();
}

I know it can still be simplified, but it works as is. I hope it helps. :)

Lendl Leyba
  • 2,287
  • 3
  • 34
  • 49
  • Btw, i have 2 fragmentJumps, that's why I separated the switchContent on the adapter. – Lendl Leyba May 25 '15 at 08:40
  • I love your idea,i will now go fix up my app,i left it unfinished.Thanks so much – Steve Kamau May 25 '15 at 12:12
  • do not understand what is mContext?? @LeiLeyba – Yeahia2508 Aug 19 '15 at 14:21
  • 1
    @yeahia2508 hey, i'm sorry. mContext is context passed on. – Lendl Leyba Aug 20 '15 at 03:19
  • is there a reason why you have **Fragment frag = fragment;** in the switchContent on the Adapter? Is it wrong if you put the **fragment** param into **mainActivity.switchContent(id, frag);** so it will be something like this **mainActivity.switchContent(id, fragment);**? – Red M Aug 02 '16 at 18:52
  • What is feed onBindViewHolder method? It's very helpful if you create a full detailed video on it. – symi khan Dec 06 '18 at 06:39
13

Had the same problem but I wanted to sent two strings to the new fragment which was to be taken from the recycler view item's textViews. This was the code I used. In the viewHolder onClick method:

    @Override
    public void onClick(View v) {

    String title = titleTextView.getText().toString();
    String author = authorTextView.getText().toString();    //two text views defined on top of the viewHolder

   Bundle bundle = new Bundle();
   bundle.putString("title", title);
   bundle.putString("author", author);

   BookFragment bookFragment = new BookFragment();
   bookFragment.setArguments(bundle);

   AppCompatActivity activity = (AppCompatActivity) v.getContext();
   activity.getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout, bookFragment).addToBackStack(null).commit();

        }

In the recieving fragment onCreateView

 View view = inflater.inflate(R.layout.fragment_book, container, false);

 Bundle bundle = this.getArguments();
 if(bundle != null){
 String title = bundle.get("title").toString();
 String author = bundle.get("author").toString();
 }

And it worked.

sammy
  • 296
  • 2
  • 6
6

In your OnBindViewHolder start as follows,

@Override
        public void onClick(View view){

            AppCompatActivity activity = (AppCompatActivity) view.getContext();
            Fragment myFragment = new MyFragment();
            activity.getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, myFragment).addToBackStack(null).commit();


        }
Parinda Rajapaksha
  • 2,963
  • 1
  • 36
  • 40
-3
public class AdapterClass extends RecyclerView.Adapter<AdapterClass.MyViewHolder> {
    private LayoutInflater inflater;
    private Context context;
    List<Information> data = Collections.emptyList();

    public AdapterClass(Context context, List<Information> data) {
        this.context = context;

        inflater = LayoutInflater.from(context);
        this.data = data;
    }

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

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        Information current = data.get(position);
        holder.title.setText(current.title);
        holder.icon.setImageResource(current.iconId);

    }

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

    class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        TextView title;
        ImageView icon;

        public MyViewHolder(View itemView) {
            super(itemView);
            context = itemView.getContext();
            title = (TextView) itemView.findViewById(R.id.listText);
            icon = (ImageView) itemView.findViewById(R.id.listIcon);
            itemView.setClickable(true);
            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {

            final Intent intent;
            switch (getPosition()) {
                case 0:
                    intent = new Intent(context, next.class);
                    break;

                case 1:
                    intent = new Intent(context, next.class);
                    break;

                case 2:
                    intent = new Intent(context, next.class);
                    break;
                default:
                    intent = new Intent(context, next.class);
                    break;
            }
            context.startActivity(intent);
        }
    }
};
Satan Pandeya
  • 3,747
  • 4
  • 27
  • 53
  • 2
    While this code may answer the question, providing additional context regarding **how** and/or **why** it solves the problem would improve the answer's long-term value. – Alexander Mar 03 '18 at 15:09