StwParser.kt now collects all its data before adding everything to the database all at once, fixing problems where LiveData would update before all transactions were finished; ViewPagers have been updated to use Adapters extending FragmentStateAdapter instead of RecyclerView.Adapter

This commit is contained in:
denizk0461
2023-04-27 21:58:10 +02:00
parent ccd77a5daf
commit ce7b854e8c
15 changed files with 373 additions and 164 deletions
+1 -1
View File
@@ -8,10 +8,10 @@
<inspection_tool class="AndroidLintNegativeMargin" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AndroidLintStringFormatTrivial" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="AndroidLintTypos" enabled="true" level="TYPO" enabled_by_default="true" />
<inspection_tool class="BooleanParameter" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="Destructure" enabled="true" level="INFO" enabled_by_default="true" />
<inspection_tool class="DirectUseOfResultType" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="IncompleteDestructuring" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="KDocMissingDocumentation" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="NoConstructorMigration" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="NonExhaustiveWhenStatementMigration" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PublicApiImplicitType" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
@@ -49,6 +49,15 @@ class CanteenOfferItemAdapter(
// Retrieve item for current position
val currentItem = offers[position]
/*
* Children of the line container MUST be removed before any are added, as otherwise, during
* recycling, lines will be duplicated when they are scrolled off the visible screen area
* and then scrolled onto the screen again. In other terms, if removeAllViews() wasn't
* called and the user was to scroll down a list and then back up again, the items at the
* top of the list would be added again, creating duplicates.
*/
holder.binding.lineContainer.removeAllViews()
// If an item has been added to mark that there are no offers available, tell the user
if (currentItem.category == "NO\$ITEMS") {
@@ -1,16 +1,15 @@
package com.denizk0461.studip.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.denizk0461.studip.databinding.ItemScrollablePageBinding
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.denizk0461.studip.fragment.CanteenPageFragment
import com.denizk0461.studip.model.CanteenOfferGroup
/**
* Custom RecyclerView adapter for managing multiple pages of canteen offers in a RecyclerView or
* ViewPager.
* Custom ViewPager adapter for managing multiple pages of canteen offers.
*
* @param fragmentActivity parent fragment activity
* @param offers all offers for a given canteen, grouped by category (not filtered by day at
* this point)
* @param daysCovered tells for how many days offers are available for.
@@ -20,55 +19,24 @@ import com.denizk0461.studip.model.CanteenOfferGroup
* @param displayAllergens whether the user wants allergens to be marked
*/
class CanteenOfferPageAdapter(
fragmentActivity: FragmentActivity,
private var offers: List<CanteenOfferGroup>,
private var daysCovered: Int,
private val onClickListener: CanteenOfferItemAdapter.OnClickListener,
private val displayAllergens: Boolean,
) : RecyclerView.Adapter<CanteenOfferPageAdapter.CanteenOfferPageViewHolder>() {
/**
* View holder class for parent class
*
* @param binding view binding object
*/
class CanteenOfferPageViewHolder(val binding: ItemScrollablePageBinding) : RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CanteenOfferPageViewHolder =
CanteenOfferPageViewHolder(
ItemScrollablePageBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
) : FragmentStateAdapter(fragmentActivity) {
// Returns the count of days covered
override fun getItemCount(): Int = daysCovered
override fun onBindViewHolder(holder: CanteenOfferPageViewHolder, position: Int) {
holder.binding.pageRecyclerView.apply {
// Set page to horizontally scroll
layoutManager = LinearLayoutManager(
holder.binding.root.context, LinearLayoutManager.VERTICAL, false
)
/*
* Create new adapter for every page. Attribute position denotes day that will be set up
* by the newly created adapter (0 = Monday, 4 = Friday)
* TODO check if the filtered list is empty, and tell the user if it is
*/
adapter = CanteenOfferItemAdapter(
offers.filter { it.dateId == position },
override fun createFragment(position: Int): Fragment =
CanteenPageFragment(
offers,
onClickListener,
displayAllergens,
position,
)
// Animate creation of new page
scheduleLayoutAnimation()
}
}
/**
* Update the entire list of items
*
@@ -1,61 +1,31 @@
package com.denizk0461.studip.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.denizk0461.studip.model.StudIPEvent
import com.denizk0461.studip.databinding.ItemScrollablePageBinding
import com.denizk0461.studip.fragment.EventPageFragment
/**
* Custom RecyclerView adapter for managing multiple pages of Stud.IP events in a RecyclerView or
* ViewPager.
* Custom ViewPager adapter for managing multiple pages of Stud.IP events.
*
* @param fragmentActivity parent fragment activity
* @param events all events (not filtered by day at this point)
* @param onClickListener for managing click and long press events
*/
class StudIPEventPageAdapter(
fragmentActivity: FragmentActivity,
private var events: List<StudIPEvent>,
private val onClickListener: StudIPEventItemAdapter.OnClickListener,
) : RecyclerView.Adapter<StudIPEventPageAdapter.EventPageViewHolder>() {
/**
* View holder class for parent class
*
* @param binding view binding object
*/
class EventPageViewHolder(val binding: ItemScrollablePageBinding) : RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EventPageViewHolder = EventPageViewHolder(
ItemScrollablePageBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
) : FragmentStateAdapter(fragmentActivity) {
/*
* Assume that there will always be 5 pages, for 5 days - Monday through Friday.
* TODO is it right to assume that the user only has events on weekdays?
* Assume that there will always be 7 pages, for 7 days - Monday through Sunday.
*/
override fun getItemCount(): Int = 5
override fun getItemCount(): Int = 7
// Set up page
override fun onBindViewHolder(holder: EventPageViewHolder, position: Int) {
holder.binding.pageRecyclerView.apply {
// Set page to horizontally scroll
layoutManager = LinearLayoutManager(holder.binding.root.context, LinearLayoutManager.VERTICAL, false)
/*
* Create new adapter for every page. Attribute position denotes day that will be set up
* by the newly created adapter (0 = Monday, 4 = Friday)
*/
adapter = StudIPEventItemAdapter(events, currentDay = position, onClickListener) // TODO check if empty
// Animate creation of new page
scheduleLayoutAnimation()
}
}
override fun createFragment(position: Int): Fragment =
EventPageFragment(events, position, onClickListener)
/**
* Update the entire list of items
@@ -1,6 +1,5 @@
package com.denizk0461.studip.data
import com.denizk0461.studip.db.AppRepository
import com.denizk0461.studip.model.*
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
@@ -63,8 +62,15 @@ class StwParser {
Dependencies.repo.nukeOffers()
// Fetch offers from the chosen canteen
parseFromPage(link, Dependencies.repo)
val (dates, canteens, categories, items) = parseFromPage(link)
// Save everything all at once into the database
with (Dependencies.repo) {
insertDates(dates)
insertCanteens(canteens)
insertCategories(categories)
insertItems(items)
}
// TODO implement onRefresh(Int)
// Action call once all fetching activities have finished
@@ -75,9 +81,14 @@ class StwParser {
* Fetch and parse the plan of a specific canteen.
*
* @param url link to the canteen to be scraped. Must be a subpage of stw-bremen.de
* @param repo reference to the app repository used to save the items to persistent storage
*/
private fun parseFromPage(url: String, repo: AppRepository) {
private fun parseFromPage(url: String): StwResults {
val dates = mutableListOf<OfferDate>()
val canteens = mutableListOf<OfferCanteen>()
val categories = mutableListOf<OfferCategory>()
val items = mutableListOf<OfferItem>()
// Used to store a parsed date string without creating a new variable on every loop
var date: String
@@ -120,8 +131,8 @@ class StwParser {
// Trim off excess line breaks
openingHours = openingHours.trim()
// Save the canteen to persistent storage
repo.insert(
// Save the canteen to its list
canteens.add(
OfferCanteen(
canteenId,
doc.getElementsByClass("pane-title")[1].text(),
@@ -148,12 +159,8 @@ class StwParser {
*/
date = "${rawDate[0]}${rawDate[1].monthToNumber()}."
/*
* Save the date to persistent storage.
* TODO this will duplicate date entries for every canteen that is fetched. This is
* inefficient.
*/
repo.insert(OfferDate(dateId, date))
// Save the date to its list
dates.add(OfferDate(dateId, date))
dateHasItems = false
@@ -165,8 +172,8 @@ class StwParser {
// Retrieve the category text
val categoryTitle = category.getElementsByClass("category-name")[0].text()
// Save the category to persistent storage
repo.insert(OfferCategory(categoryId, dateId, canteenId, categoryTitle))
// Save the category to its list
categories.add(OfferCategory(categoryId, dateId, canteenId, categoryTitle))
// Iterate through all items in a category
category
@@ -195,8 +202,8 @@ class StwParser {
val filteredText = tableRows[1].getFilteredText()
// Save the item to persistent storage
repo.insert(
// Save the item to its list
items.add(
OfferItem(
itemId,
categoryId,
@@ -219,8 +226,8 @@ class StwParser {
* is available. Text will then be handled in the adapter class.
*/
if (!dateHasItems) {
repo.insert(OfferCategory(categoryId, dateId, canteenId, "NO\$ITEMS"))
repo.insert(
categories.add(OfferCategory(categoryId, dateId, canteenId, "NO\$ITEMS"))
items.add(
OfferItem(
itemId,
categoryId,
@@ -240,6 +247,8 @@ class StwParser {
}
// Increment the canteen ID to avoid conflict
canteenId += 1
return StwResults(dates, canteens, categories, items)
}
/**
@@ -366,6 +375,13 @@ class StwParser {
// .replace("<p>", "")
// .replace("</p>", "")
private data class StwResults(
val dates: List<OfferDate>,
val canteens: List<OfferCanteen>,
val categories: List<OfferCategory>,
val items: List<OfferItem>,
)
// Image links to all dietary preferences used for checking whether a preference is met
private val imageLinkPrefFair = "https://www.stw-bremen.de/sites/default/files/images/pictograms/at_small.png"
private val imageLinkPrefFish = "https://www.stw-bremen.de/sites/default/files/images/pictograms/fisch.png"
@@ -49,7 +49,7 @@ interface AppDAO {
*
* @param events objects to be saved to the database
*/
@Insert fun insert(events: List<StudIPEvent>)
@Insert fun insertEvents(events: List<StudIPEvent>)
/**
* Deletes all Stud.IP events from the database.
@@ -128,6 +128,13 @@ interface AppDAO {
*/
@Insert fun insert(date: OfferDate)
/**
* Inserts a list of dates into the database.
*
* @param dates objects to be saved to the database
*/
@Insert fun insertDates(dates: List<OfferDate>)
/**
* Inserts a canteen into the database.
*
@@ -135,6 +142,13 @@ interface AppDAO {
*/
@Insert fun insert(canteen: OfferCanteen)
/**
* Inserts a list of canteens into the database.
*
* @param canteens objects to be saved to the database
*/
@Insert fun insertCanteens(canteens: List<OfferCanteen>)
/**
* Inserts a canteen offer category into the database.
*
@@ -142,6 +156,13 @@ interface AppDAO {
*/
@Insert fun insert(category: OfferCategory)
/**
* Inserts a list of categories into the database.
*
* @param categories objects to be saved to the database
*/
@Insert fun insertCategories(categories: List<OfferCategory>)
/**
* Inserts a canteen offer item into the database.
*
@@ -149,6 +170,13 @@ interface AppDAO {
*/
@Insert fun insert(item: OfferItem)
/**
* Inserts a list of items into the database.
*
* @param items objects to be saved to the database
*/
@Insert fun insertItems(items: List<OfferItem>)
/**
* Retrieves the opening hours of the canteen as a string.
*
@@ -37,7 +37,7 @@ class AppRepository(app: Application) {
*
* @param events objects to be saved to the database
*/
fun insertEvents(events: List<StudIPEvent>) { dao.insert(events) }
fun insertEvents(events: List<StudIPEvent>) { dao.insertEvents(events) }
/**
* Deletes all Stud.IP events from the database.
@@ -173,6 +173,13 @@ class AppRepository(app: Application) {
*/
fun insert(date: OfferDate) { dao.insert(date) }
/**
* Inserts a list of dates into the database.
*
* @param dates objects to be saved to the database
*/
fun insertDates(dates: List<OfferDate>) { dao.insertDates(dates) }
/**
* Inserts a canteen into the database.
*
@@ -180,6 +187,13 @@ class AppRepository(app: Application) {
*/
fun insert(canteen: OfferCanteen) { dao.insert(canteen) }
/**
* Inserts a list of canteens into the database.
*
* @param canteens objects to be saved to the database
*/
fun insertCanteens(canteens: List<OfferCanteen>) { dao.insertCanteens(canteens) }
/**
* Inserts a canteen offer category into the database.
*
@@ -187,6 +201,13 @@ class AppRepository(app: Application) {
*/
fun insert(category: OfferCategory) { dao.insert(category) }
/**
* Inserts a list of categories into the database.
*
* @param categories objects to be saved to the database
*/
fun insertCategories(categories: List<OfferCategory>) { dao.insertCategories(categories) }
/**
* Inserts a canteen offer item into the database.
*
@@ -194,6 +215,13 @@ class AppRepository(app: Application) {
*/
fun insert(item: OfferItem) { dao.insert(item) }
/**
* Inserts a list of items into the database.
*
* @param items objects to be saved to the database
*/
fun insertItems(items: List<OfferItem>) { dao.insertItems(items) }
// --- settings preferences --- //
/**
@@ -5,6 +5,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.PopupMenu
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.viewModels
import com.denizk0461.studip.R
import com.denizk0461.studip.adapter.CanteenOfferItemAdapter
@@ -145,7 +146,11 @@ class CanteenFragment : AppFragment(), CanteenOfferItemAdapter.OnClickListener {
// Set up the view pager's adapter
viewPagerAdapter = CanteenOfferPageAdapter(
listOf(), 0, this, viewModel.preferenceAllergen
activity as FragmentActivity,
listOf(),
0,
this,
viewModel.preferenceAllergen,
)
// Assign the adapter to the view pager
@@ -163,7 +168,9 @@ class CanteenFragment : AppFragment(), CanteenOfferItemAdapter.OnClickListener {
val groupedElements = offers.groupElements().distinct()
// Find all dates stored in the database
val newDates = /*groupedElements.map { it.date }.distinct() TODO */viewModel.getDates()
// val newDates = /*groupedElements.map { it.date }.distinct() TODO */viewModel.getDates()
val newDates = groupedElements.map { it.date }.distinct()
// Update the date count stored in this fragment
dateSize = newDates.size
@@ -0,0 +1,71 @@
package com.denizk0461.studip.fragment
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import com.denizk0461.studip.adapter.CanteenOfferItemAdapter
import com.denizk0461.studip.adapter.StudIPEventPageAdapter
import com.denizk0461.studip.databinding.RecyclerViewBinding
import com.denizk0461.studip.model.CanteenOfferGroup
/**
* Fragment that is instantiated by [StudIPEventPageAdapter] to display individual days' pages and
* their events.
*
* @param offers all offers for a given canteen, grouped by category (not filtered by day at
* this point)
* @param onClickListener for managing click and long press events
* @param displayAllergens whether the user wants allergens to be marked
* @param currentDay current day
*/
class CanteenPageFragment(
private var offers: List<CanteenOfferGroup>,
private val onClickListener: CanteenOfferItemAdapter.OnClickListener,
private val displayAllergens: Boolean,
private val currentDay: Int,
) : AppFragment() {
// Nullable view binding reference
private var _binding: RecyclerViewBinding? = null
/*
* Non-null reference to the view binding. This property is only valid between onCreateView and
* onDestroyView.
*/
private val binding get() = _binding!!
// Instantiate the view binding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = RecyclerViewBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.recyclerView.apply {
// Set page to scroll vertically
layoutManager = LinearLayoutManager(
context, LinearLayoutManager.VERTICAL, false
)
/*
* Create new adapter for every page. Attribute position denotes day that will be set up
* by the newly created adapter (0 = Monday, 4 = Friday)
* TODO check if the filtered list is empty, and tell the user if it is
*/
val o = offers.filter { it.dateId == currentDay }
adapter = CanteenOfferItemAdapter(
o,
onClickListener,
displayAllergens,
)
// Animate creation of new page
scheduleLayoutAnimation()
}
}
}
@@ -1,9 +1,12 @@
package com.denizk0461.studip.fragment
import android.os.Bundle
import android.os.Parcelable
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.viewModels
import com.denizk0461.studip.R
import com.denizk0461.studip.adapter.StudIPEventItemAdapter
@@ -39,13 +42,12 @@ class EventFragment : AppFragment() {
private var dayOfWeek: Int = 0
// Titles for the view pager's tabs
private val dayStrings = listOf(
R.string.monday,
R.string.tuesday,
R.string.wednesday,
R.string.thursday,
R.string.friday,
)
private lateinit var weekdays: Array<String>
// private var viewPagerScrollPosition: Parcelable? = null
private var viewPagerPosition = -1
private var hasFragmentStarted = false
// Instantiate the view binding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
@@ -56,24 +58,29 @@ class EventFragment : AppFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
/*
* Determine the current day.
* TODO expand to weekend
*/
weekdays = resources.getStringArray(R.array.weekdays)
// Determine the current day
dayOfWeek = when (Calendar.getInstance().get(Calendar.DAY_OF_WEEK)) {
Calendar.TUESDAY -> 1
Calendar.WEDNESDAY -> 2
Calendar.THURSDAY -> 3
Calendar.FRIDAY -> 4
else -> 0
Calendar.SATURDAY -> 5
Calendar.SUNDAY -> 6
else -> 0 // assume Monday
}
// Set up the view pager's adapter
viewPagerAdapter = StudIPEventPageAdapter(listOf(), object : StudIPEventItemAdapter.OnClickListener {
viewPagerAdapter =
StudIPEventPageAdapter(activity as FragmentActivity, listOf(), object : StudIPEventItemAdapter.OnClickListener {
override fun onClick(event: StudIPEvent) {
// TODO implement functionality or delete
}
override fun onLongClick(event: StudIPEvent): Boolean {
// Save the current page of the ViewPager
viewPagerPosition = binding.viewPager.currentItem
// Open a bottom sheet to edit the event
openBottomSheet(ScheduleUpdateSheet(event, onUpdate = { eventToUpdate ->
viewModel.update(eventToUpdate)
@@ -89,7 +96,7 @@ class EventFragment : AppFragment() {
// Create and attach the object mediating the tabs for the view pager
TabLayoutMediator(binding.dayTabLayout, binding.viewPager) { tab, position ->
tab.text = getString(dayStrings[position])
tab.text = weekdays[position]
}.attach()
// Set up LiveData observer to refresh the view on update
@@ -97,16 +104,53 @@ class EventFragment : AppFragment() {
// Update the item list in the view pager's adapter
viewPagerAdapter.setNewItems(events)
// Scroll to the current day
if (!hasFragmentStarted) {
// Scroll to the current day, if no page has been stored to be scrolled to
switchToCurrentDayView()
hasFragmentStarted = true
// } else {
// /*
// * If a page was previously saved, scroll to that one instead. This is meant to
// * prevent jumping from
// */
// binding.viewPager.currentItem = viewPagerPosition
}
}
}
override fun onPause() {
// viewPagerPosition = binding.viewPager.currentItem
// Log.d("AAA?", "onpause: $viewPagerPosition")
super.onPause()
}
override fun onResume() {
super.onResume()
binding.viewPager.currentItem = viewPagerPosition
Log.d("AAA?", "onresume: pos: $viewPagerPosition; vpp: ${binding.viewPager.currentItem}")
// Scroll to the current day
switchToCurrentDayView()
// switchToCurrentDayView()
}
/**
* Called when the layout changes (e.g. device rotation) but NOT when the fragment is selected
* from the bottom navigation view.
*/
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
Log.d("AAA?", "${binding.viewPager.currentItem}")
outState.putInt(
"viewPagerCurrentPage",
binding.viewPager.currentItem
)
}
override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
val restoredPage = savedInstanceState?.getInt("viewPagerCurrentPage") ?: 0
viewPagerPosition = restoredPage
}
// Invalidate the view binding
@@ -0,0 +1,60 @@
package com.denizk0461.studip.fragment
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import com.denizk0461.studip.adapter.StudIPEventPageAdapter
import com.denizk0461.studip.adapter.StudIPEventItemAdapter
import com.denizk0461.studip.databinding.RecyclerViewBinding
import com.denizk0461.studip.model.StudIPEvent
/**
* Fragment that is instantiated by [StudIPEventPageAdapter] to display individual days' pages and
* their events.
*
* @param events list of all events (still not filtered by day at this point)
* @param currentDay current day that is used to show only events of a given day (0 = Monday,
* 4 = Friday)
* @param onClickListener used for listening to clicks and long presses
*/
class EventPageFragment(
private val events: List<StudIPEvent>,
private val currentDay: Int,
private val onClickListener: StudIPEventItemAdapter.OnClickListener,
) : AppFragment() {
// Nullable view binding reference
private var _binding: RecyclerViewBinding? = null
/*
* Non-null reference to the view binding. This property is only valid between onCreateView and
* onDestroyView.
*/
private val binding get() = _binding!!
// Instantiate the view binding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = RecyclerViewBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.recyclerView.apply {
// Set page to scroll vertically
layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
/*
* Create new adapter for every page. Attribute position denotes day that will be set up
* by the newly created adapter (0 = Monday, 4 = Friday)
*/
adapter = StudIPEventItemAdapter(events, currentDay, onClickListener) // TODO check if empty
// Animate creation of new page
scheduleLayoutAnimation()
}
}
}
@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/page_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/layout_animation_fall_down">
</androidx.recyclerview.widget.RecyclerView>
</androidx.core.widget.NestedScrollView>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:layoutAnimation="@anim/layout_animation_fall_down"/>
+10 -3
View File
@@ -9,6 +9,16 @@
<string name="saturday">Samstag</string>
<string name="sunday">Sonntag</string>
<string-array name="weekdays">
<item>Montag</item>
<item>Dienstag</item>
<item>Mittwoch</item>
<item>Donnerstag</item>
<item>Freitag</item>
<item>Samstag</item>
<item>Sonntag</item>
</string-array>
<string name="fetch_error_snack">Ein Fehler ist aufgetreten!</string>
<string name="save">Speichern</string>
@@ -121,9 +131,6 @@
<string name="settings_highlight_title">Markiere meinen nächsten Kurs</string>
<string name="settings_highlight_subtitle">Funktioniert nur wenn Kurse sich nicht überschneiden!</string>
<string name="settings_quarter_title">Nutze akademisches Viertel</string>
<string name="settings_quarter_subtitle">Wo es passt</string>
<string name="settings_allergens_title">Markiere Angebote mit Allergenen mit einem Stern*</string>
<string name="settings_allergens_subtitle">Wird auch für Zusatzstoffe genutzt</string>
+10
View File
@@ -9,6 +9,16 @@
<string name="saturday">Saturday</string>
<string name="sunday">Sunday</string>
<string-array name="weekdays">
<item>Monday</item>
<item>Tuesday</item>
<item>Wednesday</item>
<item>Thursday</item>
<item>Friday</item>
<item>Saturday</item>
<item>Sunday</item>
</string-array>
<string name="fetch_error_snack">Something went wrong!</string>
<string name="save">Save</string>