新四季網

七爪是什麼(七爪源碼JetpackCompose)

2023-10-07 04:11:27 2

關於如何在加載項目時實現滑動刷新功能以及佔位符的簡短指南

今天,許多應用程式都有需要在某個時候刷新的數據。 您可以在一段時間後刷新數據或使用套接字來始終擁有最新的數據,但是如果您想要允許用戶開始刷新數據的功能怎麼辦?

這可以通過一個按鈕來完成,但在某些情況下,更好的用戶體驗將是滑動刷新。 今天,我們將使用 Accompanist 庫來實現它。

滑動刷新

首先,讓我們添加一個依賴項:

implementation "com.google.accompanist:accompanist-swiperefresh:0.25.1"

注意:檢查是否有此依賴項的更新版本。

接下來是創建一個簡單的ViewModel,它將保存我們的數據和刷新邏輯。 在這裡,項目將包含隨機圖像和數字。 這是它的樣子:

class MainViewModel : ViewModel { private val _isRefreshing = MutableStateFlow(false) val isRefreshing = _isRefreshing.asStateFlow private val _currentTime = MutableStateFlow(Instant.now) val currentTime = _currentTime.asStateFlow private val _items = MutableStateFlow(generateItems) val items = _items.asStateFlow fun refresh = viewModelScope.launch { _isRefreshing.update { true } // Simulate API call delay(2000) _currentTime.value = Instant.now _items.value = generateItems _isRefreshing.update { false } } private fun generateItems: List { val list = mutableListOf for (i in 1 until 20) { list.add( RowItem( rowImage = randomImage, number = Random.nextInt(1, 1000) ) ) } return list } private fun randomImage( seed: Int = (0..100000).random, width: Int = 300, height: Int = width, ): String { return "https://picsum.photos/seed/$seed/$width/$height" }}data class RowItem( val rowImage: String = "", val number: Int = -1)

isRefreshing 是一個布爾值,我們將在 swipeRefreshState 中使用它,我們將在後面解釋。 items 只是包含隨機圖像和數字的 20 個項目的列表。

現在,讓我們創建我們的屏幕:

@Composablefun MainScreen( viewModel: MainViewModel = viewModel) { val isRefreshing = viewModel.isRefreshing.collectAsState.value val currentTime = viewModel.currentTime.collectAsState.value val items = viewModel.items.collectAsState.value val swipeRefreshState = rememberSwipeRefreshState(isRefreshing = isRefreshing) SwipeRefresh( state = swipeRefreshState, onRefresh = viewModel::refresh, modifier = Modifier .fillMaxSize .padding( vertical = 32.dp, horizontal = 16.dp ) ) { Column { Text( text = "Welcome to Swipe-to-Refresh!", style = MaterialTheme.typography.h5, modifier = Modifier.fillMaxWidth, textAlign = TextAlign.Center ) Spacer(modifier = Modifier.height(32.dp)) Text( text = currentTime.toString, modifier = Modifier.fillMaxWidth, textAlign = TextAlign.End ) Spacer(modifier = Modifier.height(8.dp)) LazyColumn { items(items) { Item( rowItem = it ) } } } }}@Composablefun Item( rowItem: RowItem) { Card( modifier = Modifier .fillMaxWidth .padding(vertical = 8.dp), elevation = 4.dp ) { Row( modifier = Modifier .fillMaxWidth .padding(16.dp), verticalAlignment = Alignment.CenterVertically, ) { Image( painter = rememberAsyncImagePainter(rowItem.rowImage), contentDescription = rowItem.number.toString, modifier = Modifier.size(64.dp) ) Spacer(modifier = Modifier.width(16.dp)) Text(text = "Number: ${rowItem.number}") } }}

我們正在收集我們的狀態並使用 isRefreshing 的值創建 swipeRefreshState。我們將這個狀態傳遞給 SwipeRefresh,但如果需要,我們也可以訪問它的屬性 isRefreshing 和 isSwipeInProgress。在 SwipeRefresh 中,我們有一個標題、當前時間和項目列表。每行項目只顯示一個圖像和數字。

SwipeRefresh 具有三個強制參數:

state: SwipeRefreshState — 可以提升以控制和觀察 SwipeRefresh 更改的狀態對象onRefresh: -> Unit — 完成滑動刷新手勢時調用的 Lambdacontent: @Composable -> Unit — 包含可組合滾動的內容

一些有趣的可選參數是:

swipeEnabled: Boolean - 布局是否應該對滑動手勢做出反應refreshTriggerDistance: Dp — 觸發刷新的最小滑動距離indicatorAlignment: Alignment — 指標的對齊方式。默認為 Alignment.TopCenterindicatorPadding: PaddingValues — 指標的內容填充,如果需要可以插入指標indicator:@Composable (state: SwipeRefreshState, refreshTrigger: Dp) — 表示當前狀態的指標。默認情況下,這將使用 SwipeRefreshIndicator

對於指標參數,您可以創建自己的可組合項,但該庫為我們提供了 SwipeRefreshIndicator,這是我們可以使用的非常好的可組合項。

它需要兩個參數:

state: SwipeRefreshState — 傳遞到 SwipeRefresh 指示器塊的 SwipeRefreshStaterefreshTriggerDistance: Dp — 觸發刷新的最小滑動距離

一些可選參數是:

fade: Boolean — 箭頭在滾動時是否應該淡入/淡出,默認為 truescale: Boolean — 指示器在滾動時是否應按比例放大/縮小,默認為 falsearrowEnabled: Boolean — 是否應在指標上繪製箭頭,默認為 truebackgroundColor: Color — 指示器背景表面的顏色

還有更多參數,但不需要全部遍歷。如果您想了解更多信息,請務必在官方文檔中查看。

這就是 SwipeRefresh 的全部內容,現在讓我們實現佔位符,這是來自 Accompanist 的另一個不錯的庫。

佔位符

通常,項目的加載由某種加載微調器顯示。另一種顯示項目正在加載的方法是使用佔位符。

Accompanist 創建了一個庫,為我們提供了用於顯示佔位符的修飾符。實際上有兩個佔位符庫。一個是基礎,另一個是材料。建議我們使用 Material,但可以隨意使用您需要的任何東西。沒有太大區別,API 大多是等價的。在本博客中,我們使用的是 Material。所以,讓我們用這個命令導入它:

implementation "com.google.accompanist:accompanist-placeholder-material:0.25.1"

注意:檢查是否有此依賴項的更新版本。

在繼續 MainScreen 之前,讓我們快速編輯 MainViewModel。 添加 init 和 isLoading StateFlow。 此外,使用 20 個默認 RowItem 初始化項目。

private val _items = MutableStateFlow(List(size = 20) { RowItem })val items = _items.asStateFlowprivate val _isLoading = MutableStateFlow(true)val isLoading = _isLoading.asStateFlowinit { viewModelScope.launch { delay(2000) _items.value = generateItems _isLoading.value = false }}

我們的 ViewModel 現在看起來像這樣:

class MainViewModel : ViewModel { private val _isRefreshing = MutableStateFlow(false) val isRefreshing = _isRefreshing.asStateFlow private val _currentTime = MutableStateFlow(Instant.now) val currentTime = _currentTime.asStateFlow private val _items = MutableStateFlow(List(size = 20) { RowItem }) val items = _items.asStateFlow private val _isLoading = MutableStateFlow(true) val isLoading = _isLoading.asStateFlow init { viewModelScope.launch { delay(2000) _items.value = generateItems _isLoading.value = false } } fun refresh = viewModelScope.launch { _isRefreshing.update { true } // Simulate API call delay(2000) _currentTime.value = Instant.now _items.value = generateItems _isRefreshing.update { false } } private fun generateItems: List { val list = mutableListOf for (i in 1 until 20) { list.add( RowItem( rowImage = randomSampleImageUrl, number = Random.nextInt(1, 1000) ) ) } return list } private fun randomSampleImageUrl( seed: Int = (0..100000).random, width: Int = 300, height: Int = width, ): String { return "https://picsum.photos/seed/$seed/$width/$height" }}data class RowItem( val rowImage: String = "", val number: Int = -1)

接下來是在我們的屏幕中收集 isLoading,然後將其用作我們的佔位符。 我們正在向 Item 可組合項添加一個新參數 childModifier:Modifier。

Item( rowItem = it, childModifier = Modifier.placeholder( visible = isLoading, highlight = PlaceholderHighlight.fade, ))

如您所見,該庫為佔位符提供了一個修飾符。必需的參數是可見的:布爾值,它確定是否應顯示佔位符或內容。如果 visible 為真,那麼將有一個佔位符來填充應用它的可組合項的大小,而不是內容。

可選參數有:

color: Color — 用於繪製佔位符 UI 的顏色。如果提供了 Color.Unspecified,則佔位符將使用 PlaceholderDefaults.colorshape: Shape — 佔位符的所需形狀。如果提供 null,佔位符將使用 MaterialTheme.shapes 中設置的小形狀highlight: PlaceholderHighlight — 可選的高亮動畫。有兩個預先創建的佔位符動畫,淡入淡出和微光placeholderFadeTransitionSpec: @Composable Transition.Segment. -> FiniteAnimationSpec — 將佔位符淡入/淡出屏幕時使用的轉換規範。為過渡定義的布爾參數可見contentFadeTransitionSpec: @Composable Transition.Segment. -> FiniteAnimationSpec — 將內容淡入/淡出屏幕時使用的轉換規範。為過渡定義的布爾參數可見

我們的 MainScreen 現在看起來像這樣:

@Composablefun MainScreen( viewModel: MainViewModel = viewModel) { val isRefreshing = viewModel.isRefreshing.collectAsState.value val isLoading = viewModel.isLoading.collectAsState.value val currentTime = viewModel.currentTime.collectAsState.value val items = viewModel.items.collectAsState.value val swipeRefreshState = rememberSwipeRefreshState(isRefreshing = isRefreshing) SwipeRefresh( state = swipeRefreshState, onRefresh = viewModel::refresh, modifier = Modifier .fillMaxSize .padding( vertical = 32.dp, horizontal = 16.dp ) ) { LazyColumn { item { Text( text = "Welcome to Swipe-to-Refresh!", style = MaterialTheme.typography.h5, modifier = Modifier.fillMaxWidth, textAlign = TextAlign.Center ) Spacer(modifier = Modifier.height(32.dp)) Text( text = currentTime.toString, modifier = Modifier.fillMaxWidth, textAlign = TextAlign.End ) Spacer(modifier = Modifier.height(8.dp)) } items(items) { Item( rowItem = it, childModifier = Modifier.placeholder( visible = isLoading, highlight = PlaceholderHighlight.fade, ) ) } } }}@Composablefun Item( rowItem: RowItem, childModifier: Modifier = Modifier,) { Card( modifier = Modifier .fillMaxWidth .padding(vertical = 8.dp), elevation = 4.dp ) { Row( modifier = Modifier .fillMaxWidth .padding(16.dp), verticalAlignment = Alignment.CenterVertically, ) { Image( painter = rememberAsyncImagePainter(rowItem.rowImage), contentDescription = rowItem.number.toString, modifier = childModifier.size(64.dp) ) Spacer(modifier = Modifier.width(16.dp)) Text( text = "Number: ${rowItem.number}", modifier = childModifier.fillMaxWidth ) } }}

就這樣。 我希望你喜歡它。

關注七爪網,獲取更多APP/小程序/網站源碼資源!

,
同类文章
葬禮的夢想

葬禮的夢想

夢見葬禮,我得到了這個夢想,五個要素的五個要素,水火只好,主要名字在外面,職業生涯良好,一切都應該對待他人治療誠意,由於小,吉利的冬天夢想,秋天的夢是不吉利的
找到手機是什麼意思?

找到手機是什麼意思?

找到手機是什麼意思?五次選舉的五個要素是兩名士兵的跡象。與他溝通很好。這是非常財富,它擅長運作,職業是仙人的標誌。單身男人有這個夢想,主要生活可以有人幫忙
我不怎麼想?

我不怎麼想?

我做了什麼意味著看到米飯烹飪?我得到了這個夢想,五線的主要土壤,但是Tu Ke水是錢的跡象,職業生涯更加真誠。他真誠地誠實。這是豐富的,這是夏瑞的巨星
夢想你的意思是什麼?

夢想你的意思是什麼?

你是什​​麼意思夢想的夢想?夢想,主要木材的五個要素,水的跡象,主營業務,主營業務,案子應該抓住魅力,不能疏忽,春天夢想的吉利夢想夏天的夢想不幸。詢問學者夢想
拯救夢想

拯救夢想

拯救夢想什麼意思?你夢想著拯救人嗎?拯救人們的夢想有一個現實,也有夢想的主觀想像力,請參閱週宮官方網站拯救人民夢想的詳細解釋。夢想著敵人被拯救出來
2022愛方向和生日是在[質量個性]中

2022愛方向和生日是在[質量個性]中

[救生員]有人說,在出生88天之前,胎兒已經知道哪天的出生,如何有優質的個性,將走在什麼樣的愛情之旅,將與生活生活有什么生活。今天
夢想切割剪裁

夢想切割剪裁

夢想切割剪裁什麼意思?你夢想切你的手是好的嗎?夢想切割手工切割手有一個真正的影響和反應,也有夢想的主觀想像力。請參閱官方網站夢想的細節,以削減手
夢想著親人死了

夢想著親人死了

夢想著親人死了什麼意思?你夢想夢想你的親人死嗎?夢想有一個現實的影響和反應,還有夢想的主觀想像力,請參閱夢想世界夢想死亡的親屬的詳細解釋
夢想搶劫

夢想搶劫

夢想搶劫什麼意思?你夢想搶劫嗎?夢想著搶劫有一個現實的影響和反應,也有夢想的主觀想像力,請參閱週恭吉夢官方網站的詳細解釋。夢想搶劫
夢想缺乏缺乏紊亂

夢想缺乏缺乏紊亂

夢想缺乏缺乏紊亂什麼意思?你夢想缺乏異常藥物嗎?夢想缺乏現實世界的影響和現實,還有夢想的主觀想像,請看官方網站的夢想組織缺乏異常藥物。我覺得有些東西缺失了