web-dev-qa-db-ja.com

ナビゲーションコントロールフラグメントのナビゲーションDrawerLayout onBackPressedを閉じる方法

NavigationパターンでAndroidxプロジェクトを作成しました。次に、drawerLayoutonBackPressed()をフラグメントで閉じます。また、OnClickListenerをドロワーメニュー項目に設定してカスタムメニューに設定したいのですが、onBackPressed()をフラグメントでオーバーライドする方法はありません。

どうすればこれを達成できるのか知りたいですか?

これが私の引き出しです:

<androidx.drawerlayout.widget.DrawerLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:orientation="vertical"
    Android:id="@+id/drawerLayoutHome"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <com.google.Android.material.navigation.NavigationView
        Android:id="@+id/nav_view"
        Android:layout_width="350dp"
        Android:layout_height="match_parent"
        Android:layout_gravity="start"
        Android:background="@color/colorPrimaryDark"
        Android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:itemIconTint="@color/white"
        app:itemTextColor="@color/white"
        app:menu="@menu/activity_main_drawer"/>

</androidx.drawerlayout.widget.DrawerLayout>

私はこれを達成したいです:

override fun onBackPressed() {

    if (drawerLayoutHome.isDrawerOpen(GravityCompat.END)) {
        drawerLayoutHome.closeDrawer(GravityCompat.END)
    } else {
        super.onBackPressed()
    }
}

しかし、これはActivity用です。Fragmentでこれを実現するにはどうすればよいですか?

17
Arbaz Pirwani

こんにちは、フラグメントを取得してKotlinコードでonbackpressをオーバーライドすることでそれを行うことができます

これはバックプレス機能であり、これでナビゲーションホストを取得し、現在のフラグメントまたは引き出しを開くフラグメントを確認できます。

override fun onBackPressed() {

    val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragmentHomeHost)
    val completeFragmentList = navHostFragment?.childFragmentManager?.fragments

    if (completeFragmentList != null) {
        when {
            completeFragmentList[0] is HomeFragment -> {
                val home = (completeFragmentList[0] as HomeFragment)


            }
            else -> super.onBackPressed()
        }
    }

    if (drawerLayoutHome.isDrawerOpen(GravityCompat.START)) {
        drawerLayoutHome.closeDrawer(GravityCompat.START)
    } else {
        super.onBackPressed()
    }
}

そして、これは選択項目リスナーを取得できる鍬です

override fun onNavigationItemSelected(item: MenuItem): Boolean {
    drawerLayoutHome.closeDrawer(GravityCompat.START)

    return true
}
8
Hello world

ドロワーアクティビティにFragmentを実装することで、OnBackStackChangedListener内でそれを行うことができます。
次に、引き出しをActionBarDrawerToggleにリンクし、onBackStackChanged()をオーバーライドして、引き出しの切り替えを同期します。

以下が完全なスニペットです。

public class MainActivity extends AppCompatActivity implements FragmentManager.OnBackStackChangedListener {


    private DrawerLayout drawer;
    private ActionBarDrawerToggle toggle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //Bind listener here
        getSupportFragmentManager().addOnBackStackChangedListener(this);
        drawer = findViewById(R.id.drawer_layout);
        toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        toggle.setToolbarNavigationClickListener(view -> onBackPressed());
        drawer.addDrawerListener(toggle);
        toggle.syncState();

    }


    //Override fragment backstack lister method 
    @Override
    public void onBackStackChanged() {
        //toggle.setDrawerIndicatorEnabled(getSupportFragmentManager().getBackStackEntryCount() == 0);
        //getSupportActionBar().setDisplayHomeAsUpEnabled(getSupportFragmentManager().getBackStackEntryCount() > 0);
        toggle.syncState();
    }

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

これがお役に立てば幸いです。

4
Mehul Solanki

短い答え

onBackPressedをホストする内部にコードを追加しないと、Fragment内のActivityコールバックをインターセプトすることはできません。 Android SDKには実装されていません。やめて.

元の答え

onBackPressedクラスにはFragmentコールバックなどはありません。しかし、あなたはそれを自分で実装することができます:

インターフェースを作成します。

interface FragmentOnBackPressedListener {
  fun onBackPressed()
}

今あなたの活動の中で:

override fun onBackPressed() {
  // find top fragment
  val currentFragment = supportFragmentManager
    .findFragmentById(R.id.your_nav_Host_fragment_id)?.let {
      it.childFragmentManager.fragments.getOrNull(0)
    }
  // check if it implements FragmentOnBackPressedListener 
  if (currentFragment is FragmentOnBackPressedListener ) {
    // if it does, transfer flow to the fragment
    return currentFragment.onBackPressed()
  }
  // if it doesn't, apply default behaviour
  super.onBackPressed()
}

次に、あなたのフラグメントで:

class ExampleFragment : Fragment(), FragmentOnBackPressedListener {

  override fun onBackPressed() {
    // close your drawer layout here if visible

    // Also: to close fragment, invoke 
    // findNavController().navigateUp() or findNavController().popBackStack()
  }

}
2
xinaiz

同様の問題がありました。

それで、これをアクティビティファイルのonBackPressedに追加しました。

FragmentManager manager = getSupportFragmentManager();
 if (manager.getBackStackEntryCount() > 0) {
                while (manager.getBackStackEntryCount() > 0) {
                    manager.popBackStackImmediate();
                }
0
sanjeev