UILayoutKit 0.0.3

UILayoutKit 0.0.3

测试已测试
Lang语言 Obj-CObjective C
许可证 Apache 2
发布最新发布2016年7月

towik维护。



  • towik

UILayoutKit 是 Android 布局系统的移植,及其可绘制和资源框架到 iOS。它是 iDroidLayout 项目的延续。

为什么?

此项目的主要原因是为了更深入地了解 Android 布局系统和其工作原理。另一个原因是 iOS 缺乏高级布局系统(更新:对于 iOS >= 6,由于引入了布局约束,这已经不再是事实了)。目前,在 iOS 中构建可维护的 UI 代码是一个问题。您可以选择在界面构建器中进行布局,这对于静态内容非常棒,但是不足以处理动态内容,或者全部使用代码,这很难维护。在 Android 中,可以采用 XML 定义布局。视图会自动调整其大小,同时考虑到其内容需求和父视图的大小限制。

亮点

  • 在 XML 中定义 布局
  • 使用 原生 UI 小部件,如 UIButton、UITextField 等,即使在布局 XML 中的 UIView 的自定义子类中也可以使用
  • 线性布局视图,向右或向上(LinearLayout
  • 相对位置布局视图和与其父视图(RelativeLayout
  • 将视图添加到 UIScrollViews 并让它们根据您的布局自动调整内容大小
  • 通过实现 自定义布局容器 来扩展布局系统
  • Interface Builder 中加载动态 xml 布局
  • 使用功能强大的 资源管理器 维护您的资源
  • 在 XML 中定义可维护的 图形,它们在运行时实时渲染
  • 支持 9-Patch PNGs

入门

可以使用 CocoaPods 安装 UILayoutKit

Podfile

pod 'UILayoutKit'

使用 UILayoutKit 定义和使用布局可以分成两个简单的步骤

  1. 创建一个包含您的视图层次结构的布局 xml 文件,并保存为 myLayout.xml。例如。
        <LinearLayout
            layout_width="match_parent"
            layout_height="wrap_content"
            orientation="vertical"
            padding="10">
            <LinearLayout
                layout_width="match_parent"
                layout_height="wrap_content"
                orientation="horizontal">
                <Label
                    id="text"
                    layout_width="wrap_content"
                    layout_height="wrap_content"
                    padding="10"
                    text="Some text"
                    textColor="#ffffff"
                    background="#80000000"/>
                <Label
                    id="otherText"
                    layout_width="match_parent"
                    layout_height="match_parent"
                    padding="10"
                    textColor="#ffffff"
                    background="#ff0000"
                    gravity="right"
                    text="Some other text"/>
            </LinearLayout>
            <UIButton
                id="button"
                background="#ff0000"
                layout_width="100"
                layout_height="30"
                layout_gravity="center_horizontal"
                layout_marginTop="10"
                text="Click me"/>
        </LinearLayout>
  1. 创建一个 ULKLayoutViewController 的实例
        ULKLayoutViewController *vc = [[ULKLayoutViewController alloc] initWithLayoutName:@"myLayout" bundle:nil];
        [self.navigationController pushViewController:vc animated:TRUE];
  1. 享受

    Layout

资源

UILayoutKit 包含一个高级资源解析框架。它允许您引用资源,如图像、布局、字符串、颜色和样式。资源标识符允许您引用资源。例如,它可以允许您指定布局内视图的文本和图像。

资源标识符语法

资源标识符的语法如下:[<bundle-identifier>:]<resource-type>/<resource-name>[.<resource-subname>]

  • <bundle-identifier>包含资源的包标识符。如果省略包标识符,则会在该主包内搜索资源。要使用除主包之外的包,您必须在资源标识符使用此包之前至少加载一次该包。
  • <resource-type>资源类型(如下面的其中一个:stringlayoutdrawablecolorstyle
  • <resource-name>资源文件的名称
  • <resource-subname>资源文件内特定资源的标识符。这仅用于某些充当资源容器的资源类型。

Drawables

Drawable 是指可以在屏幕上绘制的东西的抽象概念。这可能是简单的位图图形、颜色、形状或者这些的组合。目前实现了以下类型的邓小平:

位图

位图图形(例如 png, jpg),也可以是 9-patch 图形

层列表

管理其他 Drawables 的数组的 Drawable。这些按数组顺序绘制,因此索引最大的元素将在最上面绘制

状态列表

被其他 drawables 引用的 Drawable,取决于 drawables 的状态(例如,为不同的按钮状态绘制不同的图像)。

内嵌 Drawable

将另一个 drawable 内嵌进来的 drawable

剪切 Drawable

根据 drawables 的层级剪切另一个 drawable

形状 Drawable

绘制一个几何形状,可以用颜色或渐变填充

Drawable 可以在 XML 中定义,并可以膨胀为 drawable 对象树。以下是一个示例

    <layer-list>
        <item left="12" top="12" right="8" bottom="8">
            <shape shape="rectangle">
                <solid color="#8000"/>
                <corners topLeftRadius="40" bottomRightRadius="10"/>
            </shape>
        </item>
        <item left="10" top="10" right="10" bottom="10">
            <shape shape="rectangle" thicknessRatio="8" innerRadiusRatio="3">
                <gradient centerX="-0.1" centerY="-0.1" gradientRadius="300%" type="radial" startColor="#ccc" centerColor="#0fff" endColor="#0f0"/>
                <corners topLeftRadius="40" bottomRightRadius="10"/>
                <stroke width="1" color="#8000"/>
                <padding left="5"/>
            </shape>
        </item>
        <item>
            <selector>
                <item state_pressed="true">
                    <inset insetLeft="10" insetTop="10" insetRight="10" insetBottom="10">
                    <shape shape="rectangle">
                        <gradient startColor="#f00" centerColor="#0fff" endColor="#0ff"/>
                        <corners topLeftRadius="40" bottomRightRadius="10"/>
                    </shape>
                    </inset>
                </item>
            </selector
        </item>
    </layer-list>

假设您将 drawable XML 保存到文件 background.xml 中。现在您可以在布局中按如下方式定义按钮

    <Button
        textColor="#eee"
        layout_width="match_parent"
        layout_height="100"
        layout_gravity="center"
        background="@drawable/background"
        text="Button"/>

Button in normal state

图1: 以自定义 drawable 作为背景的正常状态的按钮

Button in pressed state

图2: 以自定义 drawable 作为背景的按下状态的按钮

问题 & 回答

我不想从 layout XML 加载整个视图层次结构。如何将布局加载到我现有视图层次结构的一个特定部分?

ULKLayoutBridge 是一个 UIView,作为普通视图布局机制和 UILayoutKit 机制之间的桥梁。首先,您必须创建一个 ULKLayoutBridge 对象并将其添加到您的视图层次结构中。现在您可以使用 ULK(LayoutInflater) 将 xml 布局加载到 ULKLayoutBridge 视图中。

    ULKLayoutBridge *bridge = [[ULKLayoutBridge alloc] initWithFrame:CGRectMake(100, 100, 120, 220)];
    ULKLayoutInflater *inflater = [[ULKLayoutInflater alloc] init];
    [inflater inflateURL:[[NSBundle mainBundle] URLForResource:@"myLayout" withExtension:@"xml"] intoRootView:bridge attachToRoot:TRUE];
    [self.view addSubview:bridge];
我能否使用本地视图?

是的,您可以使用本地视图。只需将视图的类名用作 xml 标签名(例如 <UIButton/>)。但是,对于某些本地视图,onMeasureWithWidthMeasureSpec:heightMeasureSpec: 选择器尚未实现,因此您不应该为视图的宽度和高度使用 wrap_content

我能否使用自定义视图?

是的,只需使用视图的类名作为xml标签名(例如:<MyCustomView/>)。但是,您应该实现onMeasureWithWidthMeasureSpec:heightMeasureSpec:选择器。否则您不应该为视图的宽度和高度使用wrap_content

我的自定义视图不应该使用init初始化(类似于ULKLayoutInflater通常做的那样)。我该如何实现自定义初始化呢?

ULKLayoutInflater使用ULKViewFactory协议的默认实现来创建视图对象。您可以通过实现该协议并设置ULKLayoutInflaterviewFactory属性来自定义视图工厂。

我能在UITableViewCell中使用XML布局吗?

是的,您可以使用ULKTableViewCell或者创建一个自定义的UITableViewCell,在其内部将布局充气到ULKLayoutBridge中。

我能在定义在xib文件中的视图中加载xml布局吗?

是的,可以将布局xml文件充气到界面构建器中的视图中。简单地在界面构建器中添加一个普通视图,将新添加视图的“自定义类”设置为ULKLayoutBridge,并定义一个用户定义的运行时属性,属性名为layout,属性值为您要加载的xml文件名称(不带文件扩展名)。更多详细信息,请查看示例项目。

我能在其他布局中重用布局吗?

类似于Android布局系统,您可以使用<include/><merge/>标签将其他布局嵌入到布局XML文件中。在您想要添加可重用组件的布局中添加标签。以下是一个例子

    <LinearLayout
        layout_width="match_parent"
        layout_height="match_parent"
        orientation="vertical">

        <include layout="@layout/layoutToInclude"/>

        <Label
            layout_width="match_parent"
            layout_height="wrap_content"
            text="Some text"/>
    </LinearLayout>

您还可以通过在<include/>标签中指定它们来覆盖包含布局的根视图的所有布局参数(任何layout_*属性)、id和可见性。例如

    <include id="title"
             layout_width="match_parent"
             layout_height="match_parent"
             layout="@layout/layoutToInclude"
             visibility="gone"/>

XML文件始终需要一个单个根元素。如果您必须从另一个单独的布局文件包含多个视图,您需要将容器作为根元素。这就是<merge/>标签发挥作用的地方。它允许您一次包含多个视图,而不需要额外的布局容器

    <merge>
        <Label
            layout_width="match_parent"
            layout_height="wrap_content"
            text="First text view"/>
        <Label
            layout_width="match_parent"
            layout_height="wrap_content"
            text="Second text view"/>
    </merge>

现在,当您将此布局包含到另一个布局中(使用<include/>标签)时,系统会忽略<merge/>元素,并将两个文本视图直接放置在布局中,替代<include/>标签的位置。