From 7ed230b4b9c715ffeec2befc4a6c5c0f48b1811d Mon Sep 17 00:00:00 2001 From: denizk0461 Date: Sat, 13 May 2023 10:00:40 +0200 Subject: [PATCH] Changed FABs into Extended FABs that collapse on scroll; updated FABs and scrolling behaviour of app bars; removed dimens.xml files for landscape and larger widths that had been generated by Android Studio --- README.md | 11 +- .../weserplaner/fragment/CanteenFragment.kt | 35 +- .../fragment/CanteenPageFragment.kt | 18 + .../weserplaner/fragment/EventFragment.kt | 27 ++ .../weserplaner/fragment/EventPageFragment.kt | 18 + app/src/main/res/layout/fragment_canteen.xml | 327 +++++++++--------- app/src/main/res/layout/fragment_event.xml | 16 +- app/src/main/res/layout/fragment_settings.xml | 2 +- app/src/main/res/layout/recycler_view.xml | 3 + app/src/main/res/values-de/strings.xml | 3 + app/src/main/res/values-land/dimens.xml | 3 - app/src/main/res/values-w1240dp/dimens.xml | 3 - app/src/main/res/values-w600dp/dimens.xml | 3 - app/src/main/res/values/strings.xml | 3 + 14 files changed, 280 insertions(+), 192 deletions(-) delete mode 100644 app/src/main/res/values-land/dimens.xml delete mode 100644 app/src/main/res/values-w1240dp/dimens.xml delete mode 100644 app/src/main/res/values-w600dp/dimens.xml diff --git a/README.md b/README.md index 3125073..668a09f 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,15 @@ Currently, nothing is outright broken, but a few things may be bodged together. ## Why Android-only? Because: -a) I know Android development and it's a lot easier for me to work on an app using a framework I already know than to learn a new one while still trying to keep up with my responsibilities at university, and -b) because Apple is a greedy company that charges thousands for laptops, phones, as well as $99 a year for a developer account, which are all requirements (sans the phone, if I was to use their simulator, which isn't ideal) and I, as a student, simply do not have the money for that. +- I know Android development and it's a lot easier for me to work on an app using a framework I already know than to learn a new one while still trying to keep up with my responsibilities at university, and +- because Apple is a greedy company that charges thousands for laptops, phones, as well as $99 a year for a developer account, which are all requirements (sans the phone, if I was to use their simulator, which isn't ideal) and I, as a student, simply do not have the money for that. + I may reconsider once Apple finally opens up iOS for third-party apps. +## Why this logo? Why this evil red colour scheme? + +The colour scheme is inspired by the University of Bremen's colour scheme, as well as the city of Bremen's colour scheme. The logo represents both the University of Bremen as well as (kind of) the Weserstadion, our local sports stadium. + +I admit the Weserstadion idea came to me after I had created the logo. + ![WeserPlaner app icon](https://denizk0461.github.io/weserplaner_app_icon.png) diff --git a/app/src/main/java/com/denizk0461/weserplaner/fragment/CanteenFragment.kt b/app/src/main/java/com/denizk0461/weserplaner/fragment/CanteenFragment.kt index 5d11696..cb207f0 100644 --- a/app/src/main/java/com/denizk0461/weserplaner/fragment/CanteenFragment.kt +++ b/app/src/main/java/com/denizk0461/weserplaner/fragment/CanteenFragment.kt @@ -8,6 +8,7 @@ import android.view.ViewGroup import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.widget.PopupMenu import androidx.fragment.app.viewModels +import androidx.viewpager2.widget.ViewPager2 import com.denizk0461.weserplaner.R import com.denizk0461.weserplaner.adapter.CanteenOfferPageAdapter import com.denizk0461.weserplaner.data.getTextSheet @@ -86,7 +87,6 @@ class CanteenFragment : AppFragment() { // Set up click listener to tell the user that no news are available binding.buttonNotifications.setOnClickListener { -// showToast(context, getString(R.string.text_sheet_news_empty)) context.theme.showSnackBar(binding.snackbarContainer, getString(R.string.text_sheet_news_empty)) } @@ -171,7 +171,6 @@ class CanteenFragment : AppFragment() { else -> 0 } // Set newly selected canteen to the button -// binding.buttonCanteenPicker.text = getCurrentlySelectedCanteenName() binding.appTitleBar.text = getString( R.string.title_canteen_template, getCurrentlySelectedCanteenName(), @@ -212,12 +211,6 @@ class CanteenFragment : AppFragment() { // Let the adapter know of the new amount of dates (pages) to display viewPagerAdapter.itemCount = dates.size - - // Retrieve further information about this canteen from the database -// viewModel.getCanteen().also { canteen -> - // Set visibility of the notifications icon depending on whether news are available -// badge.isVisible = info.news.isNotBlank() -// } } // Assign the adapter to the view pager @@ -228,6 +221,18 @@ class CanteenFragment : AppFragment() { tab.text = dates[position] }.attach() + // Set extended FAB to extend when the page is changed + binding.viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { + override fun onPageScrolled( + position: Int, + positionOffset: Float, + positionOffsetPixels: Int + ) { + super.onPageScrolled(position, positionOffset, positionOffsetPixels) + binding.fabRefreshOffers.extend() + } + }) + // Set up functions for when the user swipes to refresh the view binding.swipeRefreshLayout.setOnRefreshListener { refresh() @@ -252,6 +257,20 @@ class CanteenFragment : AppFragment() { _binding = null } + /** + * Shrinks the FAB. + */ + fun shrinkFab() { + binding.fabRefreshOffers.shrink() + } + + /** + * Extends the FAB. + */ + fun extendFab() { + binding.fabRefreshOffers.extend() + } + /** * Updates a given preference and refreshes the view. * diff --git a/app/src/main/java/com/denizk0461/weserplaner/fragment/CanteenPageFragment.kt b/app/src/main/java/com/denizk0461/weserplaner/fragment/CanteenPageFragment.kt index 3bfcd34..8d1a489 100644 --- a/app/src/main/java/com/denizk0461/weserplaner/fragment/CanteenPageFragment.kt +++ b/app/src/main/java/com/denizk0461/weserplaner/fragment/CanteenPageFragment.kt @@ -5,6 +5,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.viewModels +import androidx.navigation.fragment.NavHostFragment import androidx.recyclerview.widget.LinearLayoutManager import com.denizk0461.weserplaner.adapter.CanteenOfferItemAdapter import com.denizk0461.weserplaner.adapter.StudIPEventPageAdapter @@ -89,6 +90,23 @@ class CanteenPageFragment : AppFragment(), CanteenOfferItemAdapter.OnClickListen } } + // Retrieve parent fragment to access its functions + val navHostFragment = activity?.supportFragmentManager?.fragments?.get(0) as? NavHostFragment + val parent = navHostFragment?.childFragmentManager?.primaryNavigationFragment as? CanteenFragment + + // Set up scroll change listener to shrink and extend FAB accordingly + binding.recyclerView.setOnScrollChangeListener { _, _, scrollY, _, oldScrollY -> + // Calculate the vertical scroll difference + val dy = scrollY - oldScrollY + if (dy > 0) { + // If scrolling down, shrink the FAB + parent?.shrinkFab() + } else if (dy < 0) { + // If scrolling up, extend the FAB + parent?.extendFab() + } + } + // Observe dietary preference updates and re-set the items if a change is detected viewModel.dietaryPreferencesUpdate.observe(viewLifecycleOwner) { // Re-set the list of items to the recycler view, forcing an update diff --git a/app/src/main/java/com/denizk0461/weserplaner/fragment/EventFragment.kt b/app/src/main/java/com/denizk0461/weserplaner/fragment/EventFragment.kt index bbc3a28..b2ca0e7 100644 --- a/app/src/main/java/com/denizk0461/weserplaner/fragment/EventFragment.kt +++ b/app/src/main/java/com/denizk0461/weserplaner/fragment/EventFragment.kt @@ -6,6 +6,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.viewModels +import androidx.viewpager2.widget.ViewPager2 import com.denizk0461.weserplaner.R import com.denizk0461.weserplaner.activity.FetcherActivity import com.denizk0461.weserplaner.adapter.StudIPEventPageAdapter @@ -64,6 +65,18 @@ class EventFragment : AppFragment() { tab.text = weekdays[position] }.attach() + // Set extended FAB to extend when the page is changed + binding.viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { + override fun onPageScrolled( + position: Int, + positionOffset: Float, + positionOffsetPixels: Int + ) { + super.onPageScrolled(position, positionOffset, positionOffsetPixels) + binding.fabAddEvent.extend() + } + }) + // Set the view pager's current page to the current day, if the user chose this option if (viewModel.preferenceCurrentDay) { @@ -117,6 +130,20 @@ class EventFragment : AppFragment() { } } + /** + * Shrinks the FAB. + */ + fun shrinkFab() { + binding.fabAddEvent.shrink() + } + + /** + * Extends the FAB. + */ + fun extendFab() { + binding.fabAddEvent.extend() + } + // Invalidate the view binding override fun onDestroyView() { super.onDestroyView() diff --git a/app/src/main/java/com/denizk0461/weserplaner/fragment/EventPageFragment.kt b/app/src/main/java/com/denizk0461/weserplaner/fragment/EventPageFragment.kt index a9fccd5..8901502 100644 --- a/app/src/main/java/com/denizk0461/weserplaner/fragment/EventPageFragment.kt +++ b/app/src/main/java/com/denizk0461/weserplaner/fragment/EventPageFragment.kt @@ -5,6 +5,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.viewModels +import androidx.navigation.fragment.NavHostFragment import androidx.recyclerview.widget.LinearLayoutManager import com.denizk0461.weserplaner.adapter.StudIPEventPageAdapter import com.denizk0461.weserplaner.adapter.StudIPEventItemAdapter @@ -76,6 +77,23 @@ class EventPageFragment : AppFragment(), StudIPEventItemAdapter.OnClickListener scheduleLayoutAnimation() } + // Retrieve parent fragment to access its functions + val navHostFragment = activity?.supportFragmentManager?.fragments?.get(0) as? NavHostFragment + val parent = navHostFragment?.childFragmentManager?.primaryNavigationFragment as? EventFragment + + // Set up scroll change listener to shrink and extend FAB accordingly + binding.recyclerView.setOnScrollChangeListener { _, _, scrollY, _, oldScrollY -> + // Calculate the vertical scroll difference + val dy = scrollY - oldScrollY + if (dy > 0) { + // If scrolling down, shrink the FAB + parent?.shrinkFab() + } else if (dy < 0) { + // If scrolling up, extend the FAB + parent?.extendFab() + } + } + // Set up LiveData observer to refresh the view on update viewModel.getEventsForDay(currentDay).observe(viewLifecycleOwner) { events -> eventAdapter.setNewData(events) diff --git a/app/src/main/res/layout/fragment_canteen.xml b/app/src/main/res/layout/fragment_canteen.xml index 5b1f52c..2cb1054 100644 --- a/app/src/main/res/layout/fragment_canteen.xml +++ b/app/src/main/res/layout/fragment_canteen.xml @@ -16,8 +16,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" - app:layout_scrollFlags="scroll|exitUntilCollapsed"> - + app:layout_scrollFlags="scroll"> + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + app:layout_scrollFlags="scroll" + app:tabMode="scrollable" + android:background="@android:color/transparent"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -247,8 +249,7 @@ android:layout_height="wrap_content" android:orientation="vertical" android:layout_gravity="bottom|end" - app:layout_dodgeInsetEdges="bottom" - app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"> + app:layout_dodgeInsetEdges="bottom"> - + android:layout_marginBottom="@dimen/fab_margin"/> diff --git a/app/src/main/res/layout/fragment_event.xml b/app/src/main/res/layout/fragment_event.xml index 2a7312d..8573219 100644 --- a/app/src/main/res/layout/fragment_event.xml +++ b/app/src/main/res/layout/fragment_event.xml @@ -22,14 +22,15 @@ android:layout_marginHorizontal="16dp" android:layout_marginTop="16dp" android:layout_marginBottom="8dp" - app:layout_scrollFlags="scroll|exitUntilCollapsed"/> + app:layout_scrollFlags="scroll"/> + app:layout_scrollFlags="scroll" + android:background="@android:color/transparent"/> @@ -49,17 +50,14 @@ android:text="@string/event_empty_fetch_button" android:visibility="gone"/> - + android:layout_marginBottom="@dimen/fab_margin"/> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml index e05511c..960252f 100644 --- a/app/src/main/res/layout/fragment_settings.xml +++ b/app/src/main/res/layout/fragment_settings.xml @@ -22,7 +22,7 @@ android:layout_marginBottom="8dp" android:fontFamily="@font/lato_blackitalic" android:text="@string/title_settings" - app:layout_scrollFlags="scroll|exitUntilCollapsed" + app:layout_scrollFlags="scroll" android:textSize="28sp"/> diff --git a/app/src/main/res/layout/recycler_view.xml b/app/src/main/res/layout/recycler_view.xml index 38451d7..42af2ec 100644 --- a/app/src/main/res/layout/recycler_view.xml +++ b/app/src/main/res/layout/recycler_view.xml @@ -4,4 +4,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical" + android:paddingBottom="72dp" + android:clipToPadding="false" + android:scrollbarStyle="outsideOverlay" android:layoutAnimation="@anim/layout_animation_fall_down"/> \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 835f4ba..f66c496 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -42,6 +42,8 @@ • Logge dich mit deinem Stud.IP-Login ein\n • Öffne deinen Stundenplan (falls er sich nicht automatisch öffnet)\n • Klicke auf den \'Speichern\'-Knopf, der unten in der rechten Ecke auftauchen sollte\n • Fertig! Speichere den Stundenplan in der App ab + Neue Veranstaltung + Speichern Löschen Sicher? @@ -68,6 +70,7 @@ Zeige Öffnungszeiten Wechsle Mensa Aktualisiere Angebote + Aktualisieren %s – Öffnungszeiten diff --git a/app/src/main/res/values-land/dimens.xml b/app/src/main/res/values-land/dimens.xml deleted file mode 100644 index 22d7f00..0000000 --- a/app/src/main/res/values-land/dimens.xml +++ /dev/null @@ -1,3 +0,0 @@ - - 48dp - \ No newline at end of file diff --git a/app/src/main/res/values-w1240dp/dimens.xml b/app/src/main/res/values-w1240dp/dimens.xml deleted file mode 100644 index d73f4a3..0000000 --- a/app/src/main/res/values-w1240dp/dimens.xml +++ /dev/null @@ -1,3 +0,0 @@ - - 200dp - \ No newline at end of file diff --git a/app/src/main/res/values-w600dp/dimens.xml b/app/src/main/res/values-w600dp/dimens.xml deleted file mode 100644 index 22d7f00..0000000 --- a/app/src/main/res/values-w600dp/dimens.xml +++ /dev/null @@ -1,3 +0,0 @@ - - 48dp - \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2b96bbe..540dbfe 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -43,6 +43,8 @@ • Log in with your Stud.IP login\n • Open your timetable view (in case it doesn\'t open automatically)\n • Click the \'save\' button that should appear in the bottom right corner\n • Done! Save the timetable in the app + New event + Save Delete Sure? @@ -70,6 +72,7 @@ Show opening hours Switch canteen Refresh offers + Refresh %s – opening hours The opening hours could not be downloaded.