[UI] Add pager fragment templates. Move all templates to 'template' module. Fix swipe to refresh with pager fragments.

This commit is contained in:
Kuba Szczodrzyński 2020-03-30 12:50:21 +02:00
parent 043f8210ba
commit 8c869d082b
18 changed files with 223 additions and 79 deletions

View File

@ -73,6 +73,7 @@ import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesListFragment
import pl.szczodrzynski.edziennik.ui.modules.notifications.NotificationsFragment import pl.szczodrzynski.edziennik.ui.modules.notifications.NotificationsFragment
import pl.szczodrzynski.edziennik.ui.modules.settings.ProfileManagerFragment import pl.szczodrzynski.edziennik.ui.modules.settings.ProfileManagerFragment
import pl.szczodrzynski.edziennik.ui.modules.settings.SettingsNewFragment import pl.szczodrzynski.edziennik.ui.modules.settings.SettingsNewFragment
import pl.szczodrzynski.edziennik.ui.modules.template.TemplateFragment
import pl.szczodrzynski.edziennik.ui.modules.timetable.TimetableFragment import pl.szczodrzynski.edziennik.ui.modules.timetable.TimetableFragment
import pl.szczodrzynski.edziennik.ui.modules.webpush.WebPushFragment import pl.szczodrzynski.edziennik.ui.modules.webpush.WebPushFragment
import pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoTouch import pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoTouch
@ -129,6 +130,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
const val TARGET_MESSAGES_DETAILS = 503 const val TARGET_MESSAGES_DETAILS = 503
const val TARGET_MESSAGES_COMPOSE = 504 const val TARGET_MESSAGES_COMPOSE = 504
const val TARGET_WEB_PUSH = 140 const val TARGET_WEB_PUSH = 140
const val TARGET_TEMPLATE = 1000
const val HOME_ID = DRAWER_ITEM_HOME const val HOME_ID = DRAWER_ITEM_HOME
@ -227,6 +229,13 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
list += NavTarget(TARGET_MESSAGES_COMPOSE, R.string.menu_message_compose, MessagesComposeFragment::class) list += NavTarget(TARGET_MESSAGES_COMPOSE, R.string.menu_message_compose, MessagesComposeFragment::class)
list += NavTarget(TARGET_WEB_PUSH, R.string.menu_web_push, WebPushFragment::class) list += NavTarget(TARGET_WEB_PUSH, R.string.menu_web_push, WebPushFragment::class)
list += NavTarget(DRAWER_ITEM_DEBUG, R.string.menu_debug, DebugFragment::class) list += NavTarget(DRAWER_ITEM_DEBUG, R.string.menu_debug, DebugFragment::class)
if (App.devMode) {
list += NavTarget(TARGET_TEMPLATE, R.string.menu_template, TemplateFragment::class)
.withIcon(CommunityMaterial.Icon2.cmd_test_tube_empty)
.isInDrawer(true)
.isBelowSeparator(true)
.isStatic(true)
}
list list
} }

View File

