安卓约束布局的编程实现?

45

在iOS中,我非常喜欢删除Storyboard并使用Cartography框架来编写布局代码。以下是从Cartography的Github上借鉴的内容:

constrain(view1, view2) { view1, view2 in
    view1.width   == (view1.superview!.width - 50) * 0.5
    view2.width   == view1.width - 50
    view1.height  == 40
    view2.height  == view1.height
    view1.centerX == view1.superview!.centerX
    view2.centerX == view1.centerX

    view1.top >= view1.superview!.top + 20
    view2.top == view1.bottom + 20
}

Android有没有任何等效的东西?似乎新的约束布局是朝着正确方向迈出的一步,但我想通过编程来实现它。


6
人们希望以编程的方式完成这个任务有很多原因,比如人们正在开发除应用程序外具有预定义用户界面的库,或者人们需要在运行时更改受用户交互影响的布局规范,还有更多其他原因... 谷歌在这个新特性上确实缺乏文档资料。 - yongsunCN
3
另一个(简单的)原因是,如果你需要使用TransitionManager,特别是TransitionManager.beginDelayedTransition(root);,那么你必须手动指定布局更改,以便它们在下一次渲染时得到呈现。因此,有时你需要编程修改内容。 - Martin Marconcini
2个回答

74

有些晚了,但你需要将约束布局中的视图视为普通视图,只是它们有自己的LayoutParams。

关于ConstraintLayout的说明可以在这里找到:https://developer.android.com/reference/androidx/constraintlayout/widget/ConstraintLayout.LayoutParams

该类包含不同的属性,指定视图在ConstraintLayout中希望如何布局。建议使用ConstraintSet来在运行时构建约束。

因此,推荐的方法是使用ConstraintSet

那里有一个很好的代码示例,但核心概念是您需要创建一个新的集合(通过复制/克隆/新建等方式),设置其属性,然后将其应用于您的布局。

例如:假设您的布局包含一个名为mConstraintLayout的ConstraintLayout,并且内部包含一个视图(示例中的R.id.go_button),您可以执行以下操作:

    ConstraintSet set = new ConstraintSet();

    // You may want (optional) to start with the existing constraint,
    // so uncomment this.
    // set.clone(mConstraintLayout); 

    // Resize to 100dp
    set.constrainHeight(R.id.go_button, (int)(100 * density));
    set.constrainWidth(R.id.go_button, (int)(100 * density));

    // center horizontally in the container
    set.centerHorizontally(R.id.go_button, R.id.rootLayout);

    // pin to the bottom of the container
    set.connect(R.id.go_button, BOTTOM, R.id.rootLayout, BOTTOM, 8);

    // Apply the changes
    set.applyTo(mConstraintLayout); 
    // this is my… (ConstraintLayout) findViewById(R.id.rootLayout);

15
在我的情况下,需要添加set.clone(mConstraintLayout)来复制当前约束条件,然后再进行添加操作。 - Carlos Perez Perez
你戴着拖把头了吗,@Martin Marconcini? - Tom Howard
1
@TomHoward 我不敢! ;) (如果你好奇,http://www.thinkgeek.com/product/f0d0/)以防链接将来失效,请谷歌“矮人胡须帽”(我在think geek买的),大约5年前。 - Martin Marconcini
@CarlosPerezPerez 感谢您的评论,我认为(在文本中)已经很清楚了,但为了更加明确,我已经添加了克隆代码(已注释)在那里。+1 :) - Martin Marconcini
“对我来说,句子“For building up constraints at run time, using ConstraintSet is recommended.”很令人困惑。事实上,我正在通过编程创建视图,这意味着我正在运行时定义约束条件。所以我不理解那句话的含义。我在https://stackoverflow.com/questions/60030308/difference-between-constraintset-and-constraintlayout-layoutparams 上有一个类似的问题。您能看一下吗?” - Mukesh Ghatiya
@MukeshGhatiya,我给你留了一条评论。 - Martin Marconcini

2
我也曾遇到过同样的困境,因为在iOS中,以编程方式构建视图是更常见的做法。
我正在使用Kotlin将Stevia库移植到Android平台,这里是该项目的链接。由于新的ConstraintLayout与我们喜爱的Autolayout非常相似,所以进行移植工作较为容易。
以下是如何定义一个简单的视图。
class MyView(context: Context): ConstraintLayout(context) {

  val label = TextView(context)

  init {

      // View Hierarchy
      subviews(
          label
      )

      // Layout
      label.centerInParent()

      // Style
      label.style {
          textSize = 12F
      }
  }}

请注意,如Martin的回答所解释的那样,这是基于纯原生约束布局实现的。
虽然只是一个开始,但到目前为止,使用它来编写Kotlin Android视图已经被证明是一种令人愉悦的方式,因此我想分享一下。希望这能有所帮助 :)

我是 Stevia 在 iOS 上的用户和贡献者。这可能是最好的选择。 - onurgenes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接