六、iWriter 布局的设定

大家好,我是姜友华,前面两章我们实现了两类视图,一个是标签视图,一个是分割视图。这一节我们来实现布局的控制。

在进行布局控制之前,我们先来了解一下布局。

一、布局的设定。

布局的构成

上图是我们对当前应用进行的布局设定,它有以下特征。

  1. 布局是由分割视图(SplitView)和标签视图(BlockView)组成,前者为枝节点,后者为叶节点。
  2. 每一个BlockView会加载一组功能视图。
  3. 每个SplitView必须至少包含有一个BlockView,如果没有,则该SplitView可被移除。

二、 数据的设定。

1)数据的定义。

通过布局的设定,我们可以理解为布局是加载一组树状结构的数据。所以我们将这下数据抽取出来,表现如下:

struct Layout: Codable {
    static func == (lhs: Layout, rhs: Layout) -> Bool {
        return lhs.id == rhs.id
    }
    var id = Date.id
    var children: [Layout] = [] // 为空时为叶节点
    var kind: Kind = .hSplit
    var bar: Bar = Bar()
    var length: CGFloat? = nil
    
    enum Kind: Codable, Equatable, Hashable {
        case hSplit  // 横的
        case vSplit  // 竖的
        case chapter // 章节窗口
        case assist  // 辅助功能窗口
    }
    
    struct Bar: Codable, Equatable, Hashable{
        var tags: [Int] = [0]
        var current: Int = 0
    }
}
  • id、kind、bar、length,都是附加数据。分别表示创建的时间、视图的类型、占宽或高等信息。
  • children,表示为布局视图的子节点。
  • kind,表示叶节点加载的视图的类型。暂时定义了4种:
    1. hSplit水平分割的视图;
    2. vSplit垂直分割的视图;
    3. chapter章节视图;
    4. assist辅助功能视图。
  • Bar结构体,需要说明一下。
    1. tags,打开的标签。
    2. current,当前的标签。

2)对应用的视图。

  • LayoutView,对应用kind = hSplitkind = vSplit, 加载layout,并实现布局的分割与嵌套, 与其实类型的实例化。
  • ChapterView,对应用kind = chapter, 加载章节内容。
  • AssistView,对应用kind = assist, 为辅助功能视图。具体到每个辅助功能,则都有自己的视图,暂定的有:
  1. CatalogView,目录。
  2. MindView, 导图。
  3. ReminderView,备忘。
  4. SymbolView,符号。
  5. CollectView,收藏。
  6. SearchView,搜索。
  • Layout数据示例:
let layout: Layout = Layout(
        children:[Layout(
            kind: .assist,
            bar: Layout.Bar(tags: [0], current: 0),
            length: 200
        ),Layout(
            kind: .chapter,
            bar: Layout.Bar(tags: [0], current: 0),
            length: 400
        ),Layout(
            kind: .assist,
            bar: Layout.Bar(tags: [1,2,3,4,5], current: 1),
            length: 400
        )],
        kind: .hSplit
    )

我们定义一个layout,它水平显示3栏:

  1. 加载目录,宽200;
  2. 加载文章,宽400;
  3. 加载其它辅助功能,宽400.
    需要注意的是,首先,为什么是宽?因为这是水平的kind: hSplit布局,如果是垂直的布局则为高;其次,为什么第一栏加载的是目录?因为我们初始化了一组辅助功能数据。
let assists = [
        Assist(kind: .catalog),
        Assist(kind: .mind),
        Assist(kind: .reminder),
        Assist(kind: .symbol),
        Assist(kind: .collect),
        Assist(kind: .search)
    ]

运行一下,看看效果。


布局的显示效果

三、操作的设定。

从布局的设定可以看出,界面的表面会被ChapterViewAssistView所覆盖,也就是说,我们无论将标签拖到哪个位置,其下必然有ChapterViewAssistView。因此我们只需要在ChapterViewAssistView上对拖移作反应即可。这种反映叫热区反映。

`BlockView`的反应区

热区分上下左右中和顶部,其中顶部为标签栏。

  1. 左、右热区。表示随标签移动的FunctionView将与热区BlockView水平排列,并放置其左或其右。
  2. 上、下热区。处理逻辑同上,位置为其上或其下。
  3. 中、顶热区。表示随标签移动的FunctionView将加入到热区BlockView里,作为标签方式呈现。
  4. 经过左热区时,BlockView 视图区左则显示蒙版。右、上、下如之类推。
  5. 经过中热区时,BlockView 视图区显示全蒙版。
  6. 经过顶热区时,BlockView 标题区显示位置蒙版。

好,这一节就这些,我是姜友华,下次见。

你可能感兴趣的:(六、iWriter 布局的设定)