• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.accompanist.sample.swiperefresh
18 
19 import android.os.Bundle
20 import androidx.activity.ComponentActivity
21 import androidx.activity.compose.setContent
22 import androidx.compose.foundation.Image
23 import androidx.compose.foundation.layout.Row
24 import androidx.compose.foundation.layout.Spacer
25 import androidx.compose.foundation.layout.WindowInsets
26 import androidx.compose.foundation.layout.WindowInsetsSides
27 import androidx.compose.foundation.layout.asPaddingValues
28 import androidx.compose.foundation.layout.fillMaxWidth
29 import androidx.compose.foundation.layout.only
30 import androidx.compose.foundation.layout.padding
31 import androidx.compose.foundation.layout.size
32 import androidx.compose.foundation.layout.systemBars
33 import androidx.compose.foundation.layout.width
34 import androidx.compose.foundation.layout.windowInsetsPadding
35 import androidx.compose.foundation.lazy.LazyColumn
36 import androidx.compose.foundation.lazy.items
37 import androidx.compose.foundation.shape.RoundedCornerShape
38 import androidx.compose.material.MaterialTheme
39 import androidx.compose.material.Text
40 import androidx.compose.runtime.Composable
41 import androidx.compose.runtime.LaunchedEffect
42 import androidx.compose.runtime.SideEffect
43 import androidx.compose.runtime.getValue
44 import androidx.compose.runtime.mutableStateOf
45 import androidx.compose.runtime.remember
46 import androidx.compose.runtime.setValue
47 import androidx.compose.ui.Alignment
48 import androidx.compose.ui.Modifier
49 import androidx.compose.ui.draw.clip
50 import androidx.compose.ui.graphics.Color
51 import androidx.compose.ui.res.stringResource
52 import androidx.compose.ui.unit.dp
53 import androidx.core.view.WindowCompat
54 import coil.annotation.ExperimentalCoilApi
55 import coil.compose.rememberImagePainter
56 import com.google.accompanist.insets.ui.Scaffold
57 import com.google.accompanist.insets.ui.TopAppBarContent
58 import com.google.accompanist.insets.ui.TopAppBarSurface
59 import com.google.accompanist.sample.AccompanistSampleTheme
60 import com.google.accompanist.sample.R
61 import com.google.accompanist.sample.randomSampleImageUrl
62 import com.google.accompanist.swiperefresh.SwipeRefresh
63 import com.google.accompanist.swiperefresh.SwipeRefreshIndicator
64 import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
65 import com.google.accompanist.systemuicontroller.rememberSystemUiController
66 import kotlinx.coroutines.delay
67 
68 class SwipeRefreshContentPaddingSample : ComponentActivity() {
69     override fun onCreate(savedInstanceState: Bundle?) {
70         super.onCreate(savedInstanceState)
71 
72         // Turn off the decor fitting system windows, which means we need to through handling
73         // insets
74         WindowCompat.setDecorFitsSystemWindows(window, false)
75 
76         setContent {
77             AccompanistSampleTheme {
78                 Sample()
79             }
80         }
81     }
82 }
83 
<lambda>null84 private val listItems = List(40) { randomSampleImageUrl(it) }
85 
86 @Suppress("DEPRECATION")
87 @Composable
Samplenull88 private fun Sample() {
89     val systemUiController = rememberSystemUiController()
90     val useDarkIcons = MaterialTheme.colors.isLight
91     SideEffect {
92         systemUiController.setSystemBarsColor(Color.Transparent, darkIcons = useDarkIcons)
93     }
94 
95     // Simulate a fake 2-second 'load'. Ideally this 'refreshing' value would
96     // come from a ViewModel or similar
97     var refreshing by remember { mutableStateOf(false) }
98     LaunchedEffect(refreshing) {
99         if (refreshing) {
100             delay(2000)
101             refreshing = false
102         }
103     }
104 
105     Scaffold(
106         topBar = {
107             TopAppBarSurface(
108                 backgroundColor = MaterialTheme.colors.surface.copy(alpha = 0.9f),
109                 modifier = Modifier.fillMaxWidth()
110             ) {
111                 TopAppBarContent(
112                     title = {
113                         Text(stringResource(R.string.swiperefresh_title_content_padding))
114                     },
115                     modifier = Modifier.windowInsetsPadding(
116                         WindowInsets.systemBars.only(
117                             WindowInsetsSides.Horizontal + WindowInsetsSides.Top
118                         )
119                     )
120                 )
121             }
122         },
123         contentPadding = WindowInsets.systemBars
124             .only(WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom)
125             .asPaddingValues()
126     ) { contentPadding ->
127         SwipeRefresh(
128             state = rememberSwipeRefreshState(refreshing),
129             onRefresh = { refreshing = true },
130             // Shift the indicator to match the list content padding
131             indicatorPadding = contentPadding,
132             // We want the indicator to draw within the padding
133             clipIndicatorToPadding = false,
134             // Tweak the indicator to scale up/down
135             indicator = { state, refreshTriggerDistance ->
136                 SwipeRefreshIndicator(
137                     state = state,
138                     refreshTriggerDistance = refreshTriggerDistance,
139                     scale = true
140                 )
141             }
142         ) {
143             LazyColumn(contentPadding = contentPadding) {
144                 items(items = listItems) { imageUrl ->
145                     ListItem(imageUrl, Modifier.fillMaxWidth())
146                 }
147             }
148         }
149     }
150 }
151 
152 @OptIn(ExperimentalCoilApi::class)
153 @Composable
ListItemnull154 fun ListItem(
155     imageUrl: String,
156     modifier: Modifier = Modifier
157 ) {
158     Row(modifier.padding(horizontal = 16.dp, vertical = 8.dp)) {
159         Image(
160             painter = rememberImagePainter(imageUrl),
161             contentDescription = null,
162             modifier = Modifier
163                 .size(64.dp)
164                 .clip(RoundedCornerShape(4.dp)),
165         )
166 
167         Spacer(Modifier.width(16.dp))
168 
169         Text(
170             text = "Text",
171             style = MaterialTheme.typography.subtitle2,
172             modifier = Modifier.weight(1f)
173                 .align(Alignment.CenterVertically)
174         )
175     }
176 }
177