mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2024-11-24 19:04:38 -06:00
[UI] Add lazy loading to fragments with view pager.
This commit is contained in:
parent
41a79caf83
commit
043f8210ba
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-3-29.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.base.lazypager
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
abstract class LazyFragment : Fragment() {
|
||||
private var isPageCreated = false
|
||||
var swipeRefreshLayoutCallback: ((isEnabled: Boolean) -> Unit)? = null
|
||||
|
||||
/**
|
||||
* Called when the page is first shown, or if previous
|
||||
* [onPageCreated] returned false
|
||||
*
|
||||
* @return true if the view is set up
|
||||
* @return false if the setup failed. The method may be then called
|
||||
* again, when page becomes visible.
|
||||
*/
|
||||
abstract fun onPageCreated(): Boolean
|
||||
|
||||
internal fun createPage() {
|
||||
if (!isPageCreated && isAdded) {
|
||||
isPageCreated = onPageCreated()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
createPage()
|
||||
super.onResume()
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-3-29.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.base.lazypager
|
||||
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter
|
||||
|
||||
abstract class LazyPagerAdapter(fragmentManager: FragmentManager) : FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
|
||||
var swipeRefreshLayoutCallback: ((isEnabled: Boolean) -> Unit)? = null
|
||||
abstract override fun getItem(position: Int): LazyFragment
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2020-3-29.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.base.lazypager
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
|
||||
class LazyViewPager @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null
|
||||
) : ViewPager(context, attrs) {
|
||||
init {
|
||||
addOnPageChangeListener(object : OnPageChangeListener {
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
if (adapter is LazyPagerAdapter) {
|
||||
val fragment = adapter?.instantiateItem(this@LazyViewPager, position)
|
||||
val lazyFragment = fragment as? LazyFragment
|
||||
lazyFragment?.createPage()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -68,6 +68,10 @@ class HomeworkFragment : Fragment() {
|
||||
}))
|
||||
|
||||
b.viewPager.adapter = MessagesFragment.Adapter(childFragmentManager).also { adapter ->
|
||||
adapter.swipeRefreshLayoutCallback = { isEnabled ->
|
||||
b.refreshLayout.isEnabled = isEnabled
|
||||
}
|
||||
|
||||
adapter.addFragment(HomeworkListFragment().also { fragment ->
|
||||
fragment.arguments = Bundle().also { args ->
|
||||
args.putInt("homeworkDate", HomeworkDate.CURRENT)
|
||||
|
@ -4,17 +4,18 @@ import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Event
|
||||
import pl.szczodrzynski.edziennik.databinding.HomeworkListBinding
|
||||
import pl.szczodrzynski.edziennik.getInt
|
||||
import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyFragment
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class HomeworkListFragment : Fragment() {
|
||||
class HomeworkListFragment : LazyFragment() {
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var activity: MainActivity
|
||||
@ -30,11 +31,7 @@ class HomeworkListFragment : Fragment() {
|
||||
return b.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
// TODO check if app, activity, b can be null
|
||||
if (!isAdded)
|
||||
return
|
||||
|
||||
override fun onPageCreated(): Boolean {
|
||||
if (arguments != null) {
|
||||
homeworkDate = arguments.getInt("homeworkDate", HomeworkDate.CURRENT)
|
||||
}
|
||||
@ -45,6 +42,16 @@ class HomeworkListFragment : Fragment() {
|
||||
|
||||
b.homeworkView.setHasFixedSize(true)
|
||||
b.homeworkView.layoutManager = layoutManager
|
||||
b.homeworkView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
if (recyclerView.canScrollVertically(-1)) {
|
||||
swipeRefreshLayoutCallback?.invoke(false)
|
||||
}
|
||||
if (!recyclerView.canScrollVertically(-1) && newState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
swipeRefreshLayoutCallback?.invoke(true)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
val filter = when(homeworkDate) {
|
||||
HomeworkDate.CURRENT -> "eventDate >= '" + Date.getToday().stringY_m_d + "'"
|
||||
@ -66,5 +73,6 @@ class HomeworkListFragment : Fragment() {
|
||||
b.homeworkNoData.visibility = View.VISIBLE
|
||||
}
|
||||
})
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.FragmentPagerAdapter
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
@ -14,8 +13,9 @@ import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.databinding.FragmentMessagesBinding
|
||||
import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyPagerAdapter
|
||||
import pl.szczodrzynski.edziennik.utils.Themes
|
||||
import java.util.*
|
||||
|
||||
class MessagesFragment : Fragment() {
|
||||
companion object {
|
||||
@ -56,6 +56,10 @@ class MessagesFragment : Fragment() {
|
||||
|
||||
b.viewPager.adapter = Adapter(childFragmentManager).also { adapter ->
|
||||
|
||||
adapter.swipeRefreshLayoutCallback = { isEnabled ->
|
||||
b.refreshLayout.isEnabled = isEnabled
|
||||
}
|
||||
|
||||
adapter.addFragment(MessagesListFragment().also { fragment ->
|
||||
fragment.arguments = Bundle().also { args ->
|
||||
args.putInt("messageType", Message.TYPE_RECEIVED)
|
||||
@ -126,11 +130,11 @@ class MessagesFragment : Fragment() {
|
||||
}*/
|
||||
}
|
||||
|
||||
internal class Adapter(manager: FragmentManager) : FragmentPagerAdapter(manager) {
|
||||
private val mFragmentList = ArrayList<Fragment>()
|
||||
private val mFragmentTitleList = ArrayList<String>()
|
||||
internal class Adapter(manager: FragmentManager) : LazyPagerAdapter(manager) {
|
||||
private val mFragmentList = mutableListOf<LazyFragment>()
|
||||
private val mFragmentTitleList = mutableListOf<String>()
|
||||
|
||||
override fun getItem(position: Int): Fragment {
|
||||
override fun getItem(position: Int): LazyFragment {
|
||||
return mFragmentList[position]
|
||||
}
|
||||
|
||||
@ -138,7 +142,8 @@ class MessagesFragment : Fragment() {
|
||||
return mFragmentList.size
|
||||
}
|
||||
|
||||
fun addFragment(fragment: Fragment, title: String) {
|
||||
fun addFragment(fragment: LazyFragment, title: String) {
|
||||
fragment.swipeRefreshLayoutCallback = this@Adapter.swipeRefreshLayoutCallback
|
||||
mFragmentList.add(fragment)
|
||||
mFragmentTitleList.add(title)
|
||||
}
|
||||
|
@ -10,11 +10,10 @@ import android.view.ViewGroup;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -26,13 +25,15 @@ import pl.szczodrzynski.edziennik.data.db.entity.Message;
|
||||
import pl.szczodrzynski.edziennik.data.db.full.MessageFull;
|
||||
import pl.szczodrzynski.edziennik.data.db.full.MessageRecipientFull;
|
||||
import pl.szczodrzynski.edziennik.databinding.MessagesListBinding;
|
||||
import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyFragment;
|
||||
import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration;
|
||||
import pl.szczodrzynski.edziennik.utils.Themes;
|
||||
|
||||
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
||||
import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE;
|
||||
import static pl.szczodrzynski.edziennik.utils.Utils.d;
|
||||
|
||||
public class MessagesListFragment extends Fragment {
|
||||
public class MessagesListFragment extends LazyFragment {
|
||||
|
||||
private App app = null;
|
||||
private MainActivity activity = null;
|
||||
@ -65,9 +66,9 @@ public class MessagesListFragment extends Fragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
public boolean onPageCreated() {
|
||||
if (app == null || activity == null || b == null || !isAdded())
|
||||
return;
|
||||
return false;
|
||||
|
||||
long messageId = -1;
|
||||
if (getArguments() != null) {
|
||||
@ -78,7 +79,7 @@ public class MessagesListFragment extends Fragment {
|
||||
args.putLong("messageId", messageId);
|
||||
getArguments().remove("messageId");
|
||||
activity.loadTarget(MainActivity.TARGET_MESSAGES_DETAILS, args);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getArguments() != null) {
|
||||
@ -161,11 +162,24 @@ public class MessagesListFragment extends Fragment {
|
||||
// TODO ANIMATION
|
||||
//postponeEnterTransition();
|
||||
|
||||
viewParent = (ViewGroup) view.getParent();
|
||||
viewParent = (ViewGroup) getView().getParent();
|
||||
|
||||
b.emailList.setLayoutManager(new LinearLayoutManager(view.getContext()));
|
||||
b.emailList.addItemDecoration(new SimpleDividerItemDecoration(view.getContext()));
|
||||
b.emailList.setLayoutManager(new LinearLayoutManager(getView().getContext()));
|
||||
b.emailList.addItemDecoration(new SimpleDividerItemDecoration(getView().getContext()));
|
||||
b.emailList.setAdapter(messagesAdapter);
|
||||
b.emailList.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
|
||||
if (b.emailList.canScrollVertically(-1)) {
|
||||
if (getSwipeRefreshLayoutCallback() != null)
|
||||
getSwipeRefreshLayoutCallback().invoke(false);
|
||||
}
|
||||
if (!b.emailList.canScrollVertically(-1) && newState == SCROLL_STATE_IDLE) {
|
||||
if (getSwipeRefreshLayoutCallback() != null)
|
||||
getSwipeRefreshLayoutCallback().invoke(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (messageType == Message.TYPE_RECEIVED) {
|
||||
App.db.messageDao().getReceived(App.Companion.getProfileId()).observe(this, messageFulls -> {
|
||||
@ -215,7 +229,7 @@ public class MessagesListFragment extends Fragment {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void createMessageList(List<MessageFull> messageFulls) {
|
||||
|
@ -27,7 +27,7 @@ import pl.szczodrzynski.edziennik.data.db.full.LessonFull
|
||||
import pl.szczodrzynski.edziennik.databinding.TimetableLessonBinding
|
||||
import pl.szczodrzynski.edziennik.databinding.TimetableNoTimetableBinding
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.timetable.LessonDetailsDialog
|
||||
import pl.szczodrzynski.edziennik.ui.modules.base.PagerFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.timetable.TimetableFragment.Companion.DEFAULT_END_HOUR
|
||||
import pl.szczodrzynski.edziennik.ui.modules.timetable.TimetableFragment.Companion.DEFAULT_START_HOUR
|
||||
import pl.szczodrzynski.edziennik.utils.ListenerScrollView
|
||||
@ -36,7 +36,7 @@ import java.util.*
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.math.min
|
||||
|
||||
class TimetableDayFragment : PagerFragment(), CoroutineScope {
|
||||
class TimetableDayFragment : LazyFragment(), CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "TimetableDayFragment"
|
||||
}
|
||||
@ -104,9 +104,6 @@ class TimetableDayFragment : PagerFragment(), CoroutineScope {
|
||||
}
|
||||
|
||||
override fun onPageCreated(): Boolean {
|
||||
if (!isAdded)
|
||||
return false
|
||||
|
||||
// observe lesson database
|
||||
app.db.timetableDao().getForDate(App.profileId, date).observe(this, Observer { lessons ->
|
||||
launch {
|
||||
|
@ -5,9 +5,9 @@
|
||||
package pl.szczodrzynski.edziennik.ui.modules.timetable
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.FragmentStatePagerAdapter
|
||||
import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyPagerAdapter
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Week
|
||||
|
||||
@ -16,7 +16,7 @@ class TimetablePagerAdapter(
|
||||
private val items: List<Date>,
|
||||
private val startHour: Int,
|
||||
private val endHour: Int
|
||||
) : FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
|
||||
) : LazyPagerAdapter(fragmentManager) {
|
||||
companion object {
|
||||
private const val TAG = "TimetablePagerAdapter"
|
||||
}
|
||||
@ -25,8 +25,9 @@ class TimetablePagerAdapter(
|
||||
private val weekStart by lazy { today.weekStart }
|
||||
private val weekEnd by lazy { weekStart.clone().stepForward(0, 0, 6) }
|
||||
|
||||
override fun getItem(position: Int): Fragment {
|
||||
override fun getItem(position: Int): LazyFragment {
|
||||
return TimetableDayFragment().apply {
|
||||
swipeRefreshLayoutCallback = this@TimetablePagerAdapter.swipeRefreshLayoutCallback
|
||||
arguments = Bundle().apply {
|
||||
putInt("date", items[position].value)
|
||||
putInt("startHour", startHour)
|
||||
|
@ -1,7 +1,6 @@
|
||||
<?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">
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator
|
||||
android:id="@+id/refreshLayout"
|
||||
@ -23,7 +22,7 @@
|
||||
app:tabSelectedTextColor="?colorPrimary"
|
||||
app:tabTextColor="?android:textColorPrimary" />
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
<pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyViewPager
|
||||
android:id="@+id/viewPager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
@ -21,7 +21,7 @@
|
||||
app:tabSelectedTextColor="?colorPrimary"
|
||||
app:tabTextColor="?android:textColorPrimary"/>
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
<pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyViewPager
|
||||
android:id="@+id/viewPager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
@ -29,4 +29,4 @@
|
||||
</LinearLayout>
|
||||
|
||||
</pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator>
|
||||
</layout>
|
||||
</layout>
|
||||
|
@ -28,7 +28,7 @@
|
||||
android:id="@+id/tabLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:background="@color/colorSurface_6dp"
|
||||
android:background="@color/colorSurface_1dp"
|
||||
app:rtl_tabIndicatorColor="?colorPrimary"
|
||||
app:rtl_tabMaxWidth="300dp"
|
||||
app:rtl_tabMinWidth="90dp"
|
||||
@ -40,7 +40,7 @@
|
||||
app:rtl_tabTextAppearance="@style/rtl_RecyclerTabLayout.Tab" />
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
<pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyViewPager
|
||||
android:id="@+id/viewPager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
@ -94,4 +94,4 @@
|
||||
|
||||
</FrameLayout>
|
||||
<!--</pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator>-->
|
||||
</layout>
|
||||
</layout>
|
||||
|
Loading…
Reference in New Issue
Block a user