tft每日頭條

 > 生活

 > 七爪是什麼

七爪是什麼

生活 更新时间:2024-12-27 18:24:12

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

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

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

這可以通過一個按鈕來完成,但在某些情況下,更好的用戶體驗将是滑動刷新。 今天,我們将使用 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<RowItem> { val list = mutableListOf<RowItem>() 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 個項目的列表。

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

@Composable fun 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 ) } } } } } @Composable fun 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 — 完成滑動刷新手勢時調用的 Lambda
  • content: @Composable () -> Unit — 包含可組合滾動的内容

一些有趣的可選參數是:

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

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

它需要兩個參數:

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

一些可選參數是:

  • fade: Boolean — 箭頭在滾動時是否應該淡入/淡出,默認為 true
  • scale: Boolean — 指示器在滾動時是否應按比例放大/縮小,默認為 false
  • arrowEnabled: Boolean — 是否應在指标上繪制箭頭,默認為 true
  • backgroundColor: 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.asStateFlow() private val _isLoading = MutableStateFlow(true) val isLoading = _isLoading.asStateFlow() init { 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<RowItem> { val list = mutableListOf<RowItem>() 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.color
  • shape: Shape — 占位符的所需形狀。如果提供 null,占位符将使用 MaterialTheme.shapes 中設置的小形狀
  • highlight: PlaceholderHighlight — 可選的高亮動畫。有兩個預先創建的占位符動畫,淡入淡出和微光
  • placeholderFadeTransitionSpec: @Composable Transition.Segment<Boolean>.() -> FiniteAnimationSpec<Float> — 将占位符淡入/淡出屏幕時使用的轉換規範。為過渡定義的布爾參數可見
  • contentFadeTransitionSpec: @Composable Transition.Segment<Boolean>.() -> FiniteAnimationSpec<Float> — 将内容淡入/淡出屏幕時使用的轉換規範。為過渡定義的布爾參數可見

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

@Composable fun 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(), ) ) } } } } @Composable fun 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/小程序/網站源碼資源!

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved