Создавая свое первое пользовательское приложение, я хотел бы реализовать то, что поначалу казалось простым, но, конечно, это не так. У меня есть действие с некоторыми фрагментами, к которому я могу перейти с помощью Навигатора:
res / menu / navdrawer_menu. xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/matchFragmentUI"
android:icon="@drawable/ic_match"
android:title="@string/matches_string" />
<item
android:id="@+id/statFragmentUI"
android:icon="@drawable/ic_stat"
android:title="@string/stats_string" />
<item
android:id="@+id/clubFragmentUI"
android:icon="@drawable/ic_club"
android:title="@string/club_string" />
<item
android:id="@+id/agendaFragmentUI"
android:icon="@drawable/ic_agenda"
android:title="@string/agenda_string" />
<item
android:id="@+id/settingFragmentUI"
android:icon="@drawable/ic_settings"
android:title="@string/settings_string" />
<item
android:id="@+id/profileFragmentUI"
android:icon="@drawable/ic_person_black_24dp"
android:title="@string/profile_text" />
</menu>
res / layout / activity_content. xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.drawerlayout.widget.DrawerLayout
android:id="@+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".content.ContentActivity">
<fragment
android:id="@+id/contentNavHostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/navigation_content" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/navView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="@menu/navdrawer_menu"
app:headerLayout="@layout/nav_header"/>
</androidx.drawerlayout.widget.DrawerLayout>
</layout>
Я хотел бы изменить поведение кнопки "Назад", чтобы пользователи не могли случайно покинуть приложение, например:
/* Override behavior of back button */
override fun onBackPressed() {
/* Case we are not on the home screen */
if(/* not on home screen */) /* go to home screen */
else {
/* Otherwise we return to the access activity */
/* Dialog window to prevent accidental leaving */
val backAlertDialog = android.app.AlertDialog.Builder(this)
backAlertDialog.setTitle("Log out")
backAlertDialog.setMessage("Are you sure you want to leave?")
/* buttons YES/NO actions */
backAlertDialog.setPositiveButton("No") { dialog, which -> dialog.cancel() }
backAlertDialog.setNegativeButton("Yes") { dialog, which ->
val accessIntent = Intent(this, AccessActivity::class.java)
accessIntent.flags = FLAG_ACTIVITY_CLEAR_TOP // Clear activity backstack
startActivity(accessIntent) // Go back to access activity
finish() // Finish this activity
}
backAlertDialog.show()
}
}
Моя проблема проверяет, отображаем ли мы HomeFragment
. Сначала я попробовал с этим:
if (supportFragmentManager.backstackEntryCount > 0)
Но проблема здесь в том, что навигация с помощью навигационного ящика ничего не добавляет в backstack (backstackEntryCount
остается на 0 ), поэтому он не будет работать.
Вот почему я сейчас пытаюсь использовать интерфейс NavigationView.OnNavigationItemSelectedListener
, чтобы добавить что-то в backstack, когда элемент выбран, а также отслеживать текущий отображаемый фрагмент например:
/* Keep track of what the current fragment is like */
private var fragment : Fragment? = null
override fun onNavigationItemSelected(item: MenuItem): Boolean {
val itemId = item.itemId
val fm = this.supportFragmentManager
/* Clear stack */
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
/* Add a case for each item in the drawer */
/* For each case, always add (push) a HomeFragment and then the fragment we navigate to */
/* Then, going back will always return to Home because we cleared backstack before */
when(itemId) {
R.id.profileFragmentUI -> {
fragment = ProfileFragmentUI()
}
R.id.agendaFragmentUI -> {
fragment = AgendaFragmentUI()
}
R.id.clubFragmentUI -> {
fragment = ClubFragmentUI()
}
R.id.statFragmentUI -> {
fragment = StatFragmentUI()
}
R.id.matchFragmentUI -> {
fragment = MatchFragmentUI()
}
R.id.settingFragmentUI -> {
fragment = SettingFragmentUI()
}
}
/* Replace current fragment by the selected fragment in backstack and add home for back support */
if (fragment != null) {
fm.beginTransaction()
.add(HomeFragmentUI(), "HomeFragmentUI")
.addToBackStack("HomeFragmentUI")
.replace(R.id.contentNavHostFragment, fragment!!)
.commit()
}
return true
}
Кроме того, вот мои методы onCreate()
и onSupportNavigateUp()
в коде активности:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
/* Bind layout elements at compile time to be faster at runtime */
val binding = DataBindingUtil.setContentView<ActivityContentBinding>(this, R.layout.activity_content)
val contentDrawerLayout = binding.drawerLayout
val player = intent.getParcelableExtra("player")
val navigationView = binding.navView
navigationView.setNavigationItemSelectedListener { item -> onNavigationItemSelected(item) }
/* Setup the navigation for fragments */
val navController = this.findNavController(R.id.contentNavHostFragment)
val fragmentManager = this.supportFragmentManager
/* Setup navigation bar, with drawer menu */
NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout)
NavigationUI.setupWithNavController(binding.navView, navController)
fragment = HomeFragmentUI() /* To make back button work at start of navigation */
}
override fun onSupportNavigateUp(): Boolean {
val navController = this.findNavController(R.id.contentNavHostFragment)
/* Replace up button by drawer button on title screen */
return NavigationUI.navigateUp(navController, drawerLayout)
}
Теперь я хочу выполнить свою проверку следующим образом:
if (fragment is HomeFragmentUI)
/* display dialog */
else
/* navigate back to home */
Проблема теперь в том, что когда я выбираю предмет в своем ящике, я перехожу к хорошему фрагменту, НО атрибут fragment
все еще является экземпляром HomeFragmentUI
. Я пытался поместить некоторые журналы в методе onNavigationItemSelected
, но они никогда не обнаруживаются. Я понятия не имею, почему метод никогда не вызывается, так как я определил слушателя в onCreate
.
Вот некоторые ссылки, которые я использовал до сих пор:
https://www.youtube.com/watch?v=I47Zy6JtNIU
https://www.youtube.com/watch?v=y9KYKYJJ4GY
https://guides.codepath.com/android/Fragment-Navigation-Drawer
Заранее спасибо.