Skip to content

demo和说明

Yin Yu edited this page Dec 10, 2020 · 1 revision

1. 第一个 Demo

我们先看看要完成的效果:

效果

布局及元素构成很简单,那么接下来我们看如何通过 ArgoKit 来完成.

在开始布局之前我们可以回忆一下: UIStackView 这个应该很熟悉,接下来的布局行为可以由 UIStackView 来联想就好理解了.

1.1 布局思路

如果要把要做的效果图通过 UIStackView 来实现,我们大致应该这样做:

  1. 先定义一个垂直排列的 StackView
  2. 在垂直排列的 StackView 中定义三个水平排列的 StackView

这样这个例子中的大致布局就完成了,如图:

同样在三个水平的 StackView 中我们分别命名为: Stack1,Stack2,Stack3

1.1.1 Stack1: 水平方向

元素构成是

1.1.2 Stack2:水平方向

同理参考 1.1.1

1.1.3 Stack3:水平方向

同理参考 1.1.1

布局的思路有了,我们看如何使用 ArgoKit 来描述出 View.

在开始之前我们需要了解:VStackHStack 我们可以把他暂时理解为:

VStack = (垂直方向的 UIStackView) HStack = (水平方向的 UIStackView)

但是她们又比 UIStackView 更强大一些, 我们称它们为弹性盒子.

关于弹性盒子 这个教程能快速让你掌握。

接下来我们正式开始

1.2 弹性盒子

我们把布局的思路用代码实现。

第一步:定义垂直的 VStack

代码是这样的:

    var body: View {
        VStack() {
        /// 内容
        }.padding(edge: .all, value: 15)
    }

padding(edge: .all, value: 15) 是定义 VStack 距离上下左右 都是 15

第二步:完成三个水平的 HStack

    var body: View {
        VStack() {
            HStack {
                
            }.padding(edge: .bottom, value: 15)
            HStack {
                
            }
            HStack {
                
            }.padding(edge: .top, value: 15)
        }.padding(edge: .all, value: 15)
    }

第三步:完成第一个 HStack 内部结构

    var body: View {
        VStack() {
            HStack {
                Text("<")
                    .padding(edge: .right, value: 5)
                    .alignSelf(.center)
                Image("turtlerock")
                    .circle()
                    .width(35)
                    .height(35)
                VStack {
                    HStack {
                        Text("MOMO 科技")
                            .font(style: .bold)
                            .padding(edge: .right, value: 5)
                        Text("Liv 6")
                            .textColor(.darkGray)
                            .textAlign(.center)
                            .size(width: 40, height: 16)
                            .font(size: 9)
                            .backgroundColor(.green)
                    }
                    Text("self.model.descriptionself.model.descriptionself.model.descriptionself.model.description")
                        .font(style: .bold)
                        .textColor(.gray)
                }.padding(edge: .left, value: 5).shrink(1)
                Spacer()
                Button(text: ":") {
                    print("点击")
                }.size(width: 35, height: 35)
            }.alignItems(.center)
            .padding(edge: .bottom, value: 15)
            HStack {
                
            }.height(.percent(67))
            HStack {
                
            }.padding(edge: .top, value: 15)
        }.padding(edge: .all, value: 15)
    }
这里我们需要关注 4 个地方

1、 .alignSelf(.center)

这个是弹性盒子的属性:alignSelf 是针对盒子某一个元素的布局行为. 这里是 设置 center 居中。

关于弹性盒子 这里有详细的解释.

2、.circle()

这个是设置图片是一个圆

3、 .shrink(1)

主要处理视图内容拥挤的时候对视图收缩的占比关系,数值越大收缩的幅度越大. 默认是 0, 这里只对它唯一设置1就是最大值.

4、.alignItems(.center)

盒子内元素间的对齐和空间分配, 这里设置 居中 .center

第四步:完成第二个 HStack 内部结构

这里面的内容是一个图片. 左右没有占据元素,点击图片应该是会有一个事件. 我们这里就是设置一个按钮,就不需要 HStack 包装了, 按钮的内容是一个图片。 用 ArgoKit HStack 里面的内容是这样的:

Button {
    print("放大图片事件")
} builder: { () -> View in
    Image("turtlerock")
        .cornerRadius(12)
        .grow(1)             ///     .width(100%)
        .alignSelf(.stretch) ///     .height(100%)
}.height(.percent(67))

这里需要关注 4 个地方
  • 1、.cornerRadius(12)

设置图片圆角是 12

  • 2、.grow(1)

指定了弹性盒子容器中剩余空间的分配关系,只分配设置的grow 值的视图。 比如: size:当前盒子的宽度是: 200, 高度是: 100 方向:水平排列 内容:盒子中有 view1, view2, view3 三个视图.分别占用宽度是 20,20,20. 那么未占用的内容宽度有 140.

当我们设置 view1grow = 1,其它不设置。那么未占用的宽度都会分配给 view1, 同理如果设置等宽那么设置 grow 的值相同 (>0 默认是0) 即可。

比例分配原则: 所有内容的:grow 值之和是总值,按各 viewgrow 值的占用比例去分配剩下未占用的空间。

这里设置 .grow(1) 等效于 .width(100%)

  • 3、.alignSelf(.stretch)

alignItems 是设置盒子内的元素统一的行为,而 alignSelf 是针对盒子某一个元素的布局行为。

这里是 stretch 等效于 .height(100%)

  • 4、.height(.percent(67))

.percent(67) 是占用父视图高度的 67%

第五步:完成最后一个 HStack 内部结构

最后一个 HStack 里面的内容是 三个事件按钮一个标签. 都是水平排列。 三个按钮左排列,标签是右排列。整体水平居中展示.

由于三个事件按钮都是一样的我们定义一个就可以了,对于事件我们使用一个枚举去区别。

事件这样定义:

    enum Action {
        case like
        case praise
        case share
    }

事件的 UI 我们可以这样定义一个函数返回 View:

    func button(_ text: String, _ action: Action) -> View {
        return {
            Button {
                switch action {
                case .like:
                    print("点赞")
                case .praise:
                    print("夸")
                case .share:
                    print("分享")
                }
            } builder: { () -> View in
                Text(text)
            }
        }()
    }
1、那么这三个事件的 View 就是这样的:
var like: ArgoKit.View {
    HStack {
        self.button("👍 赞", .like)
        self.button("😄 夸", .praise)
            .padding(edge: .left, value: 15)
        self.button("🤘 分享", .praise)
            .padding(edge: .left, value: 15)
    }
}

2、与标签的组合是这样的
var action: View {
    HStack {
        self.like
        Spacer()
        Text("特权操作")
            .font(size: 10)
            .textColor(.gray)
            .alignSelf(.center)
    }
}

Spacer()

是把两边的视图分到两边. self.like 靠左,Text("特权操作") 靠右

这样我们最后一个 HStack 的 View 就完成了。

接下来我们需要整体整理一下.

1.3 整理

1.3.1 我们把第一个 HStack 抽成:var user: View

它是这样的:


var user: View {
    HStack {
        Text("<")
            .padding(edge: .right, value: 5)
            .alignSelf(.center)
        Image(self.model.userImage)
            .circle()
            .width(35)
            .height(35)
        VStack {
            HStack {
                Text(self.model.name)
                    .font(style: .bold)
                    .padding(edge: .right, value: 5)
                Text("Liv \(self.model.live)")
                    .textColor(.darkGray)
                    .textAlign(.center)
                    .size(width: 40, height: 16)
                    .font(size: 9)
                    .backgroundColor(.green)
            }
            Text("self.model.descriptionself.model.descriptionself.model.descriptionself.model.description")
                .font(style: .bold)
                .textColor(.gray)
        }.padding(edge: .left, value: 5).shrink(1)
        Spacer()
        Button(text: ":") {
            print("点击")
        }.size(width: 35, height: 35)
    }.alignItems(.center)
}
    

1.3.2 第二个 HStack 抽成 var image: View

它是这样的:

var image: View {
    Button {
        print("放大图片事件")
    } builder: { () -> View in
        Image(self.model.image)
            .clipsToBounds(true)
            .cornerRadius(12)
            .grow(1)             ///     .width(100%)
            .alignSelf(.stretch) ///     .height(100%)
        

    }
}

第三个咱们已经拆成了 var action: View 直接用即可

1.3.3 最后在 body 是这样的

var body: View {
    VStack() {
        self.user
            .padding(edge: .bottom, value: 15)
        self.image
            .height(.percent(67))
        self.action
            .padding(edge: .top, value: 15)
            .height(35)
    }.padding(edge: .all, value: 15)
    .alignItems(.stretch)
}

这样我们的这个 Demo 就完成了.

完整 Demo 源码在最后

1.3.4 效果

效果

ImagePage.swift 文件


import ArgoKit

class ImagePage: ArgoKit.View {
    
    init(model: ImagePageModel) {
        self.model = model
    }
    
    var model: ImagePageModel
    var isRequest = true
    
    typealias View = ArgoKit.View
    
    var body: View {
        VStack() {
            self.user
                .padding(edge: .bottom, value: 15)
            self.image
                .height(.percent(67))
            self.action
                .padding(edge: .top, value: 15)
                .height(35)
        }.padding(edge: .all, value: 15)
        .alignItems(.stretch)
    }

    var user: View {
        HStack {
            Text("<")
                .padding(edge: .right, value: 5)
                .alignSelf(.center)
            Image(self.model.userImage)
                .circle()
                .width(35)
                .height(35)
            VStack {
                HStack {
                    Text(self.model.name)
                        .font(style: .bold)
                        .padding(edge: .right, value: 5)
                    Text("Liv \(self.model.live)")
                        .textColor(.darkGray)
                        .textAlign(.center)
                        .size(width: 40, height: 16)
                        .font(size: 9)
                        .backgroundColor(.green)
                }
                Text("self.model.descriptionself.model.descriptionself.model.descriptionself.model.description")
                    .font(style: .bold)
                    .textColor(.gray)
            }.padding(edge: .left, value: 5).shrink(1)
            Spacer()
            Button(text: ":") {
                print("点击")
            }.size(width: 35, height: 35)
        }.alignItems(.center)
    }
    
    var action: View {
        HStack {
            self.like
            Spacer()
            Text("特权操作")
                .font(size: 10)
                .textColor(.gray)
                .alignSelf(.center)
        }
    }
    
    
    var like: ArgoKit.View {
        HStack {
            self.button("👍 赞", .like)
            self.button("😄 夸", .praise)
                .padding(edge: .left, value: 15)
            self.button("🤘 分享", .praise)
                .padding(edge: .left, value: 15)
        }
    }
    
    var image: View {
        Button {
            print("放大图片事件")
        } builder: { () -> View in
            Image(self.model.image)
                .clipsToBounds(true)
                .cornerRadius(12)
                .grow(1)             ///     .width(100%)
                .alignSelf(.stretch) ///     .height(100%)
            

        }
    }
    
    func button(_ text: String, _ action: Action) -> View {
        return {
            Button {
                switch action {
                case .like:
                    print("点赞")
                case .praise:
                    print("夸")
                case .share:
                    print("分享")
                }
            } builder: { () -> View in
                Text(text)
            }
        }()
    }
    
    enum Action {
        case like
        case praise
        case share
    }
}

#if canImport(SwiftUI) && DEBUG
import ArgoKitPreview
import SwiftUI
@available(iOS 13.0.0, *)
struct ImagePage_Previews: PreviewProvider {
    static var previews: some SwiftUI.View {
        ArgoRender {
            ImagePage(model: ImagePageModel()).body
        }
    }
}
#endif

ImagePageModel.swift 文件

import Foundation
import ArgoKit

struct ImagePageModel: ArgoKitIdentifiable, Codable, Identifiable {
    var reuseIdentifier: String
    let id: String
    let userImage: String
    let live: Int
    var name: String
    let description: String
    let image: String
    
    /// 伪数据
    init() {
        reuseIdentifier = "reuseIdentifier"
        id = "idsdsd sd sd"
        userImage = "turtlerock"
        live = 6
        name = "MOMO 科技"
        description = "7 月23日 来自通讯录好友"
        image = "turtlerock"
    }
}

Clone this wiki locally