Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Navigation Drawer's Fragment Management

App Hierarchy I am developing an app where i am using only 1 Main Activity and Multiple fragment, Including ViewPager , Custom video/Image Gallery, Fullscreen Fragment(Without toolbar or bottom navigation button). I am not sure is it good practice or not but i am facing few issues cause of this.

Image above is actual App hierarchy. Following the issue i am facing.

  1. Toolbar doesn't change title of fragment, when press back button or going forward by clicking button or some link.
  2. Navigation hamburger keep showing if i change into back arrow by using: getSupportActionBar().setDisplayHomeAsUpEnabled(true); then back arrow opens drawers but not going back to last fragment.
  3. Fragment State Loss when pressed back button or jumping directly to some fragment.
  4. Whether is it good practice to doing all task within Fragment with Single Activity.

I am also using single Toolbar whole app. Toolbar.xml

<android.support.v7.widget.Toolbar
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="@color/primary"
    app:contentInsetLeft="0dp"
    app:contentInsetStart="0dp"
    app:contentInsetStartWithNavigation="0dp"
    android:fitsSystemWindows="true"
    app:layout_collapseMode="pin"
    app:layout_scrollFlags="scroll|exitUntilCollapsed">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/toolbar_connections"
        android:visibility="visible"
        android:orientation="horizontal">
    <ImageView
        android:layout_width="35dp"
        android:layout_height="match_parent"
        android:id="@+id/appLogo"
        android:layout_gravity="center_vertical" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical|center_horizontal"
            android:textSize="22sp"
            android:id="@+id/activityTitle"
            android:textColor="@color/primary_text"
            />

    </LinearLayout>

    <LinearLayout
        android:id="@+id/toolbar_chat"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone"
        android:orientation="horizontal">

        <de.hdodenhof.circleimageview.CircleImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_gravity="center_vertical"
            android:layout_marginRight="5dp"
            android:src="@drawable/baby"
            android:id="@+id/User_Image_Toolbar"/>
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:id="@+id/User_Name_Toolbar"
                android:textSize="17sp"
                android:textStyle="bold"
                android:layout_marginBottom="5dp"
                android:text="My Name"
                />
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Online"
                android:textStyle="italic"
                android:id="@+id/User_Online_Status_Toolbar"
                android:layout_marginBottom="5dp"
                android:layout_below="@+id/User_Name_Toolbar" />
        </LinearLayout>
    </LinearLayout>


</android.support.v7.widget.Toolbar>

Navigation Drawer (Single Activity which parent of all Fragments)

public class Navigation_Drawer extends AppCompatActivity implements UserData {

    Toolbar toolbar;
    DrawerLayout drawerLayout;
    NavigationView navigationView;
    String navTitles[];
    TypedArray navIcons;
    RecyclerView.Adapter recyclerViewAdapter;
    ActionBarDrawerToggle drawerToggle;
    public static final String TAG = "###Navigation Drawer###";
    boolean nextScreen;
    //Header
    ImageView headerImage,headerUserImage;
    TextView userName,userViews;
    Context context = this;
    //Setting Tabs
    ViewPager viewPager;
    TabAdapter tabAdapter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);           
        setContentView(R.layout.navigation_drawer);    

        //Initialise Views
        drawerLayout = findViewById(R.id.Navigation_Drawer_Main);
        navigationView = findViewById(R.id.nvView);
        setupToolbar();
        navigationView.setItemIconTintList(null);
        setupDrawerContent(navigationView);
        settingHeaderItems();
        drawerToggle = setupDrawerToggle();
        getSupportActionBar().setHomeButtonEnabled(true);

        drawerLayout.addDrawerListener(drawerToggle);
        viewPager = findViewById(R.id.Navigation_Drawer_ViewPager);
        tabAdapter = new TabAdapter(getFragmentManager(), this, false);    


        viewPager.setAdapter(tabAdapter);

    }


    public void setupToolbar() {
        toolbar = findViewById(R.id.Navigation_Drawer_toolbar);
        setSupportActionBar(toolbar);
    }
    private ActionBarDrawerToggle setupDrawerToggle() {
        // NOTE: Make sure you pass in a valid toolbar reference.  ActionBarDrawToggle() does not require it
        // and will not render the hamburger icon without it.
        //return new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.drawer_open,  R.string.drawer_close);
        return new ActionBarDrawerToggle(this, drawerLayout,toolbar, R.string.drawer_open,  R.string.drawer_close);
    }    


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        //  inflater.inflate(R.menu.main_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        //Handle Item Selection

        return super.onOptionsItemSelected(item);
    }
    private void setupDrawerContent(NavigationView navigationView) {
        navigationView.setNavigationItemSelectedListener(
                new NavigationView.OnNavigationItemSelectedListener() {
                    @Override
                    public boolean onNavigationItemSelected(MenuItem menuItem) {
                        selectDrawerItem(menuItem);
                        return true;

                    }

                });

    }





    public void ChangeFragment_ViewPager(int position, boolean outside) {
        if (outside) {
            Log.d(TAG, "Change Fragment Calling From Outside");
            tabAdapter = new TabAdapter(getFragmentManager(), this, false);
            viewPager.setAdapter(tabAdapter);
        }

        viewPager.setCurrentItem(position);
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        showSystemUI();
        Log.d(TAG, "On Back Pressed");

    }

    public void showSystemUI() {
        if (getWindow() != null) {
            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            getSupportActionBar().show();
        } else {
            return;
        }

    }


    public void selectDrawerItem(MenuItem menuItem) {
        // Create a new fragment and specify the fragment to show based on nav item clicked
        Fragment fragment = null;


        switch (menuItem.getItemId()) {

            case R.id.HeaderImageView:
                fragment = new EditProfile();
                break;
            case R.id.home_Fragment:
                Log.d(TAG,"Home Fragment Pressed ");
                getFragmentManager().popBackStack(null, android.app.FragmentManager.POP_BACK_STACK_INCLUSIVE);
                ChangeFragment_ViewPager(0,false);
                // Highlight the selected item has been done by NavigationView
                menuItem.setChecked(true);
                // Set action bar title
                setTitle(menuItem.getTitle());
                // Close the navigation drawer
                drawerLayout.closeDrawers();
                return;

            case R.id.ppl_Fragment:
                Log.d(TAG,"PPL Fragment Pressed ");
                ChangeFragment_ViewPager(1,false);
                // Highlight the selected item has been done by NavigationView
                menuItem.setChecked(true);
                // Set action bar title
                setTitle(menuItem.getTitle());
                // Close the navigation drawer
                drawerLayout.closeDrawers();
                return;

            case R.id.message_Fragment:
                Log.d(TAG,"Message Fragment Pressed ");
                fragment = new  Messages_Fragment();

                break;

            case R.id.addMedia_Fragment:
                Log.d(TAG,"Add Media Fragment Pressed ");
                fragment = new UserProfile_Photos();

                break;

            case R.id.invite_Fragment:
                Log.d(TAG,"Invite Fragment Pressed ");
                //fragmentClass = fragment_1.class;
                onInviteClicked();
                // Highlight the selected item has been done by NavigationView
                menuItem.setChecked(true);
                // Set action bar title
                setTitle(menuItem.getTitle());
                // Close the navigation drawer
                drawerLayout.closeDrawers();
                return;


            case R.id.setting_Fragment:
                Log.d(TAG,"Setting Fragment Pressed ");
                fragment = new  Setting_NavigationDrawer();

                break;

            case R.id.help_Fragment:
                Log.d(TAG,"Help Fragment Pressed ");
                //fragmentClass = fragment_1.class;
                fragment=new FullScreen_WebView();
                Bundle urlToSend=new Bundle();
                urlToSend.putString("webViewURL","http://boysjoys.com/test/Android/Data/help.php");
                //urlToSend.putString("webViewURL",chat_wrapper.getGoogleSearch().get(2));
                fragment.setArguments(urlToSend);
                FragmentTransaction transaction=((Activity)context).getFragmentManager().beginTransaction();
                //fragmentTrasaction.replace(R.id.Chat_Screen_Main_Layout,gallery);
                //transaction.replace(R.id.Chat_Screen_Main_Layout,fullScreen_webView);
                transaction.replace(R.id.Navigation_Main_Layout,fragment);
                transaction.addToBackStack(null);
                transaction.commit();

                // Highlight the selected item has been done by NavigationView
                menuItem.setChecked(true);
                // Set action bar title
                setTitle(menuItem.getTitle());
                // Close the navigation drawer
                drawerLayout.closeDrawers();
                return;

            case R.id.signOut_Fragment:
                new CheckLoginStatus(this, 0).execute();
                new Send_Session_Logout(this).execute();
                drawerLayout.closeDrawers();
                return;

        }


        FragmentTransaction fragmentTransaction=getFragmentManager().beginTransaction();
        fragmentTransaction.add(R.id.Navigation_Main_Layout, fragment);
        fragmentTransaction.setCustomAnimations(R.animator.enter_anim,R.animator.exit_anim);
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();

        // Highlight the selected item has been done by NavigationView

        menuItem.setChecked(true);

        // Set action bar title

        setTitle(menuItem.getTitle());

        // Close the navigation drawer

        drawerLayout.closeDrawers();

    }
    private void settingHeaderItems(){
        View HeaderLayout = navigationView.inflateHeaderView(R.layout.navigation_header_image);
        //Main Screen Tabs With VIew Pager
        headerImage = HeaderLayout.findViewById(R.id.HeaderImageView);
        headerImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                FragmentTransaction fragmentTransaction=getFragmentManager().beginTransaction();
                fragmentTransaction.replace(R.id.Navigation_Main_Layout, new EditProfile());
                fragmentTransaction.setCustomAnimations(R.animator.enter_anim,R.animator.exit_anim);
                fragmentTransaction.addToBackStack(null);
                fragmentTransaction.commit();
                drawerLayout.closeDrawers();
            }
        });
        headerUserImage = HeaderLayout.findViewById(R.id.HeaderProfilePicture);
        userName = HeaderLayout.findViewById(R.id.myImageViewText);
        userViews = HeaderLayout.findViewById(R.id.profileViews);
        if (Session.getUserCover().equals("Invalid Image")){
            headerImage.setBackgroundResource(R.drawable.cam_icon);
        }else {
            Log.d(TAG,"Path Of Cover Photo "+Session.getUserCover());
            Bitmap coverPhoto= BitmapFactory.decodeFile(Session.getUserCover());
            headerImage.setImageBitmap(coverPhoto);
            //  Glide.with(context).load(Session.getUserCover()).apply(new RequestOptions().skipMemoryCache(true).onlyRetrieveFromCache(false).diskCacheStrategy(DiskCacheStrategy.NONE)).into(holder.HeaderImage);
        }
        Bitmap bitmap = BitmapFactory.decodeFile(Session.getUserImage());

        userName.setText(Session.getUserFname()+" "+Session.getUserLname());
        headerUserImage.setImageBitmap(bitmap);
        if (Session.getProfileCounter().equals("0")){
            userViews.setText("No Profile VIsits");
        }
        else {
            userViews.setText("Profile views: "+ Session.getProfileCounter());
        }
    }

    @Override
    protected void onPostCreate(@Nullable Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        drawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        drawerToggle.onConfigurationChanged(newConfig);
    }           
}

I tired alot to resolve this issue and after months of googling and stackoverflow i m still stuck in same issue.

Issue example of Point 1:- When navigation drawer load first everything looks good, view pager changes title as per fragment. then if i click on Navigation Drawer's Menu which also open another fragment (For Ex: Recent Message). then title change successfully but when i press back button or trying to press home button which calls viewpager then title remain same as before i.e. Recent Message.

Setting Title in each fragment like this.

toolbar = (Toolbar) getActivity().findViewById(R.id.Navigation_Drawer_toolbar);
        ImageView appLogo = toolbar.findViewById(R.id.appLogo);
        TextView fragmentTitle = toolbar.findViewById(R.id.activityTitle);
        appLogo.setImageResource(DrawableImage);
        fragmentTitle.setText(Title);
like image 851
Ritu Avatar asked Jul 13 '18 12:07

Ritu


People also ask

Where is the navigation drawer on my phone?

The user can view the navigation drawer when the user swipes a finger from the left edge of the activity. They can also find it from the home activity by tapping the app icon in the action bar. The drawer icon is displayed on all top-level destinations that use a DrawerLayout.

Can we navigate from activity to fragment?

If you want to go back from Activity to Fragment. This is very simple just override onBackPressed() in your activity and call onBackPressed where you want.


1 Answers

