问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

直播应用中用户小卡的UI设计与实现

创作时间:
作者:
@小白创作中心

直播应用中用户小卡的UI设计与实现

引用
CSDN
1.
https://blog.csdn.net/weixin_39339407/article/details/144781873

在直播应用中,用户小卡是展示用户信息和促进互动的重要UI组件。一个设计合理、布局高效的用户小卡不仅能提升用户体验,还能增强用户的参与感和归属感。本文将从结构组成入手,深入分析用户小卡的布局设计,并结合具体代码,探讨如何使用UITableView来实现这一复杂布局。


用户卡片结构组成

从上图可以看到,直播间内的用户小卡包含了非常丰富的元素。我们可以从上到下将其划分为几个部分进行详细说明:

  1. 顶部的操作按钮:位于小卡左上角的操作按钮,例如举报或设置按钮。
  2. 用户基本信息:显示用户头像、昵称和用户ID,同时根据用户佩戴的徽章显示对应的徽章信息。
  3. 用户等级信息:用户基本信息下方展示用户的等级和经验值,直观地反映用户的活跃程度。
  4. 用户年龄、性别、地址与签名信息:这一部分包含用户的年龄、性别、地址以及个性签名等文本信息。
  5. 用户的关注和粉丝数量:进一步往下,显示用户的关注数量、粉丝数量,以及贡献榜前三名粉丝的信息。
  6. 用户的送礼和收礼信息:在粉丝数量下面,用于展示用户累计收到的金币和送出的礼物总数。
  7. 用户的等级、性别及标签徽章:这一部分集中展示用户的等级标签、性别标签、VIP、SVIP、贵族场控等状态标识,以及用户佩戴的所有徽章信息。
  8. 用户达成的成就信息:显示用户已达成的成就数量,并展示部分成就图标作为代表。
  9. 底部操作按钮:小卡底部的操作栏,包含关注、取消关注、@用户以及发送私信等交互按钮。
  10. 小卡背景:除了上述展示信息与操作按钮外,小卡还配有全屏或半屏高度的背景,用于区分不同用户的卡片类型或身份。

如此多的UI元素,如果直接将所有内容堆叠到一个小卡视图中,代码会变得冗杂且难以维护。更重要的是,如果需要在此基础上增减元素,操作起来将更加复杂。因此,设计一个合理且高效的UI布局方案显得尤为重要。

用户小卡布局分析

根据上面我们对小卡结构组成的分析,我们可以将小卡的布局这样进行分割。

关于用户小卡的全屏背景和半屏背景,我们可以直接使用图片按照设计的比例添加到小卡视图的最低层,不需要考虑任何其它元素,只要覆盖在上面的元素本身没有背景颜色,那么我们总可以看见小卡的背景。

背景之外的部分,我们可以注意到,顶部的操作栏和底部的工具栏是固定在小卡视图的这两个位置,并不会滑动,而其它的所有内容则是在这两个之间,并且随着内容高度高于小卡的高度还会上下滑动,因此我们将小卡的布局首先分为三个部分:

  1. 顶部工具栏:放置设置,举报等按钮,位于小卡视图的最顶端。
  2. 中间信息视图:用来展示所有的用户信息,内容高度不定,可以上下滑动。
  3. 底部工具栏:用户放置关注,@和私信等操作按钮。

关于顶部和底部的工具栏,非常简单都是单一的视图。但就中间的信息视图而言,我们还需要选择一个合适的方式来实现它的布局。由于视图可以上下滑动,所以首先会想到UIScrollView,但是如果使用了UIScrollView我们就需要自己来维护上面子组件的显示和隐藏。所以更理想的选择我们可以使用继承自UIScrollView的UITableView,不同的用户信息视图,就创建不同类型的cell,然后使用数据来控制对应信息cell的显示与隐藏。

用户小卡布局代码实现

接下来我们开始结合具体的代码来分析小卡布局的实现。从小卡背景介绍起,再到顶部工具栏视图,底部工具栏视图,以及中间显示所有用户信息的UITableView。

小卡背景

小卡背景有两种形式,一种是半屏的小卡,只占据用户小卡的顶部的一小部分,另外还有一个全屏的小卡,会占据整个小卡背景。由于它们都不受任何其它子组件的影响,因此我们可以直接着手它们的布局。

/// 卡片背景图片
private let bgImageView = UIImageView()
/// 顶部卡片背景图片
private let topBgImageView = UIImageView()

private func setupView() {
    self.backgroundColor = .wm_hex("#1E1E2E")
    self.layer.masksToBounds = true
    self.layer.cornerRadius = 20.0
    // 卡片背景图片
    self.addSubview(bgImageView)
    bgImageView.contentMode = .scaleAspectFill
    // 顶部卡片背景图片
    self.addSubview(topBgImageView)
    topBgImageView.contentMode = .scaleAspectFill
    ...
}

private func setLayout() {
    // 卡片背景图片
    bgImageView.snp.makeConstraints { make in
        make.edges.equalToSuperview()
    }
    // 顶部卡片背景图片
    topBgImageView.snp.makeConstraints { make in
        make.top.leading.trailing.equalToSuperview()
    }
    ...
}
  1. 全屏的背景我们使用bgImageView来显示,它直接充满整个小卡视图。
  2. 而半屏的背景我们使用topBgImageView来显示,它的leading,trailing和top与小卡对其,而高度则会根据内容自动填充。

顶部和底部工具栏

顶部和底部的工具栏,实际上和小卡背景异曲同工,它们都有固定的位置并且不受其它子组件的影响,并且高度固定。

/// 顶部操作视图
private let topToolView = MWUserCardTopToolView()
/// 底部操作视图
private let bottomToolView = MWUserCardBottomToolView()

