Introduction and Dependency

Compose ConstraintLayout is mainly used to construct complex layouts, avoiding Column, Row, and Box nesting, and improving development efficiency.

Add a dependency on ConstraintLayout before you start:

implementation 'androidx. Constraintlayout: constraintlayout - compose: 1.0.0 - alpha03'
Copy the code

Note: As of this writing, Compose and Constraintlayout are not in stable versions, so the library dependencies must be updated to the latest version (or a compatible version) or incompatibilities may occur.

View the latest address of ConstraintLayout

Introduction and Depth

References to create

ConstraintLayout in the View system is referenced by ID in the XML layout, and is similar in Compose. Reserve a reference to a different View through the createRefs or createRef functions.

@Composable
fun learnConstraintLayout(a){
    ConstraintLayout() {
    	Create three references with createRefs
    	val (image,name,desc)=createRefs()
    }
}
Copy the code

The binding reference

The reference is bound to the View by constrainAs, which is equivalent to assigning an ID to the View. In addition, sometimes constarinAs code does not automatically prompt, you need to write your own code oh.

@Composable
fun learnConstraintLayout(a){
    ConstraintLayout() {
    	Create three references with createRefs
    	val (image,name,desc)=createRefs()
        
        Image(painter = painterResource(id = puppy.avatar),
                contentDescription = "dog avatar",
                modifier = Modifier
                    .constrainAs(avatar) {}Bind Image to imageRef by constrainAs
                    .size(100.dp)
                    .clip(shape = RoundedCornerShape(5)),
                contentScale = ContentScale.Crop)
    }
}
Copy the code

Bind views with other views or parent by linkTo. Parent here means ConstraintLayout itself.

@Composable
fun learnConstraintLayout(a){
    ConstraintLayout() {
    	Create three references with createRefs
    	val (image,name,desc)=createRefs()
        
        Image(painter = painterResource(id = puppy.avatar),
                contentDescription = "dog avatar". modifier = Modifier .constrainAs(avatar) { top.linkTo(parent.top) start.linkTo(parent.start) end.linkTo(parent.end) bottom.linkTo(parent.bottom) }Bind Image to imageRef by constrainAs and add a constraint
                    .size(100.dp)
                    .clip(shape = RoundedCornerShape(5)),
                contentScale = ContentScale.Crop)
    }
}

Copy the code

ConstrainAs: start, top, end, and bottom represent the left, top, right, and bottom edges of the view, and linkTo represents the interaction. For example, top.linkto (parent. Top) aligns the top edge of Image with ConstraintLayout, which is the same as layout_constraintTop_toTopOf=”parent” in view. Next, add two more texts.

@Composable
fun learnConstraintLayout(a) {

    ConstraintLayout() {
        Create three references with createRefs
        val (imageRef, nameRef, descRef) = createRefs()

        Image(painter = painterResource(id = R.mipmap.dog_avatar),
            contentDescription = "dog avatar",
            modifier = Modifier
                .constrainAs(imageRef) {Bind Image to imageRef by constrainAs and add a constraint
                    top.linkTo(parent.top)
                    start.linkTo(parent.start)
                    bottom.linkTo(parent.bottom)
                }
                .size(100.dp)
                .clip(shape = RoundedCornerShape(5)),
            contentScale = ContentScale.Crop)

        Text(
            text = "Name",
            modifier = Modifier
                .constrainAs(nameRef) {
                    top.linkTo(imageRef.top, 2.dp)
                    start.linkTo(imageRef.end, 12.dp)
                    end.linkTo(parent.end)
                    width = Dimension.fillToConstraints
                }
                .fillMaxWidth(),
            fontSize = 18.sp,
            maxLines = 1,
            textAlign = TextAlign.Left,
            overflow = TextOverflow.Ellipsis,
        )

        Text(text = "Description", modifier = Modifier
            .constrainAs(descRef) {
                top.linkTo(nameRef.bottom, 5.dp)
                start.linkTo(nameRef.start)
                end.linkTo(parent.end)
                width = Dimension.fillToConstraints
            }
            .fillMaxWidth(),
            maxLines = 1,
            overflow = TextOverflow.Ellipsis,
            style = TextStyle(color = color999999, fontSize = 13.sp)
        )
    }
}
Copy the code

In the code above, you create the Image and two Text components in ConstrantLayout. In the Text constraint, with the start.linkTo(imageref.end, 12.dp) constraint, place the nameRef Text bit to the right of the Image and add 12dp margin.

Size constraints

