当前位置: 首页 > article >正文

UI页面布局分析(5)- 评分弹窗的实现

引言

评分功能时许多应用中不可或缺的一部分,无论是购物平台的商品评价,还是内容平台的用户反馈,评分弹窗都能帮助我们快速收集用户的意见。而评分弹窗中,点击星星点亮对应数量的交互,是实现良好用户体验的关键之一。该功能虽然十分简单,但偶尔也会让一些刚入门的开发一时间摸不到头脑。

在这篇博客中,我们将聚焦用评分UI的核心交互,展示如何通过点击星星实现实时点亮效果。我们将分别使用UIKit来实现这个功能,提供该技术栈下的完整代码示例。

页面布局分析

该页面可以大致分为上下两部分:下半部分为取消按钮,而上半部分为评分操作视图。评分操作视图中除了标题、图标和提示信息等辅助元素外,其核心部分是居中的五个星星评分视图。

评分视图的实现方式其实非常灵活,无论是星星、小红心,还是小灯泡,只需要选择适合的图标即可。我们可以使用UIButton或者是UIImageView来构建评分视图的每个小图标。以UIButton为例,可以通过设置按钮的normal状态为非高亮图片,而selected状态为高亮图片来实现状态切换。用户点击按钮时,更新其selected状态,并同步点亮该按钮之前的所有按钮,从而实现评分效果。

具体代码实现

根据前面的布局分析,我们将实现分为两个部分:整体页面的实现和评分核心组件的实现。

整体页面的实现

整体页面包括评分操作视图和取消按钮。评分操作视图包含标题、图标、提示信息,以及核心的评分星星视图。这部分代码将着重展示页面的基本结构和布局逻辑,确保 UI 清晰美观。

具体实现如下:

首先是上半部分的背景视图topBackgroundView,和取消按钮cancelButton:

class PHScoreView: UIView {
    
    /// 上半部分背景
    private let topBackgroundView = UIView()
    ...
    /// 取消按钮
    private let cancelButton = UIButton()


}
    private func setupView() {
        // 上半部分背景
        addSubview(topBackgroundView)
        topBackgroundView.backgroundColor = UIColor(red: 0.118, green: 0.118, blue: 0.18, alpha: 1)
        topBackgroundView.layer.masksToBounds = true
        topBackgroundView.layer.cornerRadius = 32.0
    ...
                // 取消按钮
        addSubview(cancelButton)
        cancelButton.setTitle("Cancel", for: .normal)
        cancelButton.setTitleColor(.white, for: .normal)
        cancelButton.backgroundColor = UIColor(red: 0.118, green: 0.118, blue: 0.18, alpha: 1)
        cancelButton.layer.masksToBounds = true
        cancelButton.layer.cornerRadius = 18.0
        cancelButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)


}
  private func setLayout() {
        // 上半部分背景
        topBackgroundView.snp.makeConstraints { (make) in
            make.leading.equalToSuperview().offset(30.0)
            make.trailing.equalToSuperview().offset(-30.0)
            make.top.equalToSuperview()
        }
        ....

        // 取消按钮
        cancelButton.snp.makeConstraints { (make) in
            make.top.equalTo(topBackgroundView.snp.bottom).offset(16.0)
            make.leading.equalTo(topBackgroundView.snp.leading)
            make.trailing.equalTo(topBackgroundView.snp.trailing)
            make.height.equalTo(48.0)
            make.bottom.equalToSuperview().offset(-45.0)
        }
    }
  1. topBackgroundView视图将会作为标题,图片以及评分星星视图的父视图,它的高度会有里面的子组件来决定,因此我们只设置了top和leading以及trailing约束。
  2. cancelButton取消按钮比较独立,位于视图的最低端,为了将整个视图的高度撑起,我们需要设置它的top约束以及bottom约束。

接下来是标题,图片星级和提示部分,所有视图将会放置在topBackgroundView上面:

    /// 标题
    private let titleLabel = UILabel()
    /// 标题图片
    private let titleImageView = UIImageView()
    /// 星星评分视图
    private let starView = PHStarView()
    /// 提示
    private let tipLabel = UILabel()
        // 标题
        topBackgroundView.addSubview(titleLabel)
        titleLabel.text = "Like this app?"
        titleLabel.textColor = .white
        titleLabel.font = UIFont.boldSystemFont(ofSize: 20)
        titleLabel.textAlignment = .center
        // 标题图片
        topBackgroundView.addSubview(titleImageView)
        titleImageView.image = UIImage(named: "logo")
        // 星星评分视图
        topBackgroundView.addSubview(starView)
        // 提示
        topBackgroundView.addSubview(tipLabel)
        tipLabel.text = "Tap a star to rate"
        tipLabel.font = UIFont.systemFont(ofSize: 14)
        tipLabel.textColor = UIColor(red: 0.737, green: 0.753, blue: 0.8, alpha: 1)
        tipLabel.textAlignment = .center
        // 标题
        titleLabel.snp.makeConstraints { (make) in
            make.top.equalToSuperview().offset(32.0)
            make.leading.trailing.equalToSuperview()
            make.height.equalTo(27.0)
        }
        // 标题图片
        titleImageView.snp.makeConstraints { (make) in
            make.top.equalTo(titleLabel.snp.bottom).offset(16.0)
            make.centerX.equalToSuperview()
            make.size.equalTo(CGSize(width: 206.0, height: 54.0))
        }
        // 星星评分视图
        starView.snp.makeConstraints { (make) in
            make.top.equalTo(titleImageView.snp.bottom).offset(16)
            make.centerX.equalToSuperview()
            make.height.equalTo(44.0)
        }
        // 提示
        tipLabel.snp.makeConstraints { (make) in
            make.top.equalTo(starView.snp.bottom).offset(16)
            make.leading.trailing.equalToSuperview()
            make.height.equalTo(20)
            make.bottom.equalToSuperview().offset(-32.0)
        }
  1. 这里面最需要注意的就是由于我们没有给父视图设置高度,因此需要确保各个子视图之间的约束连贯,确保可以将父视图内容撑起。
  2. 而startView我们当前只设置了高度,内容还没有实现嗷。

