Android实现拖拽式布局开发----约束性布局

通过约束性布局快速开发UI


约束性布局允许你通过扁平的视图结构图(没有嵌套视图组)来创建复杂的布局。因为所有的视图都根据与同级或父级的关系来设置,所以和相对布局有点相似,但是Android的视图编辑器比相对布局更加地稳定和简单。


因为布局的API和布局的编辑器是相互关联的,所以你只能通过布局编辑器来使用约束性布局。你可以通过拖拽代替编辑XML的方式来创建布局。


图1:编辑器里面的约束性布局


从Android2.3(API 19)开始支持约束性布局,从Android Studio 2.2开始可以使用约束性布局编辑器。


下面展示了在Android Studio中创建约束性布局的过程。如果你想知道更多关于编辑器的信息,可以参考Android Studio的官方指南Build a UI with Layout Editor(https://developer.android.com/studio/write/layout-editor.html)。


约束性布局预览

为了确定组件在约束性布局中的位置,你必须添加两个或者多个约束性组件。每个约束代表了与另一个组件、父布局的关系、对齐方式或者说是无形的指南。每个约束通过组件的横纵坐标定义了组件的位置,所以每个组件至少需要有一个约束性坐标,但是通常需要多个。


当你拖动一个组件到布局编辑器中时,即使没有约束信息,编辑器也会将组件放在你所拖动到的位置。然后,这只是方便了编辑,如果组件没有约束信息,当你在机器上运行时,这个组件会显示到坐标[0,0](左上角)。


在图2种,组件在布局编辑器中显示正常,但是TextView B并没有纵向的约束信息。当在机器上运行时,由于没有约束信息,TextView B显示到了屏幕的左上角

图2.TextView B缺少了纵向约束信息



图3.TextView B与ImageView的纵向垂直


尽管缺少约束性信息并不会引起编译错误,布局编辑器也会在工具栏里显示一个缺少约束信息的错误。如果要查看错误或者其它警告,点击Show Warnings and Errors.为了避免缺少约束性信息,布局编辑器可以通过自动推断( Autoconnect and infer constraints )功能将约束信息给你添加上。


为你的项目添加约束布局

下面是在项目中使用约束布局的步骤:

1.确保有最新的Constraint Layout library:

1.点击Tools > Android > SDK Manager

2.点击标签页SDK Tools

        3.展开Support Repository 并点击ConstraintLayout for Android 和Solver for ConstraintLayout.查看包信息和你所下载的版本信息(下面将用到)

         4.点击OK

         5.在build.gradle文件中添加ConstraintLayout Library的依赖

dependencies {
    compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha8'
}

      这里下载的library版本可能有点高,以此来适应步骤3种下载的版本。

            6.在工具栏或者是同步提示中,点击Sync Project with Gradle Files.

现在你可以通过约束性布局开发你的布局了。


注:

打开SDK Manager


选择tab页并选中ConstraintLayout for Android and Solver for ConstraintLayout,点击OK


将依赖添加进module层的build.gradle




转换成约束性布局

将普通布局转换成约束性布局的步骤如下:

1.在Android Studio中打开所要编辑的布局,并点击窗口下方的tab页Design

2.在Component Tree窗口中,在布局上点击鼠标右键并选择Convert layout 头ConstraintLayout


图4.转换成约束性布局的菜单选项


注:

这是一个从其它项目拷贝的普通的布局


点击窗口下方的标签页design


在Component Tree窗口中点击布局并选中Convert Layout to ConstraintLayout.


再选中tab页text中时,可以看到RelativeLayout转换成了ConstraintLayout



创建一个新的约束性布局

创建一个新的约束性布局的步骤如下:

1.在项目窗口的任何位置点击鼠标,然后选择File->New->XML->Layout XML.

2.在root tag中输入"android.support.constraint.ConstraintLayout"

3.点击Finish

注:在root tag中输入


可以看到生成的布局中包含ConstraintLayout





添加约束信息

从Palette创建中将组件拖动到编辑器中。将向ConstraintLayout中添加一个组件后,将会显示一个可以任意调整大小的方框。

点击来选中这个组件。长按并拖拽到可以移动到的地方(另一个view的边缘,布局的边缘,或者是指导线)。当松手时,约束信息将会被创建,可以通过默认的margin值来分开两个组件。


当创建约束时,遵守下面的原则:

--- 每个组件至少包含两个约束信息:横向的约束信息和纵向的约束信息

---  你约束手柄与相同类型的约束手柄之间建立联系。所以组件的纵向(左侧和右侧)只能被另一个组件的纵向约束;一个组件的基准线只能被另一个组件的基准线来约束。

--- 每个约束手柄只能约束一次,但是你可以将不同的组件的约束手柄指向该组件的同一个约束手柄源来实现多个约束。


如果要移除一个约束信息,选择相应的组件并点击约束手柄。


如果你为一个组件添加了与已存在的约束相对应的约束,则会生成像弹簧一样的线。当组件在约束信息之间时效果会更加明显。如果你希望组件能够调整大小满足约束信息,将组件的大小设置为“any size”;如你只是希望移动组件的位置但是并不希望调整大小,那就调整约束。


有很多方式对一个组件进行约束,但是下面是一些基本的用法。

注:

从Palette中将一个Button拖入编辑界面,最右边的方框是可以随意拖动调整大小的


可以随便调整大小的方框




通过父控件来约束

调整控件边缘以满足在布局中的合适位置。

在图5中,组件的左边缘与父布局的左边缘相连。


图5.相对应父布局的横向约束


位置约束

通过横向和纵向约束来跳转两个控件显示的位置。

图6是一个Button在Imageview下面24dp的约束。


图6.一个纵向的约束


对齐约束

将一个组件与另一个组件的边缘对齐。

在图7中,Button的左边与ImageView的左边相对齐。


图7.对齐约束


你也可以通过拖拽来实现偏移对齐约束。如图8所示Button与ImageView的边缘向右偏移24dp的位置对齐。偏移约束由组件的margin来定义。


图8.横向偏移对齐约束


基准线对齐约束

将一个TextView的基准线与另一个TextView的基准线对齐。

在图9种,TextView第一行的字体与Button中的字体对齐。

为了创建基准线约束,你的鼠标需要在基准线约束手柄上停留2s制动手柄显示为白色。然后再点击并拖拽基准线,到相对于另一个组件的基准线的合适位置。



创建指导线

你可以将指导线添加到约束信息中。你可以在布局中为控件的边缘添加以dp为单位或者百分比形式的指导线。

点击工具栏中的Guidelines图标,然后选择Add Vertical Guideline或者Add Horizontal Guidline.

点击知道先旁边的包含左箭头的圆形图标来画指导线的位置(到布局边缘的dp距离或者是百分比距离)

指导线对用户来说是不可见的。


注:

点击基准线图标,然后点击控件,移动控件的边缘来确定组件的位置




约束的自动链接和自动推断

自动推断是为布局中的每个组件自动添加两个或多个约束信息。自动推断默认是禁止的。你可以在布局编辑器的工具栏中点击Turn on Autoconnect来打开自动推断。

当打开自动推断功能时,将自动为每个组件添加约束信息;它并不创建约束信息。如果你已经为一个拖进来的空间添加了约束信息,约束信息将不会改变(margin也不改变),所以如果你想重新为组件定位时,你必须删除原来的约束信息。

你也可以通过点击Infer Constraints来为布局中所有的控件添加约束信息。

自动推断是根据布局来决定每个控件的位置一次性为所有的控件添加约束信息,所以相距很远的组件之间也可能创建约束信息。然而自动链接只是为你你所添加的一个组件添加约束信息,而且只与最近的组件创建约束信息。无论哪种情况,你都可以点击约束手柄并删除,来重新创建新的约束。


调整空间的大小

你可以通过组件四角的手柄来调整组件的大小,但是你应该避免使用这种将组件的宽高进行硬编码的方式,因为硬编码不利于适配。通过选择窗口右边编辑器中的Properties来选择自动调整大小的模式或是更多定义大小的方式。图10所示的是窗口上方显示的是inspector。



图10.属性界面包括了控制(1)大小,(2)边距,(3)偏移量约束


灰色的方框代表所选中的控件。方框内部的符合的定义如下:

Wrap Content:组件根据控件中的内容来调整大小

Any Size:根据约束条件来决定控件的大小。由于控件没有定义大小,所以实际的值是0dp,但是会根据约束条件来自动调整组件的大小。但是如果该组件只定义了一个约束条件,则会根据组件中的内容来调整控件的大小。另一种方式是“match constraints”(不是match_parent),控件大小为测算每个约束条件和边距后的最大空间的大小。

Fixed:指定了控件的大小或者在编辑器中跳转控件的大小。

如果要进行改变,点击那些符号。

注意:在约束性布局中不要使用任何match_parent,而要用"Any Size"(0dp)代替



调整约束偏移量

当为一个控件的两侧都添加了约束时(并且大小设置的是“fixed”或者是“wrap content”),然后该组件位于两个句柄的中间。当控件位于正中间时,偏移量是50%。你可以通过拖拽属性界面的滑动条来调整大小,也可以通过拖拽控件的位置来调整。

如果你想让控件自适应约束,将大小改为“any size”


调整控件的边距

为了让控件均匀地分布,点击工具栏中的Mrgin图标来为添加到布局中的每个控件设置默认的margin值。按钮上显示了现在的margin值。margin只是改变了当前所编辑的控件的值。


图11.工具栏中的margin按钮。点击调整默认的margin值。


所有的默认的margin值都是Material Design所建议的8dp。

注:将studio版本更新到2.2.0,需要更改project的build.gradle文件,将gradle plugin的版本改到2.14

classpath 'com.android.tools.build:gradle:2.1.4'





原文地址:https://developer.android.com/training/constraint-layout/index.html#add-a-constraint


参考资料:http://gold.xitu.io/entry/575059535bbb500059b0b608

http://www.jianshu.com/p/792d2682c538

http://www.wuji8.com/meta/91969616.html

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当一个View超出屏幕时,你可以使用ScrollView或者HorizontalScrollView来解决这个问题。 如果你想拖动一个ImageView,并且希望它不会超出屏幕,你可以使用以下代码: ```java imageView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { // 手指按下时记录位置 lastX = event.getRawX(); lastY = event.getRawY(); break; } case MotionEvent.ACTION_MOVE: { // 移动的距离 float dx = event.getRawX() - lastX; float dy = event.getRawY() - lastY; // 获取imageView的参数 RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) v.getLayoutParams(); // 移动imageView lp.leftMargin += dx; lp.topMargin += dy; // 确定imageView不会超出屏幕 int screenWidth = getResources().getDisplayMetrics().widthPixels; int screenHeight = getResources().getDisplayMetrics().heightPixels; if (lp.leftMargin < 0) { lp.leftMargin = 0; } else if (lp.leftMargin + v.getWidth() > screenWidth) { lp.leftMargin = screenWidth - v.getWidth(); } if (lp.topMargin < 0) { lp.topMargin = 0; } else if (lp.topMargin + v.getHeight() > screenHeight) { lp.topMargin = screenHeight - v.getHeight(); } // 重新设置imageView的参数 v.setLayoutParams(lp); // 更新位置记录 lastX = event.getRawX(); lastY = event.getRawY(); break; } case MotionEvent.ACTION_UP: { // 手指抬起时不需要做任何事情 break; } } return true; } }); ``` 这个代码片段会允许你拖动ImageView,但是它不会被拖动超出屏幕。如果ImageView被拖动到了屏幕边缘,它会停在那里并且无法继续拖动。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值