Notice, to increase width = Dimension to the width of the Text. The fillToConstraints constraints, let the Text Text is too long, not beyond the constraints.

For example, by default:

// Change the constraint of nameRef Text to the following code
Text(
    text = "Name Yes Yes No method occurred Yes No",
    modifier = Modifier
        .constrainAs(nameRef) {
            top.linkTo(imageRef.top, 2.dp)
            start.linkTo(imageRef.end, 12.dp)
        },
    fontSize = 18.sp,
    maxLines = 1,
    textAlign = TextAlign.Left,
    overflow = TextOverflow.Ellipsis,
)
Copy the code

As you can see from renderings, Text is longer than ConstraintLayout, and it extends beyond the screen.

Change the code to the following:

Text(
    text = "Name Yes Yes No method occurred Yes No",
    modifier = Modifier
        .constrainAs(nameRef) {
            top.linkTo(imageRef.top, 2.dp)
            start.linkTo(imageRef.end, 12.dp)
            end.linkTo(parent.end,12.dp)
            width=Dimension.fillToConstraints
        },
    fontSize = 18.sp,
    maxLines = 1,
    textAlign = TextAlign.Left,
    overflow = TextOverflow.Ellipsis,
)
Copy the code

Effect:

Dimension values are as follows:

  • FillToConstraints The space that is left free under the fillToConstraints condition, as in the example above.

  • PreferredWrapContent is adaptive but affected by the constraint, that is, if the width is less than the available width under the constraint, the view is its own width, but if it is larger, it is affected by the constraint. So is Gao.

    For example, when the remaining width of the constraint is smaller than:

    Text(
        text = "Name minus Less Test Match",
        modifier = Modifier
            .constrainAs(nameRef) {
                top.linkTo(imageRef.top, 2.dp)
                start.linkTo(imageRef.end, 12.dp)
                width=Dimension.preferredWrapContent
            },
        fontSize = 18.sp,
        textAlign = TextAlign.Left,
        overflow = TextOverflow.Ellipsis,
    )
    Copy the code

    Effect:

    Add text and align the right side with parent. Through the renderings, you can see the text newline processing.

    Text(
        text = "Name minus send send send send send pay pay pay pay test match",
        modifier = Modifier
            .constrainAs(nameRef) {
                top.linkTo(imageRef.top, 2.dp)
                start.linkTo(imageRef.end, 12.dp)
                end.linkTo(parent.end)
                width=Dimension.preferredWrapContent
            },
        fontSize = 18.sp,
        textAlign = TextAlign.Left,
        overflow = TextOverflow.Ellipsis,
    )
    Copy the code

    Effect:

  • WrapContent content is self-adaptive and is not affected by constraints.

  • PreferredValue Specifies a fixed value, subject to constraints.

  • Value Specifies the size of a fixed value, regardless of constraints.

Align center

Of course, Compose ConstraintLayout also provides center alignment, centerTo, centerHorizontallyTo, and centerVerticallyTo.

For example: Add two more texts so they are horizontally centered.

Text(text = "Age", modifier = Modifier
    .constrainAs(ageRef) {
        top.linkTo(descRef.bottom, 5.dp)
        start.linkTo(nameRef.start)

    },
    maxLines = 1,
    overflow = TextOverflow.Ellipsis,
    style = TextStyle(color = color999999, fontSize = 13.sp)
)

Text(text = "Color", modifier = Modifier
    .constrainAs(colorRef) {
        start.linkTo(ageRef.end,10.dp)
        centerVerticallyTo(ageRef)
        width = Dimension.fillToConstraints
    },
    maxLines = 1,
    overflow = TextOverflow.Ellipsis,
    style = TextStyle(color = color999999, fontSize = 13.sp)
)
Copy the code

Effect:

Guides, fences and chains

Because of the age and color sometimes different sizes and colors are set to highlight, and the time Text wants to align according to the bottom of the two. That’s when you need a fence.

val bottomBarrier=createBottomBarrier(ageRef,colorRef,margin = 5.dp)

Text(text = "2021-02-28", modifier = Modifier
    .constrainAs(timeRef) {
        start.linkTo(nameRef.start)
        top.linkTo(bottomBarrier)
    },
    maxLines = 1,
    overflow = TextOverflow.Ellipsis,
    style = TextStyle(color = color999999, fontSize = 13.sp)
)
Copy the code

Effect:

Of course, you can create barriers with createStartBarrier(), createTopBarrier(), and createEndBarrier() in different directions.

