动态页面顶部标签
This commit is contained in:
@@ -1,10 +1,15 @@
|
|||||||
package com.aiosman.ravenow.ui.composables
|
package com.aiosman.ravenow.ui.composables
|
||||||
|
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@@ -12,11 +17,14 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.aiosman.ravenow.LocalAppTheme
|
import com.aiosman.ravenow.LocalAppTheme
|
||||||
|
import com.aiosman.ravenow.R
|
||||||
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
||||||
|
import androidx.compose.ui.graphics.Brush
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
/**
|
/**
|
||||||
* 可复用的标签页组件
|
* 可复用的标签页组件
|
||||||
*/
|
*/
|
||||||
@@ -54,3 +62,43 @@ fun TabItem(
|
|||||||
fun TabSpacer() {
|
fun TabSpacer() {
|
||||||
Spacer(modifier = Modifier.width(8.dp))
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun UnderlineTabItem(
|
||||||
|
text: String,
|
||||||
|
isSelected: Boolean,
|
||||||
|
onClick: () -> Unit,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
val AppColors = LocalAppTheme.current
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = modifier
|
||||||
|
.noRippleClickable { onClick() },
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
fontWeight = FontWeight.ExtraBold,
|
||||||
|
color = if (isSelected) AppColors.text else AppColors.text.copy(alpha = 0.6f),
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp).padding(top = 13.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
// 选中状态下显示图标
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.size(24.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
if (isSelected) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.mipmap.underline),
|
||||||
|
contentDescription = "selected indicator",
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package com.aiosman.ravenow.ui.index.tabs.moment
|
|||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.horizontalScroll
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@@ -20,6 +21,7 @@ import androidx.compose.foundation.layout.systemBars
|
|||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.pager.HorizontalPager
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.ExperimentalMaterialApi
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
import androidx.compose.material.Icon
|
import androidx.compose.material.Icon
|
||||||
@@ -54,7 +56,7 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
import com.aiosman.ravenow.ui.composables.TabItem
|
import com.aiosman.ravenow.ui.composables.TabItem
|
||||||
import com.aiosman.ravenow.ui.composables.TabSpacer
|
import com.aiosman.ravenow.ui.composables.UnderlineTabItem
|
||||||
import com.aiosman.ravenow.ui.composables.rememberDebouncer
|
import com.aiosman.ravenow.ui.composables.rememberDebouncer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,8 +70,8 @@ fun MomentsList() {
|
|||||||
val navigationBarPaddings =
|
val navigationBarPaddings =
|
||||||
WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + 48.dp
|
WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + 48.dp
|
||||||
val statusBarPaddingValues = WindowInsets.systemBars.asPaddingValues()
|
val statusBarPaddingValues = WindowInsets.systemBars.asPaddingValues()
|
||||||
// 游客模式下不显示timeline,只显示2个tab:Dynamic、Hot // 游客模式下不显示timeline,只显示3个tab:Explore、Dynamic、Hot
|
// 现在有6个tab:推荐、短视频、新闻、探索、关注、热门
|
||||||
val tabCount = if (AppStore.isGuest) 2 else 3 // val tabCount = if (AppStore.isGuest) 3 else 4
|
val tabCount = 6
|
||||||
var pagerState = rememberPagerState { tabCount }
|
var pagerState = rememberPagerState { tabCount }
|
||||||
var scope = rememberCoroutineScope()
|
var scope = rememberCoroutineScope()
|
||||||
Column(
|
Column(
|
||||||
@@ -81,60 +83,127 @@ fun MomentsList() {
|
|||||||
),
|
),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
|
// 顶部区域:可滚动的标签页 + 搜索按钮
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.height(44.dp)
|
.height(44.dp)
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
// center the tabs
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
// 可滚动的标签页行
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.horizontalScroll(rememberScrollState()),
|
||||||
horizontalArrangement = Arrangement.Start,
|
horizontalArrangement = Arrangement.Start,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
//原探索//
|
val tabDebouncer = rememberDebouncer()
|
||||||
// Column(
|
|
||||||
// modifier = Modifier
|
// 推荐标签
|
||||||
// .noRippleClickable {
|
UnderlineTabItem(
|
||||||
// scope.launch {
|
text = stringResource(R.string.tab_recommend),
|
||||||
// pagerState.animateScrollToPage(0)
|
isSelected = pagerState.currentPage == 0,
|
||||||
// }
|
onClick = {
|
||||||
// }.padding(start = 16.dp),
|
tabDebouncer {
|
||||||
// verticalArrangement = Arrangement.Center,
|
scope.launch {
|
||||||
// horizontalAlignment = Alignment.CenterHorizontally
|
pagerState.animateScrollToPage(0)
|
||||||
//
|
}
|
||||||
// ) {
|
}
|
||||||
// Text(
|
}
|
||||||
// text = stringResource(R.string.index_worldwide),
|
|
||||||
// fontSize = if (pagerState.currentPage == 0)18.sp else 16.sp,
|
|
||||||
// color = if (pagerState.currentPage == 0) AppColors.text else AppColors.nonActiveText,
|
|
||||||
// fontWeight = FontWeight.W600)
|
|
||||||
// Spacer(modifier = Modifier.height(4.dp))
|
|
||||||
//
|
|
||||||
// Image(
|
|
||||||
// painter = painterResource(
|
|
||||||
// if (pagerState.currentPage == 0) R.mipmap.tab_indicator_selected
|
|
||||||
// else R.drawable.tab_indicator_unselected
|
|
||||||
// ),
|
|
||||||
// contentDescription = "tab indicator",
|
|
||||||
// modifier = Modifier
|
|
||||||
// .width(34.dp)
|
|
||||||
// .height(4.dp)
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// Spacer(modifier = Modifier.width(16.dp))
|
|
||||||
val lastClickTime = remember { mutableStateOf(0L) }
|
|
||||||
val clickDelay = 500L
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.moment),
|
|
||||||
fontSize = 20.sp,
|
|
||||||
fontWeight = FontWeight.W900,
|
|
||||||
color = AppColors.text,
|
|
||||||
modifier = Modifier
|
|
||||||
.align(Alignment.CenterVertically)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
|
||||||
|
|
||||||
|
// 短视频标签
|
||||||
|
UnderlineTabItem(
|
||||||
|
text = stringResource(R.string.tab_short_video),
|
||||||
|
isSelected = pagerState.currentPage == 1,
|
||||||
|
onClick = {
|
||||||
|
tabDebouncer {
|
||||||
|
scope.launch {
|
||||||
|
pagerState.animateScrollToPage(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// 动态标签
|
||||||
|
UnderlineTabItem(
|
||||||
|
text = stringResource(R.string.moment),
|
||||||
|
isSelected = pagerState.currentPage == 2,
|
||||||
|
onClick = {
|
||||||
|
tabDebouncer {
|
||||||
|
scope.launch {
|
||||||
|
pagerState.animateScrollToPage(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// 只有非游客用户才显示"关注"tab
|
||||||
|
if (!AppStore.isGuest) {
|
||||||
|
UnderlineTabItem(
|
||||||
|
text = stringResource(R.string.index_following),
|
||||||
|
isSelected = pagerState.currentPage == 3,
|
||||||
|
onClick = {
|
||||||
|
tabDebouncer {
|
||||||
|
scope.launch {
|
||||||
|
pagerState.animateScrollToPage(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// 热门标签
|
||||||
|
UnderlineTabItem(
|
||||||
|
text = stringResource(R.string.index_hot),
|
||||||
|
isSelected = pagerState.currentPage == 4,
|
||||||
|
onClick = {
|
||||||
|
tabDebouncer {
|
||||||
|
scope.launch {
|
||||||
|
pagerState.animateScrollToPage(4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// 热门标签 (游客模式)
|
||||||
|
UnderlineTabItem(
|
||||||
|
text = stringResource(R.string.index_hot),
|
||||||
|
isSelected = pagerState.currentPage == 4,
|
||||||
|
onClick = {
|
||||||
|
tabDebouncer {
|
||||||
|
scope.launch {
|
||||||
|
pagerState.animateScrollToPage(4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 新闻标签
|
||||||
|
UnderlineTabItem(
|
||||||
|
text = stringResource(R.string.tab_news),
|
||||||
|
isSelected = pagerState.currentPage == 5,
|
||||||
|
onClick = {
|
||||||
|
tabDebouncer {
|
||||||
|
scope.launch {
|
||||||
|
pagerState.animateScrollToPage(5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索按钮
|
||||||
|
val lastClickTime = remember { mutableStateOf(0L) }
|
||||||
|
val clickDelay = 500L
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(id = R.drawable.rider_pro_nav_search),
|
painter = painterResource(id = R.drawable.rider_pro_nav_search),
|
||||||
contentDescription = "search",
|
contentDescription = "search",
|
||||||
@@ -151,113 +220,38 @@ fun MomentsList() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(23.dp))
|
|
||||||
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.wrapContentHeight()
|
|
||||||
.padding(start = 16.dp, bottom = 16.dp),
|
|
||||||
horizontalArrangement = Arrangement.Start,
|
|
||||||
verticalAlignment = Alignment.Bottom
|
|
||||||
) {
|
|
||||||
val tabDebouncer = rememberDebouncer()
|
|
||||||
|
|
||||||
// 新探索标签
|
|
||||||
Box {
|
|
||||||
CustomTabItem(
|
|
||||||
text = stringResource(R.string.index_worldwide),
|
|
||||||
isSelected = pagerState.currentPage == 0,
|
|
||||||
onClick = {
|
|
||||||
tabDebouncer {
|
|
||||||
scope.launch {
|
|
||||||
pagerState.animateScrollToPage(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
TabSpacer()
|
|
||||||
|
|
||||||
// 只有非游客用户才显示"关注"tab
|
|
||||||
if (!AppStore.isGuest) {
|
|
||||||
Box {
|
|
||||||
CustomTabItem(
|
|
||||||
text = stringResource(R.string.index_following),
|
|
||||||
isSelected = pagerState.currentPage == 1,
|
|
||||||
onClick = {
|
|
||||||
tabDebouncer {
|
|
||||||
scope.launch {
|
|
||||||
pagerState.animateScrollToPage(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
TabSpacer()
|
|
||||||
|
|
||||||
// 热门标签
|
|
||||||
Box {
|
|
||||||
CustomTabItem(
|
|
||||||
text = stringResource(R.string.index_hot),
|
|
||||||
isSelected = pagerState.currentPage == 2,
|
|
||||||
onClick = {
|
|
||||||
tabDebouncer {
|
|
||||||
scope.launch {
|
|
||||||
pagerState.animateScrollToPage(2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 热门标签 (游客模式)
|
|
||||||
Box {
|
|
||||||
CustomTabItem(
|
|
||||||
text = stringResource(R.string.index_hot),
|
|
||||||
isSelected = pagerState.currentPage == 1,
|
|
||||||
onClick = {
|
|
||||||
tabDebouncer {
|
|
||||||
scope.launch {
|
|
||||||
pagerState.animateScrollToPage(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HorizontalPager(
|
HorizontalPager(
|
||||||
state = pagerState,
|
state = pagerState,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
) {
|
) {
|
||||||
if (AppStore.isGuest) {
|
|
||||||
// 游客模式:Dynamic(0), Hot(1)
|
|
||||||
when (it) {
|
when (it) {
|
||||||
0 -> {
|
0 -> {
|
||||||
Dynamic()
|
// 推荐页面
|
||||||
}
|
}
|
||||||
1 -> {
|
1 -> {
|
||||||
HotMomentsList()
|
// 短视频页面
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 正常用户:Dynamic(0), Timeline(1), Hot(2)
|
|
||||||
when (it) {
|
|
||||||
0 -> {
|
|
||||||
Dynamic()
|
|
||||||
}
|
|
||||||
1 -> {
|
|
||||||
TimelineMomentsList()
|
|
||||||
}
|
}
|
||||||
2 -> {
|
2 -> {
|
||||||
|
// 动态页面 - 暂时显示时间线内容
|
||||||
|
Dynamic()
|
||||||
|
}
|
||||||
|
3 -> {
|
||||||
|
// 关注页面 (仅非游客用户) 或 热门页面 (游客用户)
|
||||||
|
if (AppStore.isGuest) {
|
||||||
|
HotMomentsList()
|
||||||
|
} else {
|
||||||
|
TimelineMomentsList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4 -> {
|
||||||
|
// 热门页面 (仅非游客用户)
|
||||||
HotMomentsList()
|
HotMomentsList()
|
||||||
}
|
}
|
||||||
|
5 -> {
|
||||||
|
// 新闻页面
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
app/src/main/res/mipmap-hdpi/underline.png
Normal file
BIN
app/src/main/res/mipmap-hdpi/underline.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 617 B |
BIN
app/src/main/res/mipmap-mdpi/underline.png
Normal file
BIN
app/src/main/res/mipmap-mdpi/underline.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 483 B |
BIN
app/src/main/res/mipmap-xhdpi/underline.png
Normal file
BIN
app/src/main/res/mipmap-xhdpi/underline.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 646 B |
BIN
app/src/main/res/mipmap-xxhdpi/underline.png
Normal file
BIN
app/src/main/res/mipmap-xxhdpi/underline.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/underline.png
Normal file
BIN
app/src/main/res/mipmap-xxxhdpi/underline.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
@@ -222,5 +222,10 @@
|
|||||||
|
|
||||||
<!-- Login page -->
|
<!-- Login page -->
|
||||||
<string name="join_party_carnival">パーティーに参加して、一緒に盛り上がろう</string>
|
<string name="join_party_carnival">パーティーに参加して、一緒に盛り上がろう</string>
|
||||||
|
|
||||||
|
<!-- Tab labels -->
|
||||||
|
<string name="tab_recommend">おすすめ</string>
|
||||||
|
<string name="tab_short_video">ショート動画</string>
|
||||||
|
<string name="tab_news">ニュース</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
|
|||||||
@@ -226,4 +226,9 @@
|
|||||||
<!-- Login page -->
|
<!-- Login page -->
|
||||||
<string name="join_party_carnival">加入派派,一起狂欢</string>
|
<string name="join_party_carnival">加入派派,一起狂欢</string>
|
||||||
|
|
||||||
|
<!-- Tab labels -->
|
||||||
|
<string name="tab_recommend">推荐</string>
|
||||||
|
<string name="tab_short_video">短视频</string>
|
||||||
|
<string name="tab_news">新闻</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -221,4 +221,9 @@
|
|||||||
|
|
||||||
<!-- Login page -->
|
<!-- Login page -->
|
||||||
<string name="join_party_carnival">Join the party, let\'s celebrate together</string>
|
<string name="join_party_carnival">Join the party, let\'s celebrate together</string>
|
||||||
|
|
||||||
|
<!-- Tab labels -->
|
||||||
|
<string name="tab_recommend">Recommend</string>
|
||||||
|
<string name="tab_short_video">Short Video</string>
|
||||||
|
<string name="tab_news">News</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user