运行效果如下:

星级评价实现

接下来我们将重点放到PHStarView的实现上,我们采用UIStackView+UIButton的方式来实现。

具体布局如下:

class PHStarView:UIView {
    
    /// stackView
    private let stackView = UIStackView()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        addStackView()
        addSubViews()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func addStackView() {
        addSubview(stackView)
        stackView.axis = .horizontal
        stackView.spacing = 4.0
        stackView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
    }
    
    private func addSubViews() {
        for i in 0..<5 {
            let button = UIButton()
            button.setImage(UIImage(named: "star"), for: .normal)
            button.setImage(UIImage(named: "star_fill"), for: .selected)
            button.tag = i + 100
            button.addTarget(self, action: #selector(starClick), for: .touchUpInside)
            stackView.addArrangedSubview(button)
            button.snp.makeConstraints { make in
                make.height.width.equalTo(44.0)
            }
        }
    }
    
   ...
}

而关于点击评分的实现,我们只需要将点击事件之前的所有按钮设置为selected状态即可:

    @objc private func starClick(sender:UIButton) {
        let index = sender.tag - 100
        for i in 0..<5 {
            let button = stackView.viewWithTag(i + 100) as! UIButton
            button.isSelected = i <= index
        }
    }

运行效果如下:

结语

通过本篇文章,我们介绍了如何使用 UIKit 实现评分弹窗的页面布局和核心交互。我们从整体布局分析入手,逐步构建了一个简单而高效的评分视图,其中包括按钮的点击事件和星星状态的动态更新。

尽管本篇文章仅使用 UIKit 来展示实现过程,但相同的布局思路和交互逻辑也可以很容易地迁移到 SwiftUI 或其他框架中。评分弹窗的这种交互设计无论是在移动应用中,还是在其他平台的开发中,都能为用户提供直观、流畅的体验。

希望本文能够为你提供一些启发,帮助你在自己的项目中实现类似的功能。未来,我们也将继续探讨如何优化评分弹窗的交互效果,提升用户体验。

源码:https://download.csdn.net/download/weixin_39339407/90181770


http://www.kler.cn/a/458686.html

相关文章:

  • 微信小程序:定义页面标题,动态设置页面标题,json
  • C# OpenCV机器视觉:目标跟踪
  • 时间序列预测算法---LSTM
  • 《墨菲定律》
  • 深入浅出 Spring (二)| 依赖注入(DI)、自动装配
  • ArcGIS JSAPI 高级教程 - 通过RenderNode实现视频融合效果(不借助三方工具)
  • 【PCIe 总线及设备入门学习专栏 5.1 -- PCIe 引脚 PRSNT 与热插拔】
  • Edge Scdn是用来干什么的?
  • 用户界面的UML建模05
  • element-plus在Vue3中开发相关知识
  • AI文献阅读ChatDOC 、ChatPDF 哪个好?
  • 如何在Linux上配置SSH密钥以实现免密登录
  • PostgreSQL 初始化配置设置
  • Unity功能模块一对话系统(4)实现个性文本标签
  • 2024-12-29-sklearn学习(25)无监督学习-神经网络模型(无监督) 烟笼寒水月笼沙,夜泊秦淮近酒家。
  • Leetcode 3405. Count the Number of Arrays with K Matching Adjacent Elements
  • 【LangChain】Chapter1 - Models, Prompts and Output Parsers
  • 【开源免费】基于SpringBoot+Vue.JS网上摄影工作室系统(JAVA毕业设计)
  • PostgreSQL中FIRST_VALUE、LAST_VALUE、LAG 和 LEAD是窗口函数,允许返回在数据集的特定窗口(或分区)内访问行的相对位置
  • 软件测试之单元测试
  • 技术周总结 12.23~12.29 周日(C#异步线程及调试)
  • 网络畅通无阻:计算机网络知识点复习指南
  • Empire Lupin One靶机
  • AIGC多模态生成模型的演进:图像与视频生成算法的协同发展(附代码与详细教程)
  • .net core 的软件开发方法论
  • 【Go】:Sentinel 动态数据源配置指南