@@ -12,13 +12,15 @@ import android.view.ViewGroup
12
12
import androidx.appcompat.app.AppCompatActivity
13
13
import androidx.fragment.app.Fragment
14
14
import androidx.viewbinding.ViewBinding
15
+ import com.google.gson.JsonObject
15
16
import com.mikepenz.iconics.typeface.IIcon
16
17
import kotlinx.coroutines.CoroutineScope
17
18
import kotlinx.coroutines.Dispatchers
18
19
import kotlinx.coroutines.Job
19
20
import org.greenrobot.eventbus.EventBus
20
21
import pl.szczodrzynski.edziennik.App
21
22
import pl.szczodrzynski.edziennik.MainActivity
23
+ import pl.szczodrzynski.edziennik.data.enums.FeatureType
22
24
import pl.szczodrzynski.edziennik.data.enums.MetadataType
23
25
import pl.szczodrzynski.edziennik.ext.registerSafe
24
26
import pl.szczodrzynski.edziennik.ext.startCoroutineTimer
@@ -38,31 +40,37 @@ abstract class BaseFragment<B : ViewBinding, A : AppCompatActivity>(
38
40
39
41
private var isViewReady: Boolean = false
40
42
private var inState: Bundle ? = null
43
+ private var appBarAnimator: AppBarColorAnimator ? = null
41
44
42
45
/* *
43
- * Enables or disables the activity's SwipeRefreshLayout.
44
- * Use only if [getRefreshScrollingView] is not used.
45
- *
46
- * The [PagerFragment] manages its [canRefresh] state
47
- * based on the value of the currently selected page.
46
+ * Whether the view is currently being scrolled
47
+ * or is left scrolled away from the top.
48
48
*/
49
- internal var canRefresh = false
50
- set(value) {
49
+ internal var isScrolled = false
50
+ set(value) { // cannot be private - PagerFragment onPageScrollStateChanged
51
51
field = value
52
- (activity as ? MainActivity )?.swipeRefreshLayout?.isEnabled =
53
- ! canRefreshDisabled && value
52
+ dispatchCanRefresh()
53
+ appBarAnimator?.dispatchLiftOnScroll()
54
54
}
55
55
56
56
/* *
57
- * Forcefully disables the activity's SwipeRefreshLayout
58
- * if [getRefreshScrollingView] is used.
57
+ * Forcefully disables the activity's SwipeRefreshLayout.
58
+ *
59
+ * The [PagerFragment] manages its [canRefreshDisabled] state
60
+ * based on the value of the currently selected page.
59
61
*/
60
62
internal var canRefreshDisabled = false
61
63
set(value) {
62
64
field = value
63
- canRefresh = canRefresh
65
+ dispatchCanRefresh()
64
66
}
65
67
68
+ /* *
69
+ * A list of views (usually app bars) that should have their
70
+ * background color elevated when the fragment is scrolled.
71
+ */
72
+ internal var appBars = mutableSetOf<View >()
73
+
66
74
private var job = Job ()
67
75
final override val coroutineContext: CoroutineContext
68
76
get() = job + Dispatchers .Main
@@ -83,6 +91,7 @@ abstract class BaseFragment<B : ViewBinding, A : AppCompatActivity>(
83
91
? : return null
84
92
isViewReady = false // reinitialize the view in onResume()
85
93
inState = savedInstanceState // save the instance state for onResume()
94
+ appBarAnimator = AppBarColorAnimator (activity, appBars)
86
95
return b.root
87
96
}
88
97
@@ -92,9 +101,17 @@ abstract class BaseFragment<B : ViewBinding, A : AppCompatActivity>(
92
101
if (! isAdded || isViewReady)
93
102
return
94
103
isViewReady = true
95
- setupCanRefresh()
104
+ // setup the activity (bottom sheet, FAB, etc.)
105
+ // run before setupScrollListener {} to populate appBars
96
106
(activity as ? MainActivity )?.let (::setupMainActivity)
97
107
(activity as ? LoginActivity )?.let (::setupLoginActivity)
108
+ // listen to scroll state changes
109
+ var first = true
110
+ setupScrollListener {
111
+ if (isScrolled != it || first)
112
+ isScrolled = it
113
+ first = false
114
+ }
98
115
// let the UI transition for a moment
99
116
startCoroutineTimer(100L ) {
100
117
if (! isAdded)
@@ -141,9 +158,10 @@ abstract class BaseFragment<B : ViewBinding, A : AppCompatActivity>(
141
158
142
159
/* *
143
160
* Called to retrieve the scrolling view contained in the fragment.
144
- * The scrolling view is configured to act nicely with the SwipeRefreshLayout.
161
+ * The scrolling view is configured to work nicely with the app bars
162
+ * and the SwipeRefreshLayout.
145
163
*/
146
- open fun getRefreshScrollingView (): View ? = null
164
+ open fun getScrollingView (): View ? = null
147
165
148
166
/* *
149
167
* Called to retrieve the FAB label resource and the icon.
@@ -157,6 +175,22 @@ abstract class BaseFragment<B : ViewBinding, A : AppCompatActivity>(
157
175
*/
158
176
open fun getMarkAsReadType (): MetadataType ? = null
159
177
178
+ /* *
179
+ * Called to retrieve the [FeatureType] this fragment is associated with.
180
+ * May also return arguments for the sync task.
181
+ *
182
+ * If not provided, swipe-to-refresh is disabled and the manual sync dialog
183
+ * selects all features by default.
184
+ *
185
+ * If [FeatureType] is null, all features are synced (and selected by the
186
+ * manual sync dialog).
187
+ *
188
+ * It is important to return the desired [FeatureType] from the first
189
+ * call of this method, which runs before [onViewReady]. Otherwise,
190
+ * swipe-to-refresh will not be enabled unless the view is scrolled.
191
+ */
192
+ open fun getSyncParams (): Pair <FeatureType ?, JsonObject ?>? = null
193
+
160
194
/* *
161
195
* Called to retrieve any extra bottom sheet items that should be displayed.
162
196
*/
0 commit comments