From 36a7ae0035f83ec0110cf5357f847097a2afc4bf Mon Sep 17 00:00:00 2001 From: denizk0461 Date: Tue, 2 May 2023 20:52:56 +0200 Subject: [PATCH] Replaced fragment switching functionality in MainActivity.kt with Navigation component, simplifying logic significantly; upgraded to AGP 8.0.1 --- .../studip/activity/MainActivity.kt | 93 ++----------------- .../studip/adapter/StudIPEventItemAdapter.kt | 8 +- .../studip/fragment/CanteenFragment.kt | 13 +-- .../studip/fragment/EventPageFragment.kt | 6 +- .../studip/viewmodel/CanteenPageViewModel.kt | 5 +- .../studip/viewmodel/EventPageViewModel.kt | 11 +++ .../studip/viewmodel/SettingsViewModel.kt | 7 +- app/src/main/res/layout/activity_main.xml | 1 + app/src/main/res/layout/fragment_canteen.xml | 18 ++-- app/src/main/res/menu/nav_view_items.xml | 4 +- .../main/res/navigation/main_nav_graph.xml | 22 +++++ build.gradle | 4 +- 12 files changed, 73 insertions(+), 119 deletions(-) create mode 100644 app/src/main/res/navigation/main_nav_graph.xml diff --git a/app/src/main/java/com/denizk0461/studip/activity/MainActivity.kt b/app/src/main/java/com/denizk0461/studip/activity/MainActivity.kt index 46fd66d..b8f9979 100644 --- a/app/src/main/java/com/denizk0461/studip/activity/MainActivity.kt +++ b/app/src/main/java/com/denizk0461/studip/activity/MainActivity.kt @@ -3,15 +3,10 @@ package com.denizk0461.studip.activity import android.os.Bundle import androidx.core.view.WindowCompat import androidx.fragment.app.FragmentActivity -import androidx.fragment.app.FragmentTransaction -import androidx.lifecycle.Lifecycle -import com.denizk0461.studip.R +import androidx.navigation.fragment.NavHostFragment +import androidx.navigation.fragment.findNavController +import androidx.navigation.ui.setupWithNavController import com.denizk0461.studip.databinding.ActivityMainBinding -import com.denizk0461.studip.db.AppRepository -import com.denizk0461.studip.fragment.EventFragment -import com.denizk0461.studip.fragment.CanteenFragment -import com.denizk0461.studip.fragment.SettingsFragment -import com.denizk0461.studip.model.SettingsPreferences /** * Main activity that handles all common fragments. This is opened on app launch. @@ -21,91 +16,17 @@ class MainActivity : FragmentActivity() { // View binding private lateinit var binding: ActivityMainBinding - /* - * Tag for the currently active fragment; set on activity launch to the fragment that will be - * shown first. - */ - private var currentFragment: String = "event" - override fun onCreate(savedInstanceState: Bundle?) { WindowCompat.setDecorFitsSystemWindows(window, false) super.onCreate(savedInstanceState) - /* - * Instantiate repository object that is accessed by the fragments' view models to retrieve - * data. - */ -// Dependencies.repo = AppRepository(application) - // Inflate view binding and bind to this activity binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) - // Set up navigation view bar to launch fragments - binding.navView.setOnItemSelectedListener { item -> - // Launch fragment based on the item that has been clicked - loadFragment(when (item.itemId) { - R.id.food -> "canteen" - R.id.settings -> "settings" - else -> "event" - }) - } - - // Set up bottom nav bar and the initial fragment when the app launches - if (savedInstanceState == null) { - // Open the fragment that the user specified to open on app start - if (AppRepository.getRepositoryInstance(application) - .getBooleanPreference(SettingsPreferences.LAUNCH_CANTEEN_ON_START) - ) { - // Open canteen fragment - binding.navView.selectedItemId = R.id.food - currentFragment = "canteen" - } else { - // Open event fragment - binding.navView.selectedItemId = R.id.plan - currentFragment = "event" - } - - // Launch the fragment defined in currentFragment - loadFragment(currentFragment) - } - } - - /** - * Loads a given fragment. - * - * @param type tag for the fragment that is to be opened - * @return true on success, false if another fragment is currently instantiating - */ - private fun loadFragment(type: String): Boolean { - - // Find the fragment that is to be opened, or create it if it hasn't been instantiated yet - val fragment = supportFragmentManager.findFragmentByTag(type) ?: getFragment(type) - - // Don't interrupt the current fragment's lifecycle if it isn't fully initialised - if (fragment.lifecycle.currentState != Lifecycle.State.INITIALIZED) { - return false - } - - // Start the transaction to show the new fragment - supportFragmentManager.beginTransaction() - .replace(R.id.nav_host_fragment_content_main, fragment, type) - .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE) - .commit() - - // Success - return true - } - - /** - * Retrieve fragment by its tag. - * - * @param type tag for the corresponding fragment - * @return the corresponding fragment - */ - private fun getFragment(type: String) = when (type) { - "canteen" -> CanteenFragment() // CanteenFragment.kt - "settings" -> SettingsFragment() // SettingsFragment.kt - else -> EventFragment() // on unknown value or "event", launch EventFragment.kt + // Set up bottom navigation view to navigate between fragments + binding.navView.setupWithNavController( + binding.navHostFragmentContentMain.getFragment().findNavController() + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/denizk0461/studip/adapter/StudIPEventItemAdapter.kt b/app/src/main/java/com/denizk0461/studip/adapter/StudIPEventItemAdapter.kt index ec05aaf..7247e80 100644 --- a/app/src/main/java/com/denizk0461/studip/adapter/StudIPEventItemAdapter.kt +++ b/app/src/main/java/com/denizk0461/studip/adapter/StudIPEventItemAdapter.kt @@ -24,6 +24,7 @@ import java.util.* */ class StudIPEventItemAdapter( private val currentDay: Int, + private val highlightNextCourse: Boolean, private val onClickListener: OnClickListener, ) : RecyclerView.Adapter() { @@ -80,10 +81,11 @@ class StudIPEventItemAdapter( val theme = holder.binding.root.context.theme /* - * Highlight the next upcoming course of the day if the day of the adapter matches the - * current day, and if no other course has been highlighted, to avoid double highlighting. + * Highlight the next upcoming course of the day if the user selected the option, if the day + * of the adapter matches the current day, and if no other course has been highlighted, to + * avoid double highlighting. */ - if (!isAnyCourseHighlighted && currentItem.isCurrentCourse(currentCalendar)) { + if (highlightNextCourse && !isAnyCourseHighlighted && currentItem.isCurrentCourse(currentCalendar)) { // Ensure that no other course will be highlighted isAnyCourseHighlighted = true diff --git a/app/src/main/java/com/denizk0461/studip/fragment/CanteenFragment.kt b/app/src/main/java/com/denizk0461/studip/fragment/CanteenFragment.kt index 1d69e14..cec507d 100644 --- a/app/src/main/java/com/denizk0461/studip/fragment/CanteenFragment.kt +++ b/app/src/main/java/com/denizk0461/studip/fragment/CanteenFragment.kt @@ -124,17 +124,6 @@ class CanteenFragment : AppFragment() { chip.setOnCheckedChangeListener { buttonView, newValue -> // Save the preference change to persistent storage setPreference(pref, newValue) - - /* - * Force an animation on click. This is a subpar method from StackOverflow. Since - * it removes the view before immediately adding it back, this method causes a - * flicker. - * TODO implement a more efficient / better-looking method - * TODO order the chips alphabetically? - */ -// val index = binding.chipsPreference.indexOfChild(buttonView) -// binding.chipsPreference.removeView(buttonView) -// binding.chipsPreference.addView(buttonView, index) } } @@ -152,6 +141,8 @@ class CanteenFragment : AppFragment() { // Let the adapter know of the new amount of dates (pages) to display viewPagerAdapter.itemCount = dates.size + + openingHours = viewModel.getCanteenOpeningHours() } // Assign the adapter to the view pager diff --git a/app/src/main/java/com/denizk0461/studip/fragment/EventPageFragment.kt b/app/src/main/java/com/denizk0461/studip/fragment/EventPageFragment.kt index 98a5a99..d2e9597 100644 --- a/app/src/main/java/com/denizk0461/studip/fragment/EventPageFragment.kt +++ b/app/src/main/java/com/denizk0461/studip/fragment/EventPageFragment.kt @@ -48,7 +48,11 @@ class EventPageFragment : AppFragment(), StudIPEventItemAdapter.OnClickListener currentDay = arguments?.getInt("currentDay") ?: -1 // Instantiate event adapter with the current day - eventAdapter = StudIPEventItemAdapter(currentDay, this) + eventAdapter = StudIPEventItemAdapter( + currentDay, + viewModel.preferenceCourseHighlighting, + this, + ) // Inflate view binding _binding = RecyclerViewBinding.inflate(inflater, container, false) diff --git a/app/src/main/java/com/denizk0461/studip/viewmodel/CanteenPageViewModel.kt b/app/src/main/java/com/denizk0461/studip/viewmodel/CanteenPageViewModel.kt index 0021e38..bf46c69 100644 --- a/app/src/main/java/com/denizk0461/studip/viewmodel/CanteenPageViewModel.kt +++ b/app/src/main/java/com/denizk0461/studip/viewmodel/CanteenPageViewModel.kt @@ -43,7 +43,6 @@ class CanteenPageViewModel(app: Application) : AppViewModel(app) { /** * This value determines which canteen the user has selected. */ - var preferenceColour: Boolean - get() = repo.getBooleanPreference(SettingsPreferences.COLOUR_PREFS) - set(newValue) { repo.setPreference(SettingsPreferences.COLOUR_PREFS, newValue) } + val preferenceColour: Boolean + get() = repo.getBooleanPreference(SettingsPreferences.COLOUR_PREFS, defaultValue = true) } \ No newline at end of file diff --git a/app/src/main/java/com/denizk0461/studip/viewmodel/EventPageViewModel.kt b/app/src/main/java/com/denizk0461/studip/viewmodel/EventPageViewModel.kt index add4888..e681b94 100644 --- a/app/src/main/java/com/denizk0461/studip/viewmodel/EventPageViewModel.kt +++ b/app/src/main/java/com/denizk0461/studip/viewmodel/EventPageViewModel.kt @@ -2,6 +2,7 @@ package com.denizk0461.studip.viewmodel import android.app.Application import androidx.lifecycle.LiveData +import com.denizk0461.studip.model.SettingsPreferences import com.denizk0461.studip.model.StudIPEvent /** @@ -17,4 +18,14 @@ class EventPageViewModel(app: Application) : AppViewModel(app) { * @return Stud.IP events for a certain day exposed through a LiveData object */ fun getEventsForDay(day: Int): LiveData> = repo.getEventsForDay(day) + + /** + * This value determines whether the user wants to have the next course in their schedule + * highlighted. + */ + val preferenceCourseHighlighting: Boolean + get() = repo.getBooleanPreference( + SettingsPreferences.COURSE_HIGHLIGHTING, + defaultValue = true + ) } \ No newline at end of file diff --git a/app/src/main/java/com/denizk0461/studip/viewmodel/SettingsViewModel.kt b/app/src/main/java/com/denizk0461/studip/viewmodel/SettingsViewModel.kt index aa096f4..1b6745a 100644 --- a/app/src/main/java/com/denizk0461/studip/viewmodel/SettingsViewModel.kt +++ b/app/src/main/java/com/denizk0461/studip/viewmodel/SettingsViewModel.kt @@ -15,7 +15,10 @@ class SettingsViewModel(app: Application) : AppViewModel(app) { * highlighted. */ var preferenceCourseHighlighting: Boolean - get() = repo.getBooleanPreference(SettingsPreferences.COURSE_HIGHLIGHTING) + get() = repo.getBooleanPreference( + SettingsPreferences.COURSE_HIGHLIGHTING, + defaultValue = true + ) set(newValue) { repo.setPreference(SettingsPreferences.COURSE_HIGHLIGHTING, newValue) } /** @@ -36,7 +39,7 @@ class SettingsViewModel(app: Application) : AppViewModel(app) { * This value determines which canteen the user has selected. */ var preferenceColour: Boolean - get() = repo.getBooleanPreference(SettingsPreferences.COLOUR_PREFS) + get() = repo.getBooleanPreference(SettingsPreferences.COLOUR_PREFS, defaultValue = true) set(newValue) { repo.setPreference(SettingsPreferences.COLOUR_PREFS, newValue) } /** diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 94ad7f4..84d6ff0 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -13,6 +13,7 @@ android:layout_width="0dp" android:layout_height="0dp" app:defaultNavHost="true" + app:navGraph="@navigation/main_nav_graph" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toTopOf="@+id/nav_view" app:layout_constraintStart_toStartOf="parent" diff --git a/app/src/main/res/layout/fragment_canteen.xml b/app/src/main/res/layout/fragment_canteen.xml index d247a63..c630388 100644 --- a/app/src/main/res/layout/fragment_canteen.xml +++ b/app/src/main/res/layout/fragment_canteen.xml @@ -44,6 +44,15 @@ + + - - diff --git a/app/src/main/res/navigation/main_nav_graph.xml b/app/src/main/res/navigation/main_nav_graph.xml new file mode 100644 index 0000000..2324615 --- /dev/null +++ b/app/src/main/res/navigation/main_nav_graph.xml @@ -0,0 +1,22 @@ + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 8f8bf02..25ad99d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id 'com.android.application' version '8.0.0' apply false - id 'com.android.library' version '8.0.0' apply false + id 'com.android.application' version '8.0.1' apply false + id 'com.android.library' version '8.0.1' apply false id 'org.jetbrains.kotlin.android' version '1.8.20' apply false } \ No newline at end of file