导航抽屉的碎片管理

应用层次结构 我正在开发一个应用程序,我只使用1个主要活动和多个片段,包括ViewPager ,自定义video/图像库,全屏片段(没有工具栏或底部导航按钮)。 我不确定这是好的做法,但我面临的问题很少。

上图是实际的App层次结构。 在我面临的问题之后。

  1. 工具栏不会更改片段的标题,按下后退按钮或通过单击按钮或某个链接前进。
  2. 如果我使用以下方法更改为后退箭头,导航汉堡会继续显示using: getSupportActionBar().setDisplayHomeAsUpEnabled(true); 然后后退箭头打开抽屉,但不会回到最后一个片段。
  3. 按下按钮或直接跳转到某个片段时的片段状态丢失。
  4. 使用单一ActivityFragment执行所有任务是否是一种好习惯。

我也在使用单个工具栏整个应用程序。 Toolbar.xml

              

导航抽屉(单个活动所有碎片的父级)

 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); } } 

我累了很多来解决这个问题,经过几个月的谷歌搜索和stackoverflow我仍然陷入同样的​​问题。

第1点的问题示例: – 当导航抽屉首先加载所有内容时,查看寻呼机会根据片段更改标题。 然后,如果我点击导航抽屉的菜单,它也打开另一个片段(例如:最近的消息)。 然后标题更改成功但当我按下后退按钮或尝试按下调用viewpager的主页按钮时,标题保持与之前相同,即最近消息。

像这样在每个片段中设置标题。

 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); 

使用单一活动在Fragment中执行所有任务是否是一种好习惯。

使用导航抽屉,标签或底部导航时,最好使用碎片。
除此之外,片段最适合具有不同数据的可重用UI。

你正在使用单一活动在片段内完成所有任务,因为你正在使用导航绘图和标签,所以这是一个很好的做法,我会说。

工具栏不会更改片段的标题,按下后退按钮或通过单击按钮或某个链接前进。

无论何时添加/替换新片段OR,都需要手动设置片段的标题
on back press(backstack change),仅通过Fragment或使用文档中提到的OnBackStackChangedListener

您只是在点击导航项时设置它们,而不是在单击按钮或某个链接时设置它们

如果我使用以下方法更改为后退箭头,导航汉堡会继续显示:getSupportActionBar()。setDisplayHomeAsUpEnabled(true); 然后后退箭头打开抽屉,但不会回到最后一个片段。

你也需要手动处理。 单击android.R.id.home项目时使用onOptionItemSelected 。 就像从堆栈中popup片段一样。

标题持久性的原因是从Activity设置标题。 即使用此setTitle(menuItem.getTitle()); 而是通过Fragment设置它们,或者如果您通过selectDrawerItem方法从Fragment中删除它们。
同样在selectDrawerItem方法的末尾,您使用fragmentTransaction.add而不是使用fragmentTransaction.replace

如果应用程序必须使用应存在于所有视图中的导航抽屉,则应使用Fragment。 这不是一个坏习惯。

  1. 工具栏不会更改片段的标题,按下后退按钮或通过单击按钮或某个链接前进。

在Base Activity中创建方法

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

onCreateView各个片段访问此方法

 ((LandingActivity) getActivity()).setFragmentTitle(getActivity().getString(R.string.fragment_title)); 
  1. 如果我使用以下方法更改为后退箭头,导航汉堡会继续显示:getSupportActionBar()。setDisplayHomeAsUpEnabled(true); 然后后退箭头打开抽屉,但不会回到最后一个片段。

    单击android.R.id.home使用onOptionItemSelected ,popup当前的Fragment

  2. 按下按钮或直接跳转到某个片段时的片段状态丢失

    你必须提到需要持久化的值并重新填充它。


 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); } } 

在你的片段中

 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); } } 

编辑1:对于片段标题没有在BackButton按下更新

Fragment添加到Backstack时,请执行以下操作。

在您的父级活动中

 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); 

现在覆盖父Activity中的onBackPressed

  @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; } 

现在在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(); } } } }