As the text on the right increases, the obnoxious project manager sometimes demands vertical centring and sometimes averages the height of the entire Constraintlayout. This is where the chain comes in. Create vertical and horizontal chains with createVerticalChain and createHorizontalChain.

 createVerticalChain(nameRef,descRef,ageRef,timeRef,chainStyle = ChainStyle.Spread)
Copy the code

Effect:

ChainStyle:

  • The Packed: compression

  • Spread: divide the

  • SpreadInside leaves views on the upper and lower sides and evenly splits the views in the middle

SpreadInside shows that this is not ideal because some of the upper and lower constraints are not set properly. For example, after adjustment:

But can be by createGuidelineFromBottom, associated with a similar API to create guide line. The guide line is not visible and acts as an alignment reference for the View.

conclusion

Compose ConstraintLayout is the Compose ConstraintLayout constraint for the View system, which is the same as the Compose ConstraintLayout constraint. ConStraintLayout 2.0 is recommended if you are not familiar with ConStraintLayout of the View system: Here comes the update you need. If some apis do not exist or errors are reported, you are advised to check the official documents to check whether the version is updated or the API is replaced or discarded.

Also: Because Compose is optimized for deep layout nesting, there is no performance advantage in using Compose ConstraintLayout over multi-layer nesting of columns and rows, for example. It’s just easier for us to develop complex layouts, align edges, etc.

ConstraintSet

ConstraintSet is primarily a ConstraintSet animation. A ConstraintSet holds the state of a layout, and switches the state of the layout.

Effect:

Code implementation:

@Composable
fun learnConstraintSet(a) {

    val orientation = remember { mutableStateOf(1)}
    
    ConstraintLayout(
        getConstraintLayout(orientation),
        Modifier
            .padding(16.dp, 0.dp, 16.dp, 0.dp)
            .background(color = colorEFEFEF, shape = RoundedCornerShape(5.dp))
            .fillMaxWidth()
            .padding(12.dp, 12.dp, 12.dp, 12.dp)
    ) {
        Image(
            painter = painterResource(id = R.mipmap.dog_avatar),
            contentDescription = "Effect picture",
            modifier = Modifier
                .layoutId("imageRef")
                .fillMaxWidth()
                .clickable {
                    if (orientation.value==0){
                        orientation.value=1
                    }else{
                        orientation.value=0
                    }
                }
                .clip(shape = RoundedCornerShape(5)),
            contentScale = ContentScale.FillWidth
        )

        Text(
            text = "The teddy dog is actually a type of poodle. Divided into four categories based on size, the most popular are the smaller breeds: miniature poodles and toy poodles. Among them, toy poodle is the smallest one. It is active, cheerful, very alert, intelligent, likes to go out, and has a good temper and adaptability. Poodles do not shed and make excellent pet dogs. If the red toy poodle does not shave its beard and mouth hair can grow into the teddy bear in the cartoon, so the red (brown) toy poodle is also called "Teddy".,
            modifier = Modifier.layoutId("titleRef"),
            fontSize = 18.sp,
            textAlign = TextAlign.Left,
            overflow = TextOverflow.Ellipsis,
            maxLines =if (orientation.value==0) Int.MAX_VALUE else 4)}},private fun getConstraintLayout(orientation:MutableState<Int>):ConstraintSet{
    return ConstraintSet {
        val imageRef= createRefFor("imageRef")
        val titleRef= createRefFor("titleRef")

        if (orientation.value==0){
            constrain(imageRef){
                start.linkTo(parent.start)
                end.linkTo(parent.end)
                top.linkTo(parent.top)
            }

            constrain(titleRef){
                start.linkTo(imageRef.start)
                end.linkTo(imageRef.end)
                top.linkTo(imageRef.bottom,16.dp)
                width= Dimension.fillToConstraints
            }
        }else{
            constrain(imageRef){
                start.linkTo(parent.start)
                top.linkTo(parent.top)
                width=Dimension.value(100.dp)
                height=Dimension.value(100.dp)
            }

            constrain(titleRef){
                start.linkTo(imageRef.end,8.dp)
                top.linkTo(imageRef.top,2.dp)
                end.linkTo(parent.end)
                bottom.linkTo(imageRef.bottom,8.dp)
                width= Dimension.fillToConstraints
                height= Dimension.fillToConstraints
            }
        }
    }
}
Copy the code

The last

Addresses of all code repositories for this article

Welcome to like + follow + comment triple play

【Github】【 Nuggets 】【 blog 】