@ -1,28 +0,0 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-2-22.
*/
package pl.szczodrzynski.edziennik.ui.modules.base
import androidx.fragment.app.Fragment
abstract class PagerFragment : Fragment() {
private var isPageCreated = false
/**
* 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
override fun onResume() {
if (!isPageCreated) {
isPageCreated = onPageCreated()
}
super.onResume()
}
}

View File

@ -8,7 +8,8 @@ import androidx.fragment.app.Fragment
abstract class LazyFragment : Fragment() { abstract class LazyFragment : Fragment() {
private var isPageCreated = false private var isPageCreated = false
var swipeRefreshLayoutCallback: ((isEnabled: Boolean) -> Unit)? = null internal var position = -1
internal var swipeRefreshLayoutCallback: ((position: Int, isEnabled: Boolean) -> Unit)? = null
/** /**
* Called when the page is first shown, or if previous * Called when the page is first shown, or if previous
@ -20,6 +21,10 @@ abstract class LazyFragment : Fragment() {
*/ */
abstract fun onPageCreated(): Boolean abstract fun onPageCreated(): Boolean
fun enableSwipeToRefresh() = swipeRefreshLayoutCallback?.invoke(position, true)
fun disableSwipeToRefresh() = swipeRefreshLayoutCallback?.invoke(position, false)
fun setSwipeToRefresh(enabled: Boolean) = swipeRefreshLayoutCallback?.invoke(position, enabled)
internal fun createPage() { internal fun createPage() {
if (!isPageCreated && isAdded) { if (!isPageCreated && isAdded) {
isPageCreated = onPageCreated() isPageCreated = onPageCreated()

View File

@ -4,10 +4,25 @@
package pl.szczodrzynski.edziennik.ui.modules.base.lazypager package pl.szczodrzynski.edziennik.ui.modules.base.lazypager
import android.util.SparseBooleanArray
import androidx.core.util.set
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
abstract class LazyPagerAdapter(fragmentManager: FragmentManager) : FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { abstract class LazyPagerAdapter(fragmentManager: FragmentManager, val swipeRefreshLayout: SwipeRefreshLayout? = null) : FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
var swipeRefreshLayoutCallback: ((isEnabled: Boolean) -> Unit)? = null internal val enabledList = SparseBooleanArray()
abstract override fun getItem(position: Int): LazyFragment private val refreshLayoutCallback: (position: Int, isEnabled: Boolean) -> Unit = { position, isEnabled ->
swipeRefreshLayout?.isEnabled = isEnabled
if (position > -1)
enabledList[position] = isEnabled
}
final override fun getItem(position: Int): LazyFragment {
return getPage(position).also {
it.position = position
it.swipeRefreshLayoutCallback = refreshLayoutCallback
}
}
abstract fun getPage(position: Int): LazyFragment
abstract override fun getPageTitle(position: Int): CharSequence
} }

View File

@ -11,10 +11,15 @@ import androidx.viewpager.widget.ViewPager
class LazyViewPager @JvmOverloads constructor( class LazyViewPager @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null context: Context, attrs: AttributeSet? = null
) : ViewPager(context, attrs) { ) : ViewPager(context, attrs) {
var pageSelection = -1
init { init {
addOnPageChangeListener(object : OnPageChangeListener { addOnPageChangeListener(object : OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) { override fun onPageScrollStateChanged(state: Int) {
(adapter as? LazyPagerAdapter)?.let {
it.swipeRefreshLayout?.isEnabled = state == SCROLL_STATE_IDLE && it.enabledList[pageSelection, true]
}
} }
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
@ -22,6 +27,7 @@ class LazyViewPager @JvmOverloads constructor(
} }
override fun onPageSelected(position: Int) { override fun onPageSelected(position: Int) {
pageSelection = position
if (adapter is LazyPagerAdapter) { if (adapter is LazyPagerAdapter) {
val fragment = adapter?.instantiateItem(this@LazyViewPager, position) val fragment = adapter?.instantiateItem(this@LazyViewPager, position)
val lazyFragment = fragment as? LazyFragment val lazyFragment = fragment as? LazyFragment

View File

@ -67,10 +67,7 @@ class HomeworkFragment : Fragment() {
Toast.makeText(activity, R.string.main_menu_mark_as_read_success, Toast.LENGTH_SHORT).show() Toast.makeText(activity, R.string.main_menu_mark_as_read_success, Toast.LENGTH_SHORT).show()
})) }))
b.viewPager.adapter = MessagesFragment.Adapter(childFragmentManager).also { adapter -> b.viewPager.adapter = MessagesFragment.Adapter(childFragmentManager, b.refreshLayout).also { adapter ->
adapter.swipeRefreshLayoutCallback = { isEnabled ->
b.refreshLayout.isEnabled = isEnabled
}
adapter.addFragment(HomeworkListFragment().also { fragment -> adapter.addFragment(HomeworkListFragment().also { fragment ->
fragment.arguments = Bundle().also { args -> fragment.arguments = Bundle().also { args ->
@ -86,11 +83,8 @@ class HomeworkFragment : Fragment() {
} }
b.viewPager.currentItem = pageSelection b.viewPager.currentItem = pageSelection
b.viewPager.clearOnPageChangeListeners()
b.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { b.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) { override fun onPageScrollStateChanged(state: Int) {}
b.refreshLayout.isEnabled = state == ViewPager.SCROLL_STATE_IDLE
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {} override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
override fun onPageSelected(position: Int) { override fun onPageSelected(position: Int) {
pageSelection = position pageSelection = position

View File

@ -45,10 +45,10 @@ class HomeworkListFragment : LazyFragment() {
b.homeworkView.addOnScrollListener(object : RecyclerView.OnScrollListener() { b.homeworkView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
if (recyclerView.canScrollVertically(-1)) { if (recyclerView.canScrollVertically(-1)) {
swipeRefreshLayoutCallback?.invoke(false) setSwipeToRefresh(false)
} }
if (!recyclerView.canScrollVertically(-1) && newState == RecyclerView.SCROLL_STATE_IDLE) { if (!recyclerView.canScrollVertically(-1) && newState == RecyclerView.SCROLL_STATE_IDLE) {
swipeRefreshLayoutCallback?.invoke(true) setSwipeToRefresh(true)
} }
} }
}) })

View File

@ -6,6 +6,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import androidx.viewpager.widget.ViewPager import androidx.viewpager.widget.ViewPager
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
@ -54,11 +55,7 @@ class MessagesFragment : Fragment() {
return return
} }
b.viewPager.adapter = Adapter(childFragmentManager).also { adapter -> b.viewPager.adapter = Adapter(childFragmentManager, b.refreshLayout).also { adapter ->
adapter.swipeRefreshLayoutCallback = { isEnabled ->
b.refreshLayout.isEnabled = isEnabled
}
adapter.addFragment(MessagesListFragment().also { fragment -> adapter.addFragment(MessagesListFragment().also { fragment ->
fragment.arguments = Bundle().also { args -> fragment.arguments = Bundle().also { args ->
@ -75,13 +72,8 @@ class MessagesFragment : Fragment() {
} }
b.viewPager.currentItem = pageSelection b.viewPager.currentItem = pageSelection
b.viewPager.clearOnPageChangeListeners()
b.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { b.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) { override fun onPageScrollStateChanged(state: Int) {}
if (b.refreshLayout != null) {
b.refreshLayout.isEnabled = state == ViewPager.SCROLL_STATE_IDLE
}
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {} override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
override fun onPageSelected(position: Int) { override fun onPageSelected(position: Int) {
pageSelection = position pageSelection = position
@ -130,11 +122,11 @@ class MessagesFragment : Fragment() {
}*/ }*/
} }
internal class Adapter(manager: FragmentManager) : LazyPagerAdapter(manager) { internal class Adapter(manager: FragmentManager, swipeRefreshLayout: SwipeRefreshLayout) : LazyPagerAdapter(manager, swipeRefreshLayout) {
private val mFragmentList = mutableListOf<LazyFragment>() private val mFragmentList = mutableListOf<LazyFragment>()
private val mFragmentTitleList = mutableListOf<String>() private val mFragmentTitleList = mutableListOf<String>()
override fun getItem(position: Int): LazyFragment { override fun getPage(position: Int): LazyFragment {
return mFragmentList[position] return mFragmentList[position]
} }
@ -143,12 +135,11 @@ class MessagesFragment : Fragment() {
} }
fun addFragment(fragment: LazyFragment, title: String) { fun addFragment(fragment: LazyFragment, title: String) {
fragment.swipeRefreshLayoutCallback = this@Adapter.swipeRefreshLayoutCallback
mFragmentList.add(fragment) mFragmentList.add(fragment)
mFragmentTitleList.add(title) mFragmentTitleList.add(title)
} }
override fun getPageTitle(position: Int): CharSequence? { override fun getPageTitle(position: Int): CharSequence {
return mFragmentTitleList[position] return mFragmentTitleList[position]
} }
} }

View File

@ -171,12 +171,10 @@ public class MessagesListFragment extends LazyFragment {
@Override @Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
if (b.emailList.canScrollVertically(-1)) { if (b.emailList.canScrollVertically(-1)) {
if (getSwipeRefreshLayoutCallback() != null) setSwipeToRefresh(false);
getSwipeRefreshLayoutCallback().invoke(false);
} }
if (!b.emailList.canScrollVertically(-1) && newState == SCROLL_STATE_IDLE) { if (!b.emailList.canScrollVertically(-1) && newState == SCROLL_STATE_IDLE) {
if (getSwipeRefreshLayoutCallback() != null) setSwipeToRefresh(true);
getSwipeRefreshLayoutCallback().invoke(true);
} }
} }
}); });

View File

@ -1,24 +1,33 @@
/* /*
* Copyright (c) Kuba Szczodrzyński 2019-12-19. * Copyright (c) Kuba Szczodrzyński 2020-3-30.
*/ */
package pl.szczodrzynski.edziennik.ui package pl.szczodrzynski.edziennik.ui.modules.template
import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.databinding.TemplateListItemBinding import pl.szczodrzynski.edziennik.databinding.TemplateListItemBinding
import pl.szczodrzynski.edziennik.onClick import pl.szczodrzynski.edziennik.onClick
import kotlin.coroutines.CoroutineContext
class TemplateAdapter( class TemplateAdapter(
val context: Context, val activity: AppCompatActivity,
val onItemClick: ((item: TemplateItem) -> Unit)? = null, val onItemClick: ((item: TemplateItem) -> Unit)? = null,
val onItemButtonClick: ((item: TemplateItem) -> Unit)? = null val onItemButtonClick: ((item: TemplateItem) -> Unit)? = null
) : RecyclerView.Adapter<TemplateAdapter.ViewHolder>() { ) : RecyclerView.Adapter<TemplateAdapter.ViewHolder>(), CoroutineScope {
private val app by lazy { context.applicationContext as App } private val app = activity.applicationContext as App
// optional: place the manager here
private val job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
var items = listOf<TemplateItem>() var items = listOf<TemplateItem>()

View File

@ -1,8 +1,8 @@
/* /*
* Copyright (c) Kuba Szczodrzyński 2020-1-8. * Copyright (c) Kuba Szczodrzyński 2020-3-30.
*/ */
package pl.szczodrzynski.edziennik.ui.dialogs package pl.szczodrzynski.edziennik.ui.modules.template
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity

View File

@ -1,4 +1,8 @@
package pl.szczodrzynski.edziennik.ui.modules.base /*
* Copyright (c) Kuba Szczodrzyński 2020-3-30.
*/
package pl.szczodrzynski.edziennik.ui.modules.template
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
@ -10,7 +14,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.databinding.FragmentTemplateBinding import pl.szczodrzynski.edziennik.databinding.TemplateFragmentBinding
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
class TemplateFragment : Fragment(), CoroutineScope { class TemplateFragment : Fragment(), CoroutineScope {
@ -20,7 +24,7 @@ class TemplateFragment : Fragment(), CoroutineScope {
private lateinit var app: App private lateinit var app: App
private lateinit var activity: MainActivity private lateinit var activity: MainActivity
private lateinit var b: FragmentTemplateBinding private lateinit var b: TemplateFragmentBinding
private val job: Job = Job() private val job: Job = Job()
override val coroutineContext: CoroutineContext override val coroutineContext: CoroutineContext
@ -32,7 +36,7 @@ class TemplateFragment : Fragment(), CoroutineScope {
activity = (getActivity() as MainActivity?) ?: return null activity = (getActivity() as MainActivity?) ?: return null
context ?: return null context ?: return null
app = activity.application as App app = activity.application as App
b = FragmentTemplateBinding.inflate(inflater) b = TemplateFragmentBinding.inflate(inflater)
b.refreshLayout.setParent(activity.swipeRefreshLayout) b.refreshLayout.setParent(activity.swipeRefreshLayout)
return b.root return b.root
} }
@ -41,6 +45,15 @@ class TemplateFragment : Fragment(), CoroutineScope {
if (!isAdded) if (!isAdded)
return return
val pagerAdapter = TemplatePagerAdapter(
fragmentManager ?: return,
b.refreshLayout
)
b.viewPager.apply {
offscreenPageLimit = 1
adapter = pagerAdapter
currentItem = 4
b.tabLayout.setupWithViewPager(this)
}
} }
} }

View File

@ -0,0 +1,15 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-3-30.
*/
package pl.szczodrzynski.edziennik.ui.modules.template
import androidx.fragment.app.FragmentManager
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyPagerAdapter
class TemplatePagerAdapter(fragmentManager: FragmentManager, swipeRefreshLayout: SwipeRefreshLayout) : LazyPagerAdapter(fragmentManager, swipeRefreshLayout) {
override fun getPage(position: Int) = TemplatePagerFragment()
override fun getPageTitle(position: Int) = "Page $position"
override fun getCount() = 10
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-3-30.
*/
package pl.szczodrzynski.edziennik.ui.modules.template
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.databinding.TemplatePagerFragmentBinding
import pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyFragment
import kotlin.coroutines.CoroutineContext
class TemplatePagerFragment : LazyFragment(), CoroutineScope {
companion object {
private const val TAG = "TemplatePagerFragment"
}
private lateinit var app: App
private lateinit var activity: MainActivity
private lateinit var b: TemplatePagerFragmentBinding
private val job: Job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
// local/private variables go here
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
activity = (getActivity() as MainActivity?) ?: return null
context ?: return null
app = activity.application as App
b = TemplatePagerFragmentBinding.inflate(inflater)
return b.root
}
override fun onPageCreated(): Boolean {
b.text.text = "Fragment $position"
b.button.addOnCheckedChangeListener { button, isChecked ->
setSwipeToRefresh(isChecked)
}
return true
}
}

View File

@ -16,7 +16,7 @@ class TimetablePagerAdapter(
private val items: List<Date>, private val items: List<Date>,
private val startHour: Int, private val startHour: Int,
private val endHour: Int private val endHour: Int
) : LazyPagerAdapter(fragmentManager) { ) : LazyPagerAdapter(fragmentManager, null) {
companion object { companion object {
private const val TAG = "TimetablePagerAdapter" private const val TAG = "TimetablePagerAdapter"
} }
@ -25,9 +25,8 @@ class TimetablePagerAdapter(
private val weekStart by lazy { today.weekStart } private val weekStart by lazy { today.weekStart }
private val weekEnd by lazy { weekStart.clone().stepForward(0, 0, 6) } private val weekEnd by lazy { weekStart.clone().stepForward(0, 0, 6) }
override fun getItem(position: Int): LazyFragment { override fun getPage(position: Int): LazyFragment {
return TimetableDayFragment().apply { return TimetableDayFragment().apply {
swipeRefreshLayoutCallback = this@TimetablePagerAdapter.swipeRefreshLayoutCallback
arguments = Bundle().apply { arguments = Bundle().apply {
putInt("date", items[position].value) putInt("date", items[position].value)
putInt("startHour", startHour) putInt("startHour", startHour)
@ -40,7 +39,7 @@ class TimetablePagerAdapter(
return items.size return items.size
} }
override fun getPageTitle(position: Int): CharSequence? { override fun getPageTitle(position: Int): CharSequence {
val date = items[position] val date = items[position]
val pageTitle = StringBuilder(Week.getFullDayName(date.weekDay)) val pageTitle = StringBuilder(Week.getFullDayName(date.weekDay))
if (date > weekEnd || date < weekStart) { if (date > weekEnd || date < weekStart) {

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) Kuba Szczodrzyński 2020-3-30.
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator
android:id="@+id/refreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorSurface_6dp"
app:tabIndicatorColor="?colorPrimary"
app:tabMode="auto"
app:tabSelectedTextColor="?colorPrimary"
app:tabTextColor="?android:textColorPrimary" />
<pl.szczodrzynski.edziennik.ui.modules.base.lazypager.LazyViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</LinearLayout>
</pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator>
</layout>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) Kuba Szczodrzyński 2020-3-30.
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:text="Fragment 1" />
<com.google.android.material.button.MaterialButton
android:id="@+id/button"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:checkable="true"
android:text="Enable/disable Swipe to refresh"/>
</LinearLayout>
</layout>

View File

@ -1278,4 +1278,5 @@
<string name="registration_enable_dialog_title">Rejestracja na serwerze</string> <string name="registration_enable_dialog_title">Rejestracja na serwerze</string>
<string name="registration_enable_dialog_text">Rejestracja jest automatyczna, jeśli ta opcja jest włączona. Pozwala na tworzenie i odbieranie wydarzeń udostępnionych innym uczniom z Twojej klasy. Dzięki temu, można dodawać do dziennika pozycje nie zapisane przez nauczyciela.\n\nUpewnij się, że zapoznałeś się z warunkami <a href="http://szkolny.eu/privacy-policy">Polityki prywatności</a> i akceptujesz jej postanowienia.</string> <string name="registration_enable_dialog_text">Rejestracja jest automatyczna, jeśli ta opcja jest włączona. Pozwala na tworzenie i odbieranie wydarzeń udostępnionych innym uczniom z Twojej klasy. Dzięki temu, można dodawać do dziennika pozycje nie zapisane przez nauczyciela.\n\nUpewnij się, że zapoznałeś się z warunkami <a href="http://szkolny.eu/privacy-policy">Polityki prywatności</a> i akceptujesz jej postanowienia.</string>
<string name="menu_add_remove_cards">Dodaj lub usuń karty</string> <string name="menu_add_remove_cards">Dodaj lub usuń karty</string>
<string name="menu_template">Template</string>
</resources> </resources>