簡體   English   中英

片段中的導航抽屜后退按鈕

[英]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()上的toolbarsetSupportActionBar(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

我為此掙扎了一段時間。 我通過以下方式讓它工作:

  1. 在 MainActivity.kt 中設置我的抽屜布局:
    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)
  1. 在我需要工具欄的每個片段中包含工具欄布局:
    <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>
  1. 將以下代碼添加到抽屜的主片段中,使用抽屜從中調用其他片段。 這使漢堡包圖標在 onViewCreated 方法中起作用:
     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()
  2. 在 kotlin 代碼中為 home 片段之后的片段添加以下代碼,這將得到后退箭頭:
      val navController = findNavController()
        val appBarConfiguration = AppBarConfiguration(navController.graph)

        view.findViewById<Toolbar>(R.id.toolbar)
            .setupWithNavController(navController, appBarConfiguration)
  1. 編輯導航圖以確保片段正確連接

希望這可以幫助每個為此苦苦掙扎的人:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM