[英]Navigation Drawer back button in fragments
我開始創建使用一個活動(導航抽屜)和許多片段的應用程序。 但我無法使用工具欄后退按鈕從片段導航回來。 硬件后退按鈕完美運行。 我知道我需要覆蓋onOptionsItemSelected
,捕獲android.R.id.home
,檢查后堆棧中是否有東西然后彈出它。 更改片段后,“漢堡”按鈕更改為“后退箭頭”,但是當我單擊它時onOptionsItemSelected
從未觸發,只需打開 NavigationDrawer 菜單。
這是來自活動的代碼:
public class NavDrawerActivity extends AppCompatActivity implements ... {
NavigationView navigationView;
BottomNavigationView bottomNavigationView;
ActionBarDrawerToggle toggle;
FragmentManager fragmentManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nav_drawer);
fragmentManager = getSupportFragmentManager();
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
// Set back button
fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
if (fragmentManager.getBackStackEntryCount() > 0) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
} else {
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
toggle.syncState();
}
}
});
// Load default fragment
changeFragment(new HomeFragment(), false);
navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
View headerLayout = navigationView.getHeaderView(0);
bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation);
bottomNavigationView.setOnNavigationItemSelectedListener(this);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Toast.makeText(this, "Back pressed", Toast.LENGTH_SHORT)
.show();
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START))
drawer.closeDrawer(GravityCompat.START);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else if (fragmentManager.getBackStackEntryCount() > 0) {
fragmentManager.popBackStack();
} else {
super.onBackPressed();
}
}
private void changeFragment(Fragment fm, boolean addToBackStack)
{
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.frame_layout_content, fm);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
if (addToBackStack) ft.addToBackStack(null);
ft.commit();
}
}
以及我如何從HomeFragment
更改(替換)片段:
IndexDetailFragment newFragment = new IndexDetailFragment();
Bundle args = new Bundle();
args.putString(IndexDetailFragment.ARG_INDEX_ID, id);
newFragment.setArguments(args);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left);
transaction.replace(R.id.frame_layout_content, newFragment);
transaction.addToBackStack(null);
transaction.commit();
setNavigationOnClick()
上的toolbar
后setSupportActionBar(toolbar)
:
setSupportActionBar(toolbar);
toolbar.setNavigationOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Toast.makeText(getActivity(), "Back clicked!",
Toast.LENGTH_SHORT).show();
}
});
我做了一個小應用程序供參考
第一個片段
public class FirstFragment extends Fragment {
public FirstFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_first, container, false);
}
}
第二個片段
public class SecondFragment extends Fragment {
public SecondFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_second, container, false);
}
}
主要活動
public class MainActivity extends AppCompatActivity {
private Toolbar mToolbar;
private ActionBarDrawerToggle drawerToggle;
private DrawerLayout mDrawerLayout;
private String TAG = "MainActivity";
private FragmentManager mFragmentManager;
private NavigationView mNavigationView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
if (mToolbar != null) {
setSupportActionBar(mToolbar);
}
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer);
drawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.string.drawer_open, R.string.drawer_close) {
@Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
@Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
}
};
mDrawerLayout.addDrawerListener(drawerToggle);
mNavigationView = findViewById(R.id.navigation);
mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.first:
changeFragment(new FirstFragment(), true);
return true;
case R.id.second:
changeFragment(new SecondFragment(), true);
return true;
}
return false;
}
});
mFragmentManager = getSupportFragmentManager();
changeFragment(new FirstFragment(), true);
}
@Override
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
if (drawerToggle != null) {
drawerToggle.syncState();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
Log.i(TAG, "onOptionsItemSelected: Home Button Clicked");
if (mDrawerLayout.isDrawerOpen(Gravity.START)) {
mDrawerLayout.closeDrawer(Gravity.START);
} else {
mDrawerLayout.openDrawer(Gravity.START);
}
}
return super.onOptionsItemSelected(item);
}
@Override
public void onBackPressed() {
if (mDrawerLayout.isDrawerOpen(Gravity.START)) {
mDrawerLayout.closeDrawer(Gravity.START);
}
if (mDrawerLayout.isDrawerOpen(Gravity.START)) {
mDrawerLayout.closeDrawer(Gravity.START);
} else if (mFragmentManager.getBackStackEntryCount() > 0) {
mFragmentManager.popBackStack();
} else {
super.onBackPressed();
}
}
private void changeFragment(Fragment fragment, boolean needToAddBackstack) {
FragmentTransaction mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.FRAME_CONTENT, fragment);
mFragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
if (needToAddBackstack)
mFragmentTransaction.addToBackStack(null);
mFragmentTransaction.commit();
}
}
活動主
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="@dimen/abc_action_bar_default_height_material"
android:background="@color/colorPrimaryDark"
/>
<FrameLayout
android:id="@+id/FRAME_CONTENT"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/abc_action_bar_default_height_material" />
</FrameLayout>
<android.support.design.widget.NavigationView
android:id="@+id/navigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:layout_marginTop="@dimen/abc_action_bar_default_height_material"
app:menu="@menu/drawermenu" />
</android.support.v4.widget.DrawerLayout>
我有同樣的問題。
我最終通過在 onCreate 方法中添加它來解決。
getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
if(getSupportFragmentManager().getBackStackEntryCount() == 0){
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
menuToggle.setDrawerIndicatorEnabled(true);
}else{
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
menuToggle.setDrawerIndicatorEnabled(false);
}
}
});
希望它有幫助
在對我有用的 onCreate() 方法中添加以下代碼
getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, " Back Pressed ", Toast.LENGTH_SHORT).show();
}
});
} else {
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
drawerToggle = new ActionBarDrawerToggle(MainActivity.this, drawerLayout, toolbar,
R.string.app_name, R.string.app_name);
drawerLayout.addDrawerListener(drawerToggle);
drawerToggle.syncState();
}
}
});
Kotlin 開發人員最簡單的解決方案
只需將其添加到片段抵抗的根活動中
if (supportFragmentManager.backStackEntryCount > 0) {
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
toolbar.setNavigationOnClickListener {
if (supportFragmentManager.backStackEntryCount > 0) {
super.onBackPressed()
} else {
supportActionBar!!.setDisplayHomeAsUpEnabled(false)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
drawerLayout.openDrawer(GravityCompat.START)
}
}
} else {
supportActionBar!!.setDisplayHomeAsUpEnabled(false)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
}
在這里,每當setDisplayHomeAsUpEnabled
設置為true
,我都會顯示后退按鈕。 在點擊它時,我正在調用super.onBackPressed()
這類似於您的后退按鈕的作用!
解決我這個問題的事情是這樣的:
我使用了NavigationDrawerActivity
模板自動附帶的代碼,它是這樣的:
NavigationView navigationView = _binding.navView;
// Passing each menu ID as a set of Ids because each menu should be considered as top level destinations:
_AppBarConfiguration = new AppBarConfiguration.Builder(R.id.nav_x, R.id.nav_y, R.id.nav_z)
.setOpenableLayout(_binding.drawerLayout)
.build();
_navController = Navigation.findNavController(this, R.id.nav_host_content_main);
NavigationUI.setupActionBarWithNavController(this, _navController, _AppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, _navController);
我在許多技巧和竅門上掙扎了很多,但沒有任何效果對我有用。
在某些時候,我注意到我想要啟用后退按鈕的片段“被視為頂級目的地”,這正是上面代碼中的注釋所說的。 然后我刪除了那些子片段和 BOOM 就是這樣,不需要一個 hack 或一行代碼,這是開箱即用的,我只需要注意它。
所以就我而言,我改為以下代碼:
NavigationView navigationView = _binding.navView;
// Passing each menu ID as a set of Ids because each menu should be considered as top level destinations:
_AppBarConfiguration = new AppBarConfiguration.Builder(R.id.nav_x)
.setOpenableLayout(_binding.drawerLayout)
.build();
_navController = Navigation.findNavController(this, R.id.nav_host_content_main);
NavigationUI.setupActionBarWithNavController(this, _navController, _AppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, _navController);
: 剛剛刪除了R.id.nav_y, R.id.nav_z
, AppBarConfiguration
我為此掙扎了一段時間。 我通過以下方式讓它工作:
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController
findViewById<NavigationView>(R.id.nav_view).setupWithNavController(navController)
appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
/>
</com.google.android.material.appbar.AppBarLayout>
</LinearLayout>
var myToolbar = requireActivity() .findViewById<androidx.appcompat.widget.Toolbar>(R.id.toolbar) myToolbar.inflateMenu(R.menu.menu) val drawerLayout = requireActivity().findViewById<DrawerLayout>(R.id.drawer_layout) val toggle = ActionBarDrawerToggle( activity, drawerLayout, myToolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close ) toggle.setDrawerIndicatorEnabled(true) drawerLayout.addDrawerListener(toggle) toggle.syncState()
val navController = findNavController()
val appBarConfiguration = AppBarConfiguration(navController.graph)
view.findViewById<Toolbar>(R.id.toolbar)
.setupWithNavController(navController, appBarConfiguration)
希望這可以幫助每個為此苦苦掙扎的人:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.