Jetpack Compose仿某Chat主界面效果

图片

这将是一个完整的UI设计教程,是我再次长时间思考后得出的结果。我们将了解如何规划UI设计,并尽可能接近我们的线框图来实现它。作为参考,我将采用WhatsApp真实应用的界面,但请注意,颜色编码可能会有少许不同,因为颜色是从颜色拾取器中提取的。

图片

拆分细节

首先,让我们看看在每个屏幕中如何将设计细分为较小的组件。

Home Screen

图片

在这里,我们可以看到整体屏幕上有一列可能的项目作为头部区域,选项卡区域,选项卡内容区域和一个浮动操作按钮。因此,我们可以说我们的主屏幕组件应该如下所示:

Box {
  Column {
    AppBar()
    TabBar()
    HorizontalPager()
  }
  
  FloatingActionButton()
}

AppBar

AppBar简单地包含一个带有4个小部件的行。但是,我们在行中没有任何现有的间距排列,这使得我们的期望对齐方式实现:即文本位于左侧,其余三个项目位于右侧。

图片

因此,我们可以采取spacer,给它一个权重,如下所示:

Row(
        modifier = Modifier,
        verticalAlignment = Alignment.CenterVertically
    ) {
        Text(
            text = stringResource(id = R.string.whatsapp_title),
            style = TextStyle(
                fontSize = 22.sp,
                fontWeight = FontWeight.SemiBold,
                color = if (isSystemInDarkTheme()) PrimaryGray_A101 else White
            )
        )

        Spacer(modifier = Modifier.weight(1f))
        ActionIcon(id = R.drawable.ic_camera_outline)
        Spacer(modifier = Modifier.width(20.dp))
        ActionIcon(id = R.drawable.ic_search_outline)
        Spacer(modifier = Modifier.width(16.dp))
        ActionIcon(id = R.drawable.ic_overflow_filled)

    }

TabBar

现在我们来看看如何使用TabRow创建我们的选项卡布局。在WhatsApp中,状态选项卡和通话选项卡带有附加的指示器。

图片

因此,这意味着除了聊天选项卡之外,我们还需要为每个选项卡添加一个包含文本和指示器的行。我们可以这样做:

TabRow(
        modifier = Modifier.fillMaxWidth(),
        selectedTabIndex = selectedPage,
        indicator = { tabPositions ->
        }
    ) {
        homeTabs.forEachIndexed { index, tabData ->
            Tab(
                selected = index == selectedPage,
            ) {

                tabData.unreadCount?.let { count ->
                    Row(     // if we find that either status count or call count is greater than 0 then we show this row
                        verticalAlignment = Alignment.CenterVertically,
                        horizontalArrangement = Arrangement.Center
                    ) {
                        Text(
                            text = tabData.tab.value,
                            style = TextStyle(
                                fontSize = 16.sp,
                            )
                        )
                        if (tabData.tab.sameAs(Tabs.MESSAGE_STATUS)) {
                            AnimatedVisibility(visible = statusIndicatorVisible) {
                                TabIndicator()
                            }
                        } else {
                            AnimatedVisibility(visible = callIndicatorVisible) {
                                UnreadCountIndicator(count)
                            }
                        }
                    }
                }?: Text(       // else we show simple text
                    text = tabData.tab.value,
                    style = TextStyle(
                        fontSize = 16.sp,
                    )
                )
            }
        }
    }

HorizontalPager

现在是设置每个选项卡的内容的时候了。为了设置一个水平滑动页面(HorizontalPager),我们可以这样做:

HorizontalPager(
      pageCount = 3,
      beyondBoundsPageCount = 3,
      state = viewPagerState,
      modifier = Modifier
            .background(MaterialTheme.colors.background)
            .fillMaxSize(),
) { page ->
       when (page) {
            0 -> ChatListScreen()
            1 -> StatusListScreen()
            2 -> CallsListScreen()
        }
}

FloatingActionButton

现在我们看到浮动操作按钮始终在整个屏幕上方,因此我们将列包装在一个盒子内,并将FAB放在底部右下角。

图片

好的!现在我们创建了我们的屏幕,该轮到创建单独的屏幕了。

ChatList Screen

聊天列表屏幕看起来相当简单。我们有一个带有项目的列表,可以使用懒加载列来实现,如下所示:

LazyColumn(
        modifier = Modifier.padding(horizontal = 16.dp),
        horizontalAlignment = Alignment.Start,
    ) {
        item {
            Spacer(modifier = Modifier.height(4.dp))
        }
        items(
            items = chatListItems,
            key = { chatData ->
                chatData.chatId
            }
        ) { chatData ->
            ChatListItem(chatData)
        }
        item {
            Spacer(modifier = Modifier.height(75.dp))
        }
    }

这里看到的空间是为了保持设计中的边距。ChatListItem再次是一个子组件,其中包含用户图像、姓名和带有时间戳的最后一条消息。

ChatData是用于聊天列表的数据类,您可以在代码库中找到它。

https://github.com/aqua30/WhatsAppDesign-Compose/blob/master/app/src/main/java/com/aqua30/whatsapp/chatscreen/design/data/ChatDataSource.kt

图片

这里,值得注意的是在列表上向用户展示的最后一条消息。它可以是发送的或接收的消息,可以是文本、视频或音频,如果是发送的消息,则可以是已发送、待发送或已读取状态。

为了维护所有这些状态,我们将它们的标志包装在ChatDataSource中,并在组件中进行条件判断。

完成!这就是我们创建Home Screen和ChatList Screen的过程。

GitHub代码库中还包含Status和Calls标签的屏幕,它们如下所示:

图片

light theme主题样式如下

图片

GitHub

https://github.com/aqua30/WhatsAppDesign-Compose

 转自:使用Android Jetpack Compose仿某Chat主界面效果

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值