mirror of
https://github.com/BetterAndroid/FlexiUI.git
synced 2025-09-07 19:14:12 +08:00
feat: update demo
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Flexi UI - A flexible and useful UI component library.
|
||||
* Copyright (C) 2019-2024 HighCapable
|
||||
* https://github.com/BetterAndroid/FlexiUI
|
||||
*
|
||||
* Apache License Version 2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is created by fankes on 2024/1/13.
|
||||
*/
|
||||
package com.highcapable.flexiui.demo.bean
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.Stable
|
||||
|
||||
@Immutable
|
||||
data class SimpleListBean(
|
||||
val index: Int,
|
||||
val title: String,
|
||||
val subtitle: String
|
||||
) {
|
||||
|
||||
companion object {
|
||||
|
||||
@Stable
|
||||
fun create(index: Int) = SimpleListBean(
|
||||
index = index,
|
||||
title = "Item $index",
|
||||
subtitle = "This is a simple data of index $index"
|
||||
)
|
||||
}
|
||||
}
|
@@ -24,23 +24,46 @@
|
||||
package com.highcapable.flexiui.demo.screen
|
||||
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.highcapable.betterandroid.compose.multiplatform.backpress.BackHandler
|
||||
import com.highcapable.flexiui.component.Button
|
||||
import com.highcapable.flexiui.component.DropdownMenu
|
||||
import com.highcapable.flexiui.component.DropdownMenuItem
|
||||
import com.highcapable.flexiui.component.HorizontalItemBox
|
||||
import com.highcapable.flexiui.component.Icon
|
||||
import com.highcapable.flexiui.component.Scaffold
|
||||
import com.highcapable.flexiui.component.SecondaryAppBar
|
||||
import com.highcapable.flexiui.component.Tab
|
||||
import com.highcapable.flexiui.component.TabRow
|
||||
import com.highcapable.flexiui.component.Text
|
||||
import com.highcapable.flexiui.component.window.FlexiDialog
|
||||
import com.highcapable.flexiui.demo.Delete
|
||||
import com.highcapable.flexiui.demo.DeleteForever
|
||||
import com.highcapable.flexiui.demo.ListAdd
|
||||
import com.highcapable.flexiui.demo.PrimarySpacer
|
||||
import com.highcapable.flexiui.demo.bean.SimpleListBean
|
||||
import com.highcapable.flexiui.demo.rememberRouter
|
||||
import com.highcapable.flexiui.resources.FlexiIcons
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -49,54 +72,154 @@ import kotlinx.coroutines.launch
|
||||
fun LazyListScreen() {
|
||||
val router = rememberRouter()
|
||||
val pageCount = 2
|
||||
val state = rememberPagerState(pageCount = { pageCount })
|
||||
val pagerState = rememberPagerState(pageCount = { pageCount })
|
||||
val lazyListState = rememberLazyListState()
|
||||
val lazyGridState = rememberLazyGridState()
|
||||
val scope = rememberCoroutineScope()
|
||||
val testListData = remember {
|
||||
mutableStateListOf<SimpleListBean>().apply {
|
||||
for (i in 1..5) add(SimpleListBean.create(i))
|
||||
}
|
||||
}
|
||||
Scaffold(
|
||||
appBar = {
|
||||
var showRemoveAllDialog by remember { mutableStateOf(false) }
|
||||
FlexiDialog(
|
||||
visible = showRemoveAllDialog,
|
||||
onDismissRequest = { showRemoveAllDialog = false },
|
||||
title = { Text("Remove All") },
|
||||
content = { Text("Are you sure you want to remove all data?") },
|
||||
confirmButton = {
|
||||
Button(
|
||||
onClick = {
|
||||
showRemoveAllDialog = false
|
||||
testListData.clear()
|
||||
}
|
||||
) { Text("OK") }
|
||||
},
|
||||
cancelButton = {
|
||||
Button(
|
||||
onClick = { showRemoveAllDialog = false }
|
||||
) { Text("Cancel") }
|
||||
}
|
||||
)
|
||||
SecondaryAppBar(
|
||||
title = { Text("Lazy List Demo") },
|
||||
subtitle = { Text("0 items of list data", singleLine = true) },
|
||||
subtitle = { Text("${testListData.size} items of list data", singleLine = true) },
|
||||
navigationIcon = {
|
||||
NavigationIconButton(onClick = { router.goHome() })
|
||||
},
|
||||
actions = {
|
||||
ActionIconButton(onClick = { /* TODO */ }) {
|
||||
Icon(FlexiIcons.ListAdd)
|
||||
ActionIconButton(
|
||||
onClick = {
|
||||
val lastIndex = if (testListData.isNotEmpty())
|
||||
testListData[testListData.lastIndex].index + 1
|
||||
else 1
|
||||
testListData.add(SimpleListBean.create(lastIndex))
|
||||
scope.launch {
|
||||
lazyListState.animateScrollToItem(testListData.lastIndex)
|
||||
lazyGridState.animateScrollToItem(testListData.lastIndex)
|
||||
}
|
||||
ActionIconButton(onClick = { /* TODO */ }) {
|
||||
Icon(FlexiIcons.DeleteForever)
|
||||
}
|
||||
) { Icon(FlexiIcons.ListAdd) }
|
||||
ActionIconButton(
|
||||
onClick = { showRemoveAllDialog = testListData.isNotEmpty() }
|
||||
) { Icon(FlexiIcons.DeleteForever) }
|
||||
}
|
||||
)
|
||||
BackHandler { router.goHome() }
|
||||
},
|
||||
tab = {
|
||||
TabRow(
|
||||
selectedTabIndex = state.currentPage,
|
||||
selectedTabIndex = pagerState.currentPage,
|
||||
indicator = {
|
||||
TabIndicator(modifier = Modifier.pagerTabIndicatorOffset(state))
|
||||
TabIndicator(modifier = Modifier.pagerTabIndicatorOffset(pagerState))
|
||||
}
|
||||
) {
|
||||
Tab(
|
||||
selected = state.currentPage == 0,
|
||||
onClick = { scope.launch { state.animateScrollToPage(0) } }
|
||||
selected = pagerState.currentPage == 0,
|
||||
onClick = { scope.launch { pagerState.animateScrollToPage(0) } }
|
||||
) { Text("Linear List") }
|
||||
Tab(
|
||||
selected = state.currentPage == 1,
|
||||
onClick = { scope.launch { state.animateScrollToPage(1) } }
|
||||
selected = pagerState.currentPage == 1,
|
||||
onClick = { scope.launch { pagerState.animateScrollToPage(1) } }
|
||||
) { Text("Grid List") }
|
||||
}
|
||||
}
|
||||
) {
|
||||
) { innerPadding ->
|
||||
HorizontalPager(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
state = state,
|
||||
state = pagerState,
|
||||
beyondBoundsPageCount = pageCount
|
||||
) { index ->
|
||||
// TODO: To be implemented.
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
) { Text("Page ${index + 1}. To be implemented.") }
|
||||
@Composable
|
||||
fun LazyItem(modifier: Modifier, index: Int) {
|
||||
Box(modifier = modifier) {
|
||||
val hapticFeedback = LocalHapticFeedback.current
|
||||
var showDropdownMenu by remember { mutableStateOf(false) }
|
||||
HorizontalItemBox(
|
||||
onLongClick = {
|
||||
showDropdownMenu = true
|
||||
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
},
|
||||
title = { Text(testListData[index].title) },
|
||||
subtitle = { Text(testListData[index].subtitle) },
|
||||
showArrowIcon = false
|
||||
)
|
||||
DropdownMenu(
|
||||
expanded = showDropdownMenu,
|
||||
onDismissRequest = { showDropdownMenu = false }
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
onClick = { testListData.removeAt(index) }
|
||||
) {
|
||||
Icon(FlexiIcons.Delete)
|
||||
PrimarySpacer()
|
||||
Text("Remove this data")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (testListData.isNotEmpty()) when (index) {
|
||||
0 -> LazyColumn(
|
||||
modifier = Modifier.fillMaxSize().padding(innerPadding),
|
||||
state = lazyListState,
|
||||
verticalArrangement = ListSpacing
|
||||
) {
|
||||
items(
|
||||
count = testListData.size,
|
||||
key = { testListData[it].index }
|
||||
) { index ->
|
||||
LazyItem(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
index = index
|
||||
)
|
||||
}
|
||||
}
|
||||
1 -> LazyVerticalGrid(
|
||||
modifier = Modifier.fillMaxSize().padding(innerPadding),
|
||||
state = lazyGridState,
|
||||
columns = GridCells.Adaptive(GridMaxWidth),
|
||||
verticalArrangement = ListSpacing,
|
||||
horizontalArrangement = ListSpacing
|
||||
) {
|
||||
items(
|
||||
count = testListData.size,
|
||||
key = { testListData[it].index }
|
||||
) { index ->
|
||||
LazyItem(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
index = index
|
||||
)
|
||||
}
|
||||
}
|
||||
} else Box(
|
||||
modifier = Modifier.fillMaxSize().padding(innerPadding),
|
||||
contentAlignment = Alignment.Center
|
||||
) { Text("No data to show") }
|
||||
}
|
||||
BackHandler { router.goHome() }
|
||||
}
|
||||
}
|
||||
|
||||
private val ListSpacing = Arrangement.spacedBy(10.dp)
|
||||
private val GridMaxWidth = 100.dp
|
@@ -31,6 +31,7 @@ import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
@@ -78,7 +79,7 @@ import kotlinx.coroutines.launch
|
||||
@Composable
|
||||
fun MainScreen() {
|
||||
val pageCount = 2
|
||||
val state = rememberPagerState(pageCount = { pageCount })
|
||||
val pagerState = rememberPagerState(pageCount = { pageCount })
|
||||
val scope = rememberCoroutineScope()
|
||||
val uriHandler = LocalUriHandler.current
|
||||
Scaffold(
|
||||
@@ -117,36 +118,37 @@ fun MainScreen() {
|
||||
arrangement = Arrangement.SpaceAround
|
||||
) {
|
||||
NavigationBarItem(
|
||||
selected = state.currentPage == 0,
|
||||
onClick = { scope.launch { state.animateScrollToPage(page = 0) } },
|
||||
selected = pagerState.currentPage == 0,
|
||||
onClick = { scope.launch { pagerState.animateScrollToPage(page = 0) } },
|
||||
icon = { Icon(FlexiIcons.Home, style = IconDefaults.style(size = 24.dp)) },
|
||||
text = { Text("Home") }
|
||||
)
|
||||
NavigationBarItem(
|
||||
selected = state.currentPage == 1,
|
||||
onClick = { scope.launch { state.animateScrollToPage(page = 1) } },
|
||||
selected = pagerState.currentPage == 1,
|
||||
onClick = { scope.launch { pagerState.animateScrollToPage(page = 1) } },
|
||||
icon = { Icon(FlexiIcons.Component, style = IconDefaults.style(size = 24.dp)) },
|
||||
text = { Text("Component") }
|
||||
)
|
||||
}
|
||||
}
|
||||
) {
|
||||
) { innerPadding ->
|
||||
HorizontalPager(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
state = state,
|
||||
state = pagerState,
|
||||
) { index ->
|
||||
val modifier = Modifier.padding(innerPadding)
|
||||
when (index) {
|
||||
0 -> MainHomePage()
|
||||
1 -> MainComponentPage()
|
||||
0 -> MainHomePage(modifier)
|
||||
1 -> MainComponentPage(modifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MainHomePage() {
|
||||
fun MainHomePage(modifier: Modifier) {
|
||||
val scrollState = rememberScrollState()
|
||||
Column(modifier = Modifier.fillMaxSize().verticalScroll(scrollState)) {
|
||||
Column(modifier = modifier.fillMaxSize().verticalScroll(scrollState)) {
|
||||
AreaBox(modifier = Modifier.fillMaxWidth()) {
|
||||
Text("Flexi UI is a flexible and useful UI component library.")
|
||||
}
|
||||
@@ -213,15 +215,14 @@ fun MainHomePage() {
|
||||
title = { Text("Lazy List Demo") },
|
||||
subtitle = { Text("Open a lazy list page") }
|
||||
)
|
||||
PrimarySpacer()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MainComponentPage() {
|
||||
fun MainComponentPage(modifier: Modifier) {
|
||||
// TODO: To be implemented.
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
modifier = modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
) { Text("To be implemented.") }
|
||||
}
|
@@ -21,7 +21,9 @@
|
||||
*/
|
||||
package com.highcapable.flexiui.demo.screen
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.em
|
||||
@@ -46,7 +48,12 @@ fun SecondaryScreen() {
|
||||
NavigationIconButton(onClick = { router.goHome() })
|
||||
}
|
||||
)
|
||||
BackHandler { router.goHome() }
|
||||
}
|
||||
) { innerPadding ->
|
||||
Box(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
.padding(innerPadding)
|
||||
) {
|
||||
AreaColumn(modifier = Modifier.fillMaxWidth()) {
|
||||
Text(
|
||||
@@ -62,6 +69,6 @@ fun SecondaryScreen() {
|
||||
onClick = { router.goHome() }
|
||||
) { Text("Take Me Home") }
|
||||
}
|
||||
BackHandler { router.goHome() }
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user