Public number: byte array, hope to help you 😇😇
ConstraintLayout, currently the default layout in Android Studio, has the advantage of using a flat view hierarchy (no nested view groups) to create large, complex and varied layouts, which gives it an advantage over other layouts in terms of rendering efficiency. ConstraintLayout is similar to a RelativeLayout in that all views are positioned according to the relationship between their siblings and their parent layout, but with more flexibility than a RelativeLayout, And it’s easier to work with Android Studio’s layout editor
ConstraintLayout can flexibly locate and adjust the size of subviews, which depend on constraints to determine their position, and each subview must have at least one horizontal constraint and one vertical constraint. Each constraint represents how it is connected or aligned with other views, parent layouts, or invisible bootlines. In a constraint relation, there needs to be a Source (Source) and a Target (Target). The position of the Source depends on the Target, which can be understood as the Source and Target are linked together through the constraint relation. The Source position is fixed relative to Target
Importing the current latest release:
dependencies {
implementation "Androidx. Constraintlayout: constraintlayout: 2.0.4."
}
Copy the code
First, relative positioning
ConstraintLayout the basic attributes of ConstraintLayout are layout_constraintXXX_toYYYOf attributes that constrain the XXX direction of ViewA and YYY direction of ViewB. A ViewB can also be a parent container, ConstraintLayout, represented by parent. These properties are used to add vertical and horizontal constraints to the control, and the control is placed in different positions depending on whether the constraints are “present” or “strong”
layout_constraintLeft_toLeftOf
layout_constraintLeft_toRightOf
layout_constraintRight_toLeftOf
layout_constraintRight_toRightOf
layout_constraintTop_toTopOf
layout_constraintTop_toBottomOf
layout_constraintBottom_toTopOf
layout_constraintBottom_toBottomOf
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf
layout_constraintBaseline_toBaselineOf
For example, controls are aligned in different directions depending on the constraints
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintLayoutActivity">
<TextView
android:id="@+id/tv1"
android:layout_width="200dp"
android:layout_height="150dp"
android:layout_margin="20dp"
android:background="#f5ec7e"
android:gravity="center"
android:text="Hello World!"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/tv2"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:background="#68b0f9"
android:gravity="center"
android:text="No bottom constraint is set, so only the top is aligned with the yellow block."
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/tv1"
app:layout_constraintTop_toTopOf="@+id/tv1" />
<TextView
android:id="@+id/tv3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:background="#984ff7"
android:gravity="center"
android:text="There are constraints up and down, so it's going to be in the middle."
app:layout_constraintBottom_toBottomOf="@+id/tv1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/tv1"
app:layout_constraintTop_toBottomOf="@+id/tv2" />
<TextView
android:id="@+id/tv4"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#9C27B0"
android:gravity="center"
android:text="Center the screen in all directions"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
2. Intensity of binding force
If you want a control with a constant ratio of left to right or up to down spacing, that is, the strength of the binding force on both sides varies in one direction, You can rely on the layout_constraintHorizontal_bias and layout_constraintVertical_bias properties to set the horizontal and vertical offset of the control
For example, you can control the percentage of left to right or up to down spacing of a TextView
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintLayoutActivity">
<TextView
android:layout_width="200dp"
android:layout_height="200dp"
android:background="#FF9800"
android:gravity="center"
android:text="Public number: Byte array"
android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.9"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.1" />
<TextView
android:layout_width="200dp"
android:layout_height="200dp"
android:background="#2196F3"
android:gravity="center"
android:text="https://github.com/leavesC"
android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.9"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.9" />
<TextView
android:layout_width="200dp"
android:layout_height="200dp"
android:background="#4CAF50"
android:gravity="center"
android:text="Hello World!"
android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
Three, width to height ratio
ConstraintLayout is easy to use when using other layout types to maintain a fixed aspect ratio on different screens. For example, if we wanted to implement a fixed aspect ratio for the Activity’s top title bar, we could set the width to fill the screen, the height to 0dp, and then set the aspect ratio to a fixed ratio using the app:layout_constraintDimensionRatio property. ConstraintLayout dynamically calculates how tall the title bar should be based on the width of the screen
Additionally, to use the layout_constraintDimensionRatio attribute, one of its width or height values needs to be knowable, and the remaining one is 0DP. Knowable, that is, the value already has explicit constraints. The width/height ratio of the control is set by “float value” or “Width: height”, indicating whether the scale value is calculated by width or height by adding w or h before the scale value
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintLayoutActivity">
<TextView
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#f5ec7e"
android:gravity="center"
android:text="Public number: Byte array"
android:textColor="@android:color/black"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintDimensionRatio="h,15:2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:layout_width="100dp"
android:layout_height="0dp"
android:background="#5476fd"
android:gravity="center"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="W,1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
Four, the width and height ratio between controls
ConstraintLayout also sets the layout_weight property for its child controls, just like the LinearLayout does, so the width ratio between the child controls is as follows: Layout_constraintHorizontal_weight and layout_constraintVertical_weight
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintLayoutActivity">
<TextView
android:id="@+id/tv1"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#f5ec7e"
android:gravity="center"
android:text="Hello World!"
app:layout_constraintBottom_toTopOf="@id/tv4"
app:layout_constraintEnd_toStartOf="@+id/tv2"
app:layout_constraintHorizontal_weight="3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_weight="1" />
<TextView
android:id="@+id/tv2"
android:layout_width="0dp"
android:layout_height="50dp"
android:background="#55e4f4"
android:gravity="center"
android:text="Hello World!"
app:layout_constraintEnd_toStartOf="@+id/tv3"
app:layout_constraintHorizontal_weight="2"
app:layout_constraintStart_toEndOf="@+id/tv1"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv3"
android:layout_width="0dp"
android:layout_height="50dp"
android:background="#f186ad"
android:gravity="center"
android:text="Hello World!"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@+id/tv2"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv4"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#03A9F4"
android:gravity="center"
android:text="Hello World!"
app:layout_constraintBottom_toTopOf="@id/tv5"
app:layout_constraintEnd_toEndOf="@id/tv1"
app:layout_constraintStart_toStartOf="@id/tv1"
app:layout_constraintTop_toBottomOf="@id/tv1"
app:layout_constraintVertical_weight="1" />
<TextView
android:id="@+id/tv5"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#F44336"
android:gravity="center"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@id/tv4"
app:layout_constraintStart_toStartOf="@id/tv4"
app:layout_constraintTop_toBottomOf="@id/tv4"
app:layout_constraintVertical_weight="1" />
</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
Five, the Dimensions
When the width or height of the control is set to 0dp, you can specify the width or height of the control as a percentage of the space of the parent control with two properties ranging from 0 to 1
- layout_constrainWidth_percent
- layout_constrainHeight_percent
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintLayoutActivity">
<Button
android:id="@+id/btn_target"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Target Button"
android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.8" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Source Button"
android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_target"
app:layout_constraintWidth_percent="0.5" />
</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
Sixth, the Visibility
In any other layout, if the View’s visibility property is set to GONE, all other properties that rely on the View to reference and position will be invalidated, and will be different in ConstraintLayout
In the following layout, the red square is in the middle of the rectangle formed by the upper right corner of the screen and the lower left corner of the yellow square
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintLayoutActivity">
<TextView
android:id="@+id/tv1"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#f5ec7e"
android:gravity="center"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv2"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#fa6e61"
android:gravity="center"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="@+id/tv1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/tv1"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
If the yellow cube’s visibility property is set to GONE, the position of the red cube will change. This can be interpreted as the yellow square shrinking to an invisible dot in the middle of its original position, while the red square is changed to be positioned according to that dot
In addition, the red square can also rely on the following properties to control the margin value of the red square when the yellow square is Gone. These properties will only take effect when the visibility property of the yellow square is set to Gone
layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom
Seven, circular positioning
Circular positioning is used to position two views in two dimensions, Angle and distance, with the center of two views as the anchor point
- App :layout_constraintCircle – ID of the target View
- App :layout_constraintCircleAngle – Aligned Angle
- App :layout_constraintCircleRadius – Distance from target View (clockwise, 0~360 degrees)
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintLayoutActivity">
<ImageView
android:id="@+id/iv_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_a"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/iv_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_b"
app:layout_constraintCircle="@id/iv_a"
app:layout_constraintCircleAngle="45"
app:layout_constraintCircleRadius="200dp" />
<ImageView
android:id="@+id/iv_c"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_c"
app:layout_constraintCircle="@id/iv_a"
app:layout_constraintCircleAngle="180"
app:layout_constraintCircleRadius="200dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
Eight, Guideline
Guideline is a subclass of View, used in the same way as regular views, but with the following special properties:
- Width and height are 0
- The visibility is view.gone
The indicator line is meant to help other views locate and does not actually appear on the page
For example, the following code adds two guidelines, and you can choose to set the location of the Guideline using percentage or actual distance, and set the orientation of the Guideline using the orientation property
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintLayoutActivity">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="100dp" />
<TextView
android:id="@+id/tv1"
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#f5ec7e"
android:gravity="center"
android:text="Hello World!"
app:layout_constraintLeft_toRightOf="@+id/guideline1"
app:layout_constraintTop_toBottomOf="@+id/guideline2" />
</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
Set the horizontal indicator line 100dp away from the top, the yellow square according to the indicator line to set the top position. The vertical indicator line sets its horizontal distance percentage to 0.5, so the left side of the yellow square is in the middle of the screen
Nine, the Barrier
Many times the width and height of a control changes according to the amount of data it contains. It is difficult to set the relationship between controls when you have multiple controls that are bound by each other. Barrier, like GuideLine, is a virtual View that is not visible to the interface and is used as an aid to layout
Barrier can use the following properties:
- BarrierDirection: sets the location of the Barrier. The values are bottom, top, start, end, left, and right
- Constraint_referenced_ids: Specifies the ID of the control referenced by the Barrier
- BarrierAllowsGoneWidgets: Defaults to true and creates a Barrier where the control referred to by the Barrier has already been resolved. If set to false, the Gone control is not taken into account
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintLayoutActivity">
<TextView
android:id="@+id/btn_target"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#03A9F4"
android:padding="10dp"
android:text="This is not a very long text."
android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/btn_source"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="# 009688"
android:padding="10dp"
android:text="I don't know what to say."
android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_target" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:barrierAllowsGoneWidgets="false"
app:barrierDirection="end"
app:constraint_referenced_ids="btn_target,btn_source" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#E91E63"
android:padding="10dp"
android:text="Well, just write about it."
android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/barrier"
app:layout_constraintTop_toBottomOf="@id/btn_target" />
</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
The layout file states that the red block must always be to the right of the blue + green block, which is not obvious at this point, but will be as the text increases. When the width of the blue square or the green square increases, the red square automatically moves to the right
Ten, Group
Group is used to control the visibility of multiple controls. Constraint_referenced_ids binds other views, and then indirectly changes the visibility of the bound View by controlling the visibility of the Group separately
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintLayoutActivity">
<Button
android:id="@+id/btn_target"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Target Button"
android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_source"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Source Button"
android:textAllCaps="false"
app:layout_constraintCircle="@id/btn_target"
app:layout_constraintCircleAngle="45"
app:layout_constraintCircleRadius="120dp" />
<androidx.constraintlayout.widget.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible"
app:constraint_referenced_ids="btn_target, btn_source" />
</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
Eleven, Placeholder
Placeholder (Placeholder) Placeholder is associated with a view, which is converted to the specified view by the setContentId() method. That is, the view will be displayed in the Placeholder position, and will disappear from its original position if the view is already in the layout
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintLayoutActivity">
<Button
android:id="@+id/btn_setContentId"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:onClick="setContentId"
android:text="setContentId"
android:textAllCaps="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/iv_target"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_a"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_setContentId" />
<androidx.constraintlayout.widget.Placeholder
android:id="@+id/placeholder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
val placeholder = findViewById<Placeholder>(R.id.placeholder)
placeholder.setContentId(R.id.iv_target)
Copy the code
Twelve, Chains,
Chain is difficult to describe. It is a special form of constraint. Multiple controls restrict each other’s positions through explicit mutual constraints, thus forming a Chain
For example, in the layout below, the three TextViews can be called a chain if they form a whole and all specify constraints on their left and right sides
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintLayoutActivity">
<TextView
android:id="@+id/tv1"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#f5ec7e"
android:gravity="center"
android:text="Hello World!"
app:layout_constraintEnd_toStartOf="@+id/tv2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv2"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_marginTop="0dp"
android:background="#ff538c"
android:gravity="center"
android:text="Hello World!"
app:layout_constraintEnd_toStartOf="@+id/tv3"
app:layout_constraintStart_toEndOf="@+id/tv1"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv3"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#41c0ff"
android:gravity="center"
android:text="Hello World!"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/tv2"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
Chains are divided into horizontal chains and vertical chains, which are set with layout_constraintHorizontal_chainStyle and layout_constraintVertical_chainStyle respectively. The attribute values are as follows:
- Spread (default)
- spread_inside
- packed
It’s easy to understand the effects by looking at them directly
When the value is spread and the control width is wrAP_content
android:layout_width="wrap_content"
app:layout_constraintHorizontal_chainStyle="spread"
Copy the code
When the parameter value is spread and the control width is 0dp
android:layout_width="0dp"
app:layout_constraintHorizontal_chainStyle="spread"
Copy the code
When the parameter value is spread_INSIDE and the control width is wrap_content
android:layout_width="wrap_content"
app:layout_constraintHorizontal_chainStyle="spread_inside"
Copy the code
When the parameter is packed and the control width is WRAP_content
android:layout_width="wrap_content"
app:layout_constraintHorizontal_chainStyle="packed"
Copy the code
13, a Flow
Flow is a new virtual layout designed to create chained typography that wraps automatically when space runs out, or even extends to another area of the screen. Flow is useful when you need to chain layout multiple elements, but are not sure what the actual size of the layout space is at run time. You can use Flow to dynamically adapt your layout to changes in the screen size of your application, such as screen width changes as the device rotates. In addition, Flow is a virtual layout and is not added as a view to the view hierarchy, but merely refers to other views to assist them in performing their layout functions in the layout system
One of the most important configuration options in Flow is wrapMode, which determines the layout behavior in case of overflow (or line breaks). There are three modes:
- None – All referenced views are laid out in a chain, and if the content overflows, the overflow content is not visible
- Chain – When an overflow occurs, the spilled content is wrapped in a new chain layout
- Align – similar to chain, but laid out in columns instead of rows
For example, you could include five cardViews in your layout file, and the orientation constraint of each CardView is controlled by the Flow. The Flow is displayed horizontally by default, and you could actively set android:orientation=”vertical” to vertical
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FlowActivity">
<include
android:id="@+id/cardView1"
layout="@layout/item_cardview" />
<include
android:id="@+id/cardView2"
layout="@layout/item_cardview" />
<include
android:id="@+id/cardView3"
layout="@layout/item_cardview" />
<include
android:id="@+id/cardView4"
layout="@layout/item_cardview" />
<include
android:id="@+id/cardView5"
layout="@layout/item_cardview" />
<androidx.constraintlayout.helper.widget.Flow
android:id="@+id/flow"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:constraint_referenced_ids="cardView1,cardView2,cardView3,cardView4,cardView5"
app:flow_horizontalGap="30dp"
app:flow_verticalGap="30dp"
app:flow_wrapMode="none"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
none
In this mode, the control does not wrap itself, and only part of the content is displayed because the screen width cannot be fully displayed
The following configuration items can be used simultaneously in this mode:
- Flow_horizontalStyle = “spread | spread_inside | the packed” / / Chains chain form of show
- flow_verticalStyle = “spread|spread_inside|packed”
- flow_horizontalBias = “float“// This controls the horizontal offset of the control only when style is packed
- flow_verticalBias = “float“
- flow_horizontalGap = “dimension“// Sets the left and right spacing for each control
- flow_verticalGap = “dimension“
- flow_horizontalAlign = “start|end”
- flow_verticalAlign = “top|bottom|center|baseline
chain
In this mode, the control is automatically wrapped and content that is less than one line is centered
The following configuration items can be used simultaneously in this mode:
- Flow_firstHorizontalStyle = “spread | spread_inside | the packed” / / the first row Chains chain form of show
- flow_firstVerticalStyle = “spread|spread_inside|packed”
- flow_firstHorizontalBias = “float“// This controls the horizontal offset of the first row only when style is packed
- flow_firstVerticalBias = “float“
- Flow_lastHorizontalStyle = “spread | spread_inside | the packed” / / the last row Chains chain form of show
- flow_lastHorizontalBias = “float“
Here’s an example:
<androidx.constraintlayout.helper.widget.Flow
android:id="@+id/flow"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:constraint_referenced_ids="cardView1,cardView2,cardView3,cardView4,cardView5"
app:flow_firstHorizontalStyle="spread_inside"
app:flow_horizontalGap="30dp"
app:flow_lastHorizontalBias="1"
app:flow_lastHorizontalStyle="packed"
app:flow_verticalGap="30dp"
app:flow_wrapMode="chain"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Copy the code
Because flow_firstHorizontalStyle has the value spread_inside, the first row moves to the side. Since flow_lastHorizontalBias is 1, the last line is also drawn directly to the right
aligned
This pattern is similar to chain, except that less than one line of content is displayed aligned to the side
14, Layer
Layer, as a new auxiliary tool, can create a virtual Layer on multiple views. Unlike Flow, it does not layout views, but simultaneously transforms multiple views. If you want to rotate, translate, or scale multiple views as a whole, Layer is the best choice
In the layout file, all views that need to be transformed are referred to by Layer first, without position constraints on Layer
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".LayerActivity">
<TextView
android:id="@+id/tv1"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#f5ec7e"
android:gravity="center"
android:text="Hello World!"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv2"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#FF9800"
android:gravity="center"
android:text="Hello World!"
app:layout_constraintStart_toEndOf="@id/tv1"
app:layout_constraintTop_toBottomOf="@id/tv1" />
<TextView
android:id="@+id/tv3"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#2196F3"
android:gravity="center"
android:text="Hello World!"
app:layout_constraintStart_toEndOf="@id/tv2"
app:layout_constraintTop_toBottomOf="@id/tv2" />
<androidx.constraintlayout.helper.widget.Layer
android:id="@+id/layer"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="tv1, tv2, tv3"
tools:ignore="MissingConstraints" />
<Button
android:id="@+id/btn_test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20dp"
android:text="Animate"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
The Layer is then animated directly in the code so that all views referenced to it are fully animated
/ * * *@Author: leavesC
* @Date: 2020/12/26 22:06
* @Desc:
* @Github: https://github.com/leavesC * /
class LayerActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_layer)
btn_test.setOnClickListener {
val layer = findViewById<Layer>(R.id.layer)
val animator = ValueAnimator.ofFloat(0f.360f)
animator.addUpdateListener { animation ->
val angle = animation.animatedValue as Float
layer.rotation = angle
layer.scaleX = 1 + (180 - abs(angle - 180)) / 20f
layer.scaleY = 1 + (180 - abs(angle - 180)) / 20f
val translationX = 500 * sin(Math.toRadians((angle * 5).toDouble())).toFloat()
val translationY = 500 * sin(Math.toRadians((angle * 7).toDouble())).toFloat()
layer.translationX = translationX
layer.translationY = translationY
}
animator.duration = 6000
animator.start()
}
}
}
Copy the code
In addition, a useful point of Layer is that it can be used to set the background color. In the past, if we want to set a background color for a certain area, we often need to nest one more Layer, but if we use Layer, we can set it directly without nesting
15 and ConstraintSet
Layer animates part of ConstraintLayout, and ConstraintSet animates the entire ConstraintLayout
ConstraintSet can be understood as a collection of constraint rules for all of ConstraintLayout’s child controls. ConstraintLayout is used to smoothly change the position of all the child controls within ConstraintLayout, which requires a major adjustment depending on the interaction rules
For example, if you need to use two different layouts in different scenarios, define the layout files so that the ids of the sub-views remain the same and the constraints of the views can be set arbitrarily. ConstraintSet is then used to load the constraint rules for the two layout files in code, and apply to ConstraintLayout to smoothly switch between the two layout effects
/ * * *@Author: leavesC
* @Date: 2020/12/26 23:02
* @Desc:
* @Github: https://github.com/leavesC * /
class ConstraintSetActivity : AppCompatActivity() {
companion object {
private const val SHOW_BIG_IMAGE = "showBigImage"
}
private var showBigImage = false
private val constraintSetNormal = ConstraintSet()
private val constraintSetBig = ConstraintSet()
override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_constraint_set)
// Get the initial constraint set
constraintSetNormal.clone(cl_rootView)
// Load the target constraint set
constraintSetBig.load(this, R.layout.activity_constraint_set_big)
if(savedInstanceState ! =null) {
val previous = savedInstanceState.getBoolean(SHOW_BIG_IMAGE)
if(previous ! = showBigImage) { showBigImage = previous applyConfig() } } }override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putBoolean(SHOW_BIG_IMAGE, showBigImage)
}
fun toggleMode(view: View){ TransitionManager.beginDelayedTransition(cl_rootView) showBigImage = ! showBigImage applyConfig() }// Apply the constraint set to the control
private fun applyConfig(a) {
if (showBigImage) {
constraintSetBig.applyTo(cl_rootView)
} else {
constraintSetNormal.applyTo(cl_rootView)
}
}
}
Copy the code
16, ConstraintHelper
Flow and Layer are subclasses of ConstraintHelper, which is a layout aid utility class. ConstraintLayout also opens up ConstraintHelper to the developer
For example, we can implement an animation that unfolds gradually
Inherit ConstraintHelper, iterate through all the controls it references in the updatePostLayout method, and then apply the CircularReveal animation to each control. The updatePostLayout method is called before onLayout is executed
/ * * *@Author: leavesC
* @Date: 2020/12/26 company *@Desc:
* @Github: https://github.com/leavesC * /
class CircularRevealHelper @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ConstraintHelper(context, attrs, defStyleAttr) {
override fun updatePostLayout(container: ConstraintLayout) {
super.updatePostLayout(container)
val views = getViews(container)
for (view in views) {
val anim = ViewAnimationUtils.createCircularReveal(
view, view.width / 2,
view.height / 2.0f,
hypot((view.height / 2).toDouble(), (view.width / 2).toDouble()).toFloat()
)
anim.duration = 3000
anim.start()
}
}
}
Copy the code
Just reference the View that you want to animate in the layout file
<? xml version="1.0" encoding="utf-8"? > <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintHelperActivity">
<ImageView
android:id="@+id/imageView"
android:layout_width="300dp"
android:layout_height="300dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/icon_avatar" />
<github.leavesc.constraint_layout.CircularRevealHelper
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="imageView"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
In the 17th and ImageFilterView
ImageFilterView is a View placed in the utils.widget package of ConstraintLayout. From the package name, we can guess that ImageFilterView is an additional tool attribute class provided by Google. ConstraintLayout has nothing to do with ConstraintLayout itself
ImageFilterView directly inherits from AppCompatImageView, which extends many functions for implementing graphics transformation
attribute | meaning |
---|---|
altSrc | Used to specify the target image to be converted from SRC. You can use the crossfade to fade in and out |
crossfade | Sets the degree of blending between SRC and altSrc images. 0 = SRC = 1 altSrc images |
saturation | Saturation. 0= gray scale, 1= original, 2= supersaturated |
brightness | Brightness. 0= black, 1= raw, 2= double brightness |
warmth | Color temperature. 1= natural, 2= warm, 0.5= cool |
contrast | Contrast. 1= constant, 0= gray, 2= high contrast |
round | Used to implement rounded corners, with dimension as the value |
roundPercent | The value ranges from 0F to 1f. If the value is 1F, a circular picture will be formed |
Let’s look at an example. Declare multiple ImagefilterViews in XML
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ImageFilterViewActivity">
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="@+id/imageView1"
android:layout_width="100dp"
android:layout_height="100dp"
app:layout_constraintEnd_toStartOf="@id/imageView2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/icon_avatar_normal" />// omit other imagefilterViews<androidx.appcompat.widget.AppCompatSeekBar
android:id="@+id/seekBar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:max="100"
android:progress="0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
Adjust the above property values in your code
/ * * *@Author: leavesC
* @Date: 2020/12/27 0:17
* @Desc:
* @Github: https://github.com/leavesC * /
class ImageFilterViewActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_image_filter_view)
seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if (fromUser) {
val realProgress = (progress / 100.0).toFloat()
imageView1.saturation = realProgress * 20
imageView2.brightness = 1 - realProgress
imageView3.warmth = realProgress * 20
imageView4.contrast = realProgress * 2
imageView5.round = realProgress * 40
imageView6.roundPercent = realProgress
imageView7.crossfade = realProgress
}
}
override fun onStartTrackingTouch(seekBar: SeekBar?).{}override fun onStopTrackingTouch(seekBar: SeekBar?).{}})}}Copy the code
18. Demo Download
Example code I have put on Github, please check: AndroidOpenSourceDemo
19. Reference materials
- Developer. The android. Google. Cn/reference/a…
- Juejin. Cn/post / 690521…