private func setupView() {
    ...
    // 顶部操作视图
    self.addSubview(topToolView)
    // 列表
    ...
    // 底部操作视图
    self.addSubview(bottomToolView)
    bottomToolView.backgroundColor = .wm_hex("353543")
}

private func setLayout() {
    ...
    // 顶部操作视图
    topToolView.snp.makeConstraints { make in
        make.leading.trailing.top.equalToSuperview()
        make.height.equalTo(48.0)
    }
    // 列表
    ...
    // 底部操作视图
    bottomToolView.snp.makeConstraints { make in
        make.leading.trailing.bottom.equalToSuperview()
        make.height.equalTo(44.0)
    }
}
  1. 顶部工具栏固定在顶部,高度为48。
  2. 底部工具栏固定在小卡底部,高度固定为44。

用户信息列表

用户信息我们采用UITableView来展示,从用户的头像昵称等信息到用户的成就信息,每一个信息视图对应一个类型的cell。为此我们定义了一个数据模型MWBaseRowItem,里面包含了cell的类以及cell标识,具体实现如下:

import UIKit
open class MWBaseRowItem: NSObject {
    /// cell标识
    public var cellIdentifier: String = ""
    /// cell类名
    public var cellClass: AnyClass?
    
    public init(cellIdentifier: String, cellClass: AnyClass? = nil) {
        self.cellIdentifier = cellIdentifier
        self.cellClass = cellClass
    }
}

而每一条用户信息都会创建一个对应的MWBaseRowItem实例,放在dataList里,来维护用户信息的一个列表。列表会根据dataList的内容来显示对应类型cell。

dataList构建实现如下:

/// 构建用户卡片列表数据
class func buildUserCardListData() -> [MWBaseRowItem] {
    var list = [MWBaseRowItem]()
    //1.头部数据
    let headerItem = MWBaseRowItem(cellIdentifier: NSStringFromClass(MWUserCardHeadInfoCell.self), cellClass: MWUserCardHeadInfoCell.self)
    list.append(headerItem)
    //2.等级
    let levelItem = MWBaseRowItem(cellIdentifier: NSStringFromClass(MWUserCardLevelCell.self), cellClass: MWUserCardLevelCell.self)
    list.append(levelItem)
    //3. 介绍
    let introItem = MWBaseRowItem(cellIdentifier: NSStringFromClass(MWUserCardIntroCell.self), cellClass: MWUserCardIntroCell.self)
    list.append(introItem)
    //4.粉丝/关注数量
    let fansItem = MWBaseRowItem(cellIdentifier: NSStringFromClass(MWUserCardFansCell.self), cellClass: MWUserCardFansCell.self)
    list.append(fansItem)
    //5.金币钻石
    let coinItem = MWBaseRowItem(cellIdentifier: NSStringFromClass(MWUserCardCoinCell.self), cellClass: MWUserCardCoinCell.self)
    list.append(coinItem)
    //6.标签徽章
    let badgeItem = MWBaseRowItem(cellIdentifier: NSStringFromClass(MWUserCardBadgeCell.self), cellClass: MWUserCardBadgeCell.self)
    list.append(badgeItem)
    //7.成就
    let achievementItem = MWBaseRowItem(cellIdentifier: NSStringFromClass(MWUserCardAchievementCell.self), cellClass: MWUserCardAchievementCell.self)
    list.append(achievementItem)
    
    return list
}

数据里面包含了从用户头像到,用户成就列表的所有数据,以及对应的cell。

下面我们只需要创建一个UITableView并,使用dataList里面的数据来渲染列表即可,实现如下:

/// 列表
private let tableView = UITableView(frame: .zero, style: .plain)

private func setupView() {
    ...
    // 列表
    self.addSubview(tableView)
    tableView.backgroundColor = .clear
    tableView.separatorStyle = .none
    tableView.delegate = self
    tableView.dataSource = self
    for item in dataList {
        tableView.register(item.cellClass, forCellReuseIdentifier: item.cellIdentifier)
    }
    ...
}

private func setLayout() {
    ...
    // 列表
    tableView.snp.makeConstraints { make in
        make.leading.trailing.equalToSuperview()
        make.bottom.equalToSuperview().offset(-44.0)
        make.top.equalTo(topToolView.snp.bottom)
    }
    ...
}
  1. 我们根据dataList的数据来注册所有需要用的cell。
  2. 布局时,将顶部工具栏和底部工具栏的位置空出。

接下来在UITableView的代理方法中,我们需要根据dataList中的元素标识,直接返回cell即可:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return dataList.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let item = dataList[indexPath.row]
    let cell = tableView.dequeueReusableCell(withIdentifier: item.cellIdentifier, for: indexPath)
    cell.selectionStyle = .none
    return cell
}

我们不需要关心cell的类型,也不需要关心该显示那些视图,所有的事情都在数据处理阶段完成了。就算新增新的信息视图,我们只需要创建一个新的cell添加到dataList数组中。如果需要因此某个信息视图,只将对应的数据从dataList数组中移除。

结语

直播间内用户小卡的设计不仅仅是简单的信息展示,更是用户交互体验的关键一环。在这篇博客中,我们从小卡的结构组成入手,分析了其布局设计的重点,并通过代码展示了如何高效实现这样一个复杂的UI组件。

合理的布局不仅能够提升代码的可维护性,还能为后续功能扩展打下坚实的基础。通过模块化的设计思路,我们可以轻松地增减元素,而不影响整体的布局和性能。希望本篇内容能为你在直播应用开发中处理类似的复杂UI需求提供帮助与灵感。

UI设计的每一处细节都值得被精雕细琢,而用户小卡的布局也不例外。如果你在阅读后有任何问题或更好的设计思路,欢迎留言与我交流,共同探索更优雅的实现方式!

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号