If application have to use Navigation Drawer which should be present in all views, then Fragment should be used. And its not a bad practice.

  1. Toolbar doesn't change title of fragment, when press back button or going forward by clicking button or some link.

Create a method in Base Activity

public void setFragmentTitle(String title){
        if(!TextUtils.isEmpty(title))
        mTitleText.setText(title);
    }

Access this method from your individual Fragments in onCreateView

((LandingActivity) getActivity()).setFragmentTitle(getActivity().getString(R.string.fragment_title));
  1. Navigation hamburger keep showing if i change into back arrow by using: getSupportActionBar().setDisplayHomeAsUpEnabled(true); then back arrow opens drawers but not going back to last fragment.

    Use onOptionItemSelected on click of android.R.id.home , pop the current Fragment

  2. Fragment State Loss when pressed back button or jumping directly to some fragment

    You have to mention the values which needs to be persisted and repopulate it.


public class ActivityABC....{

private String mFName;
private TableSelectFragment mFragment;

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FragmentManager fm = getSupportFragmentManager();

    if (savedInstanceState != null) {

      mFragment=(TableSelectFragment)fm.getFragment(savedInstanceState,"TABLE_FRAGMENT");
      mFName = savedInstanceState.getString("FNAMETAG");

    }else{
      mFragment = new TableSelectFragment();
      fm.beginTransaction().add(R.id.content_frame,mFragment,"TABLE_FRAGMENT").commit();
       }
    }

   @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
       getSupportFragmentManager().putFragment(outState,"TABLE_FRAGMENT",mFragment);
    }
}

In your Fragment

TableSelectFragment{

  ....

   private String mFName;

   @Override
   public void onCreate(@Nullable Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setRetainInstance(true);
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        outState.putString("FNAMETAG", mFName);
        super.onSaveInstanceState(outState);
    }
}

EDIT 1: For Fragment Title not getting updated in BackButton press

While adding Fragment to backstack , do the following.

In your parent Activity

FragmentManager fragMan = getSupportFragmentManager();
FragmentTransaction fragTrans = fragMan.beginTransaction();
LandingFrag landingFrag = LandingFrag.newInstance();
fragTrans.replace(R.id.landing_view, landingFrag,"LandingFrag");
fragTrans.addToBackStack(null);
fragTrans.commit();
landingFrag.setUserVisibleHint(true);

Now override onBackPressed in parent Activity

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {

            .. POP Fragment Backstack here

            Fragment fragment =  getActiveFragment();
            if(fragment instanceof  LandingFrag)
            {
                    LandingFrag landingFrag = (LandingFrag)fragment;
                    landingFrag.setUserVisibleHint(true);
            }

        }

  public Fragment getActiveFragment() {
        if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
            return null;
        }
        Fragment fragment=null;
        int trackBackValue = 1;//INCREASE OR DECREASE ACCORDING TO YOUR BACK STACK

        try {
            fragment = getSupportFragmentManager().getFragments().get(getSupportFragmentManager().getBackStackEntryCount() - trackBackValue);
        } catch (Exception e) {
        }
        return fragment;

   }

Now in LandingFrag

public class LandingFrag...
{

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setUserVisibleHint(false);
        .....
    }

    @Override
    public void onViewStateRestored(@Nullable Bundle savedInstanceState) {
        super.onViewStateRestored(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
         ................    
          ((LandingActivity) getActivity()).setFragmentTitle("Current Fragment Title");
    }
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if(isVisibleToUser){
            try {
                ((LandingActivity) getActivity()).setFragmentTitle("Current Fragment Title");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}
like image 51
Sreehari Avatar answered Sep 23 '22 04:09

Sreehari