ConstraintLayout으로 반응형 UI 빌드 Android Jetpack의 구성요소

Compose 방법 사용해 보기
Jetpack Compose는 Android에 권장되는 UI 도구 키트입니다. Compose에서 레이아웃을 사용하는 방법을 알아보세요.

ConstraintLayout를 사용하면 중첩된 뷰 그룹이 없는 플랫 뷰 계층 구조로 크고 복잡한 레이아웃을 만들 수 있습니다. 이 클래스는 모든 뷰가 동위 뷰와 상위 레이아웃 간의 관계에 따라 배치된다는 점에서 RelativeLayout와 비슷하지만 RelativeLayout보다 유연하고 Android 스튜디오의 Layout Editor와 함께 사용하기가 더 쉽습니다.

Layout API와 Layout Editor가 서로를 위해 특별히 빌드되었기 때문에 Layout Editor의 시각적 도구에서 직접 ConstraintLayout의 모든 기능을 사용할 수 있습니다. XML을 수정하는 대신 드래그하여 완전히 ConstraintLayout로 레이아웃을 빌드할 수 있습니다.

이 페이지에서는 Android 스튜디오 3.0 이상에서 ConstraintLayout를 사용하여 레이아웃을 빌드하는 방법을 보여줍니다. Layout Editor에 관한 자세한 내용은 Layout Editor로 UI 빌드를 참고하세요.

ConstraintLayout로 만들 수 있는 다양한 레이아웃을 보려면 GitHub의 제약조건 레이아웃 예시 프로젝트를 참고하세요.

제약조건 개요

ConstraintLayout에서 뷰의 위치를 정의하려면 뷰에 가로 및 세로 제약 조건을 각각 하나 이상 추가합니다. 각 제약 조건은 다른 뷰, 상위 요소 레이아웃 또는 표시되지 않는 가이드라인과의 연결 또는 정렬을 나타냅니다. 각 제약 조건은 세로 또는 가로축을 따라 뷰의 위치를 정의합니다. 각 뷰에는 각 축에 최소 하나의 제약조건이 있어야 하지만 더 많은 제약조건이 필요한 경우가 많습니다.

뷰를 Layout Editor에 드롭하면 제약 조건이 없더라도 그대로 둡니다. 이렇게 하면 편집을 더 쉽게 할 수 있습니다. 기기에서 레이아웃을 실행할 때 뷰에 제약 조건이 없으면 뷰가 왼쪽 상단 [0,0]에 그려집니다.

그림 1에서는 편집기에서 레이아웃이 정상적으로 표시되지만 뷰 C에는 세로 제약 조건이 없습니다. 이 레이아웃을 기기에 그릴 때 뷰 C는 뷰 A의 왼쪽과 오른쪽 가장자리에 가로로 정렬되지만 세로 제약 조건이 없으므로 화면 상단에 표시됩니다.

그림 1. 편집기에 뷰 C가 A 아래에 표시되지만 세로 제약조건이 없습니다.

그림 2. 이제 보기 C는 보기 A 아래에 세로로 제한됩니다.

제약 조건 누락으로 컴파일 오류가 발생하지는 않지만 Layout Editor에서는 누락된 제약 조건을 툴바에 오류로 표시합니다. 오류 및 기타 경고를 보려면 Show Warnings and errors 를 클릭합니다. 제약 조건이 누락되지 않도록 Layout Editor에서는 자동 연결 및 제약 조건 추론 기능을 사용하여 제약 조건을 자동으로 추가합니다.

ConstraintLayout을 프로젝트에 추가

프로젝트에서 ConstraintLayout를 사용하려면 다음 단계를 진행하세요.

  1. settings.gradle 파일에 선언된 maven.google.com 저장소가 있는지 확인합니다.

    Groovy

        dependencyResolutionManagement {
          ...
          repositories {
              google()
          }
        )
        

    Kotlin

        dependencyResolutionManagement {
          ...
          repositories {
              google()
          }
        }
        
  2. 다음 예와 같이 모듈을 모듈 수준 build.gradle 파일에 종속 항목으로 추가합니다. 최신 버전은 다음 예에 표시된 것과 다를 수 있습니다.

    Groovy

    dependencies {
        implementation "androidx.constraintlayout:constraintlayout:2.2.0-alpha13"
        // To use constraintlayout in compose
        implementation "androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha13"
    }
    

    Kotlin

    dependencies {
        implementation("androidx.constraintlayout:constraintlayout:2.2.0-alpha13")
        // To use constraintlayout in compose
        implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha13")
    }
    
  3. 툴바 또는 동기화 알림에서 Sync Project with Gradle Files를 클릭합니다.

이제 ConstraintLayout으로 레이아웃을 빌드할 준비가 되었습니다.

레이아웃 변환

그림 3. 레이아웃을 ConstraintLayout로 변환하는 메뉴

기존 레이아웃을 제약조건 레이아웃으로 변환하려면 다음 단계를 따르세요.

  1. Android 스튜디오에서 레이아웃을 열고 편집기 창 하단에 있는 Design 탭을 클릭합니다.
  2. Component Tree 창에서 레이아웃을 마우스 오른쪽 버튼으로 클릭하고 Convert LinearLayout to ConstraintLayout을 클릭합니다.

새 레이아웃 생성

새 제약조건 레이아웃 파일을 시작하려면 다음 단계를 따르세요.

  1. Project 창에서 모듈 폴더를 클릭하고 File > New > XML > Layout XML을 선택합니다.
  2. 레이아웃 파일의 이름을 입력하고 Root Tag에 'androidx.constraintlayout.widget.ConstraintLayout'을 입력합니다.
  3. Finish를 클릭합니다.

제약조건 추가 또는 삭제

제약조건을 추가하려면 다음 단계를 따르세요.

동영상 1. 뷰의 왼쪽은 상위 요소의 왼쪽으로 제한됩니다.

  1. Palette 창에서 편집기로 보기를 드래그합니다.

    ConstraintLayout에 뷰를 추가하면 각 모서리에 정사각형 크기 조절 핸들과 각 측면에 원형 제약 조건 핸들이 있는 경계 상자에 표시됩니다.

  2. 보기를 클릭하여 선택합니다.
  3. 다음 중 한 가지 방법을 사용합니다.
    • 제약조건 핸들을 클릭하여 사용 가능한 앵커 포인트로 드래그합니다. 이 지점은 다른 보기의 가장자리, 레이아웃의 가장자리 또는 안내선일 수 있습니다. 제약 조건 핸들을 드래그하면 Layout Editor에 잠재적 연결 앵커와 파란색 오버레이가 표시됩니다.
    • 그림 4와 같이 Attributes 창의 Layout 섹션에서 Create a connection 버튼 중 하나를 클릭합니다.

      그림 4. Attributes 창의 Layout 섹션을 사용하여 연결을 만들 수 있습니다.

제약 조건이 생성되면 편집기에서 기본 여백을 부여하여 두 뷰를 구분합니다.

제약조건을 만들 때 다음 규칙을 기억하세요.

  • 모든 뷰에는 가로와 세로 하나라는 두 개 이상의 제약 조건이 있어야 합니다.
  • 동일한 평면을 공유하는 제약 조건 핸들과 앵커 포인트 간에만 제약 조건을 만들 수 있습니다. 보기의 세로 평면(왼쪽 및 오른쪽)은 다른 세로 평면으로만 제한될 수 있으며 기준은 다른 기준으로만 제한될 수 있습니다.
  • 각 제약조건 핸들은 하나의 제약조건에만 사용할 수 있지만 여러 뷰에서 동일한 앵커 포인트에 여러 제약 조건을 만들 수 있습니다.

다음 중 하나를 실행하여 제약조건을 삭제할 수 있습니다.

  • 제약조건을 클릭하여 선택한 다음 삭제를 클릭합니다.
  • 제약 조건 앵커를 Control 키를 누른 상태에서 클릭합니다 (macOS의 경우 Command 키를 누른 상태에서 클릭). 그림 5와 같이 제약조건이 빨간색으로 바뀌어 클릭하여 삭제할 수 있음을 나타냅니다.

    그림 5. 빨간색 제약조건은 클릭하여 삭제할 수 있음을 나타냅니다.

  • Attributes 창의 Layout 섹션에서 그림 6과 같이 제약 조건 앵커를 클릭합니다.

    그림 6. 제약조건 앵커를 클릭하여 삭제합니다.

동영상 2. 기존 제약조건에 반대되는 제약조건 추가

뷰에 반대되는 제약 조건을 추가하면 제약 조건 선이 스프링처럼 감겨 있어 동영상 2와 같이 반대 힘을 나타냅니다. 이 효과는 뷰 크기가 '고정' 또는 '콘텐츠 래핑'으로 설정될 때 가장 잘 나타납니다. 이 경우 뷰는 제약 조건 사이의 중앙에 배치됩니다. 대신 제약 조건에 맞게 뷰 크기를 늘리려면 '제약조건과 일치'하도록 크기를 전환합니다. 현재 크기를 유지하되 뷰가 중앙에 오지 않도록 이동하려면 제약조건 편향을 조정하세요.

다음 섹션에 설명된 대로 제약조건을 사용하여 다양한 유형의 레이아웃 동작을 실행할 수 있습니다.

상위 요소 포지셔닝

뷰의 측면을 레이아웃의 상응하는 가장자리로 제한합니다.

그림 7에서 뷰의 왼쪽은 상위 요소 레이아웃의 왼쪽 가장자리에 연결됩니다. 여백을 사용하여 가장자리로부터의 거리를 정의할 수 있습니다.

그림 7. 상위 요소에 대한 가로 제약 조건입니다.

위치 순서 지정

두 뷰의 표시 순서를 세로 또는 가로로 정의합니다.

그림 8에서 B는 항상 A의 오른쪽에 있도록 제한되고 C는 A 아래 있도록 제한됩니다. 그러나 이러한 제약 조건은 정렬을 의미하지 않으므로 B는 계속 위아래로 이동할 수 있습니다.

그림 8. 가로 및 세로 제약 조건

정렬

보기의 가장자리를 다른 보기의 가장자리에 맞게 정렬합니다.

그림 9에서 B의 왼쪽은 A의 왼쪽에 맞게 정렬됩니다. 뷰 중심을 정렬하려면 양쪽에 제약 조건을 만듭니다.

제약 조건에서 안쪽으로 뷰를 드래그하여 정렬을 오프셋할 수 있습니다. 예를 들어 그림 10에서는 24dp 오프셋 정렬을 사용하는 B를 보여줍니다. 오프셋은 제한된 뷰의 여백으로 정의됩니다.

정렬할 뷰를 모두 선택한 다음 툴바에서 Align 을 클릭하여 정렬 유형을 선택할 수도 있습니다.

그림 9. 가로 정렬 제약조건.

그림 10. 오프셋 가로 정렬 제약조건.

기준선 정렬

보기의 텍스트 기준선을 다른 보기의 텍스트 기준선에 맞춥니다.

그림 11에서 B의 첫 번째 줄은 A의 텍스트에 맞게 정렬됩니다.

기준선 제약조건을 만들려면 제한할 텍스트 뷰를 마우스 오른쪽 버튼으로 클릭한 다음 Show Baseline을 클릭합니다. 그런 다음 텍스트 기준선을 클릭하고 선을 다른 기준선으로 드래그합니다.

그림 11. 기준 정렬 제약조건

안내선으로 제한

뷰를 제한하고 앱 사용자에게는 표시되지 않도록 세로 또는 가로 가이드라인을 추가할 수 있습니다. dp 단위 또는 레이아웃 가장자리를 기준으로 한 백분율에 따라 레이아웃 내에 가이드라인을 배치할 수 있습니다.

안내선을 만들려면 툴바에서 Guidelines 를 클릭한 다음 Add Vertical Guideline 또는 Add Horizontal Guideline을 클릭합니다.

점선을 드래그하여 위치를 조정하고 안내선 가장자리의 원을 클릭하여 측정 모드를 전환합니다.

그림 12. 안내선으로 제한된 뷰

경계선으로 제한

안내선과 마찬가지로 경계선은 뷰를 제한할 수 있는 보이지 않는 선입니다. 단, 경계선이 자체 위치를 정의하지는 않습니다. 대신 경계선 위치는 포함된 뷰의 위치에 따라 이동합니다. 이 방법은 하나의 특정 뷰가 아닌 일련의 뷰로 뷰를 제한하려는 경우에 유용합니다.

예를 들어, 그림 13에서 뷰 C는 경계선의 오른쪽으로 제한됩니다. 경계선은 보기 A와 보기 B의 '끝' (또는 왼쪽에서 오른쪽 레이아웃에서는 오른쪽)으로 설정됩니다. 경계선은 뷰 A의 오른쪽 또는 뷰 B의 오른쪽 중 맨 오른쪽에 있는지에 따라 이동합니다.

경계선을 만들려면 다음 단계를 따르세요.

  1. 툴바에서 Guidelines 를 클릭한 후 Add Vertical Barrier 또는 Add Horizontal Barrier를 클릭합니다.
  2. Component Tree 창에서 경계선 내부의 원하는 보기를 선택하여 경계선 구성요소로 드래그합니다.
  3. Component Tree에서 경계선을 선택하고 Attributes 창을 연 다음 barrierDirection을 설정합니다.

이제 다른 보기에서 경계선으로의 제약조건을 만들 수 있습니다.

경계선 내부의 뷰를 경계선으로 제한할 수도 있습니다. 이렇게 하면 어느 뷰가 가장 길거나 가장 높은지 모르더라도 경계선에 있는 모든 뷰를 서로 정렬할 수 있습니다.

경계선의 '최소' 위치를 보장하기 위해 경계선 내부에 안내선을 포함할 수도 있습니다.

그림 13. 뷰 C는 뷰 A와 뷰 B의 위치와 크기에 따라 이동하는 배리어로 제한됩니다.

제약조건 편향 조정

뷰의 양쪽에 제약 조건을 추가하고 동일한 크기의 뷰 크기가 '고정' 또는 '콘텐츠 래핑'이면 뷰가 두 제약 조건 사이의 중앙에 배치되며 기본적으로 편향은 50% 입니다. 동영상 3과 같이 Attributes 창에서 편향 슬라이더를 드래그하거나 뷰를 드래그하여 편향을 조정할 수 있습니다.

대신 제약 조건에 맞게 보기의 크기를 늘리려면 '제약조건과 일치'하도록 크기를 전환합니다.

동영상 3. 제약조건 편향 조정

보기 크기 조정

그림 14. 뷰를 선택하면 Attributes 창에는 크기 비율 1, 제약 조건 삭제 2, 높이 또는 너비 모드 3, 여백 4, 제약 조건 바이어스 5에 관한 컨트롤이 포함됩니다. 6 제약 조건 목록에서 제약 조건을 클릭하여 Layout Editor에서 개별 제약 조건을 강조 표시할 수도 있습니다.

모서리 핸들을 사용하여 뷰 크기를 조절할 수 있지만 그러면 크기가 하드코딩됩니다. 즉, 뷰는 다른 콘텐츠나 화면 크기에 맞게 크기가 조절되지 않습니다. 다른 크기 조정 모드를 선택하려면 뷰를 클릭하고 편집기의 오른쪽에 있는 Attributes 창을 엽니다.

Attributes 창 상단에는 뷰 검사기가 있습니다. 여기에는 그림 14와 같이 여러 레이아웃 속성의 컨트롤이 포함되어 있습니다. 이 기능은 제약 조건 레이아웃의 뷰에만 사용할 수 있습니다.

그림 14에서 설명선 3으로 표시된 기호를 클릭하여 높이와 너비를 계산하는 방법을 변경할 수 있습니다. 이러한 기호는 다음과 같이 크기 모드를 나타냅니다. 기호를 클릭하여 다음 설정 간에 전환합니다.

  • 고정: 다음 텍스트 상자에서 특정 크기를 지정하거나 편집기에서 뷰 크기를 조절합니다.
  • 콘텐츠 래핑: 보기가 콘텐츠에 맞게 필요한 만큼만 확장됩니다.
    • layout_constraintWidth
    • 가로 크기가 제약 조건을 따르도록 변경하려면 true로 설정합니다. 기본적으로 WRAP_CONTENT로 설정된 위젯은 제약 조건으로 제한되지 않습니다.

  • Match Constraints: 뷰의 여백을 고려한 후 뷰가 양쪽의 제약 조건에 맞게 최대한 크게 확장됩니다. 그러나 다음 속성과 값을 사용하여 동작을 수정할 수 있습니다. 다음 속성은 보기 너비를 '제약조건과 일치'로 설정한 경우에만 적용됩니다.
    • layout_constraintWidth_min

      보기의 최소 너비에 dp 측정기준을 사용합니다.

    • layout_constraintWidth_max

      보기의 최대 너비에 dp 측정기준을 사용합니다.

    그러나 지정된 측정기준에 제약 조건이 하나만 있으면 보기가 콘텐츠에 맞게 확장됩니다. 높이 또는 너비로 이 모드를 사용하면 크기 비율을 설정할 수도 있습니다.

크기를 비율로 설정

그림 15. 뷰는 높이의 비율을 기준으로 너비가 16:9의 가로세로 비율로 설정됩니다.

하나 이상의 뷰 크기가 '제약조건과 일치' (0dp)로 설정된 경우 뷰 크기를 16:9와 같은 비율로 설정할 수 있습니다. 비율을 사용 설정하려면 가로세로 비율 제약 조건 전환 (그림 14의 1 참조)을 클릭하고 표시되는 입력에 width:height 비율을 입력합니다.

너비와 높이가 모두 '제약조건과 일치'로 설정된 경우 Toggle Aspect Ratio Constraint를 클릭하여 다른 측정기준의 비율을 기반으로 할 측정기준을 선택할 수 있습니다. 뷰 검사기에서는 상응하는 가장자리를 실선으로 연결하여 비율로 설정할 측정기준을 나타냅니다.

예를 들어 양쪽을 '제약조건과 일치'로 설정했다면 Toggle Aspect Ratio Constraint를 두 번 클릭하여 너비가 높이의 비율이 되도록 설정합니다. 전체 크기는 뷰의 높이로 결정되며 이는 그림 15와 같이 어떤 방식으로든 정의할 수 있습니다.

보기 여백 조정

뷰를 균일한 간격으로 만들려면 툴바에서 Margin 을 클릭하여 레이아웃에 추가하는 각 뷰의 기본 여백을 선택합니다. 기본 여백을 변경하면 이후에 추가하는 보기에만 적용됩니다.

각 제약조건을 나타내는 줄의 숫자를 클릭하여 Attributes 창에서 각 뷰의 여백을 제어할 수 있습니다. 그림 14에서 콜아웃 4는 하단 여백이 16dp로 설정되어 있음을 보여줍니다.

그림 16. 툴바의 Margin 버튼

도구에서 제공하는 모든 여백은 뷰가 Material Design의 8dp 정사각형 그리드 권장사항에 맞게 정렬되는 데 도움이 되는 8dp의 인수입니다.

체인이 있는 선형 그룹 제어

그림 17. 두 개의 보기가 있는 가로 체인.

체인은 양방향 위치 제약 조건으로 서로 연결된 뷰 그룹입니다. 체인 내의 보기는 세로 또는 가로로 분산될 수 있습니다.

그림 18. 각 체인 스타일의 예

체인 스타일은 다음 방법 중 하나로 지정할 수 있습니다.

  1. 넓히기: 여백을 고려한 후 뷰가 균등하게 분산됩니다. 이는 기본값입니다.
  2. 내부로 확산: 첫 번째 보기와 마지막 보기가 체인의 각 끝에 있는 제약조건에 고정되고 나머지 보기는 균등하게 분산됩니다.
  3. 가중치 적용: 체인이 펼치기 또는 내부에서 넓히기로 설정된 경우 하나 이상의 보기를 '제약조건과 일치' (0dp)하도록 설정하여 남은 공간을 채울 수 있습니다. 기본적으로 '제약조건과 일치'로 설정된 각 보기 간에 공간은 균일하게 분산되지만 layout_constraintHorizontal_weightlayout_constraintVertical_weight 속성을 사용하여 각 보기에 중요도 가중치를 할당할 수 있습니다. 이는 선형 레이아웃layout_weight와 같은 방식으로 작동합니다. 가중치 값이 가장 높은 뷰에 가장 많은 공간이 할당되고 가중치가 동일한 뷰에는 동일한 크기의 공간이 부여됩니다.
  4. 패킹됨: 여백을 고려한 후 뷰가 함께 패킹됩니다. 체인의 '헤드' 뷰 바이어스를 변경하여 체인의 전체 편향(왼쪽 또는 오른쪽 또는 위쪽 또는 아래쪽)을 조정할 수 있습니다.

체인의 '헤드' 뷰(가로 체인의 가장 왼쪽 뷰(왼쪽에서 오른쪽 레이아웃))와 세로 체인의 맨 위에 있는 뷰는 XML에서 체인의 스타일을 정의합니다. 그러나 체인의 뷰를 선택하고 뷰 아래에 표시되는 체인 버튼 을 클릭하여 넓히기, 내부에서 넓히기, 채워짐 간에 전환할 수 있습니다.

체인을 만들려면 동영상 4와 같이 다음 단계를 따르세요.

  1. 체인에 포함할 보기를 모두 선택합니다.
  2. 뷰 중 하나를 마우스 오른쪽 버튼으로 클릭합니다.
  3. 체인점을 선택합니다.
  4. 가로 가운데 중심 또는 세로 중심을 선택합니다.

동영상 4. 가로 체인 만들기

다음은 체인을 사용할 때 고려할 몇 가지 사항입니다.

  • 뷰는 가로 및 세로 체인의 일부가 될 수 있으므로 유연한 그리드 레이아웃을 빌드할 수 있습니다.
  • 그림 14와 같이 체인의 각 끝이 같은 축의 다른 객체로 제한된 경우에만 체인이 올바르게 작동합니다.
  • 체인의 방향이 세로 또는 가로이지만 체인을 사용하면 보기가 해당 방향으로 정렬되지 않습니다. 체인에서 각 뷰의 적절한 위치를 확보하려면 정렬 제약 조건과 같은 다른 제약 조건을 포함합니다.

자동으로 제약조건 만들기

레이아웃에 배치할 때 모든 뷰에 제약 조건을 추가하는 대신 Layout Editor에서 원하는 위치로 각 뷰를 이동한 다음 Infer Constraints 를 클릭하여 제약 조건을 자동으로 생성할 수 있습니다.

Infer Constraints에서는 레이아웃을 스캔하여 모든 뷰에 가장 효과적인 제약 조건 집합을 결정합니다. 뷰를 현재 위치로 제한하면서 유연성을 제공합니다. 다양한 화면 크기와 방향에 맞게 레이아웃이 반응하도록 조정해야 할 수 있습니다.

부모에 자동 연결은 사용 설정할 수 있는 별도의 기능입니다. 이 기능을 사용 설정한 상태에서 상위 뷰에 하위 뷰를 추가하면 뷰를 상위 레이아웃으로 제한하는 것이 적절한 경우에만 레이아웃에 뷰를 추가할 때 이 기능을 통해 각 뷰에 관한 제약 조건이 두 개 이상 자동으로 생성됩니다. 자동 연결은 레이아웃의 다른 뷰에 관한 제약 조건을 생성하지 않습니다.

자동 연결은 기본적으로 사용되지 않습니다. Layout Editor 툴바에서 Enable Autoconnection to Parent 를 클릭하여 사용 설정합니다.

키프레임 애니메이션

ConstraintLayout 내에서 ConstraintSetTransitionManager를 사용하여 요소의 크기와 위치 변경사항을 애니메이션으로 보여줄 수 있습니다.

ConstraintSetConstraintLayout 내에 있는 모든 하위 요소의 제약 조건, 여백, 패딩을 나타내는 경량 객체입니다. 표시된 ConstraintLayoutConstraintSet를 적용하면 레이아웃은 모든 하위 요소의 제약 조건을 업데이트합니다.

ConstraintSet를 사용하여 애니메이션을 빌드하려면 애니메이션의 시작 및 종료 키프레임 역할을 하는 두 개의 레이아웃 파일을 지정합니다. 그런 다음 두 번째 키프레임 파일에서 ConstraintSet를 로드하여 표시된 ConstraintLayout에 적용할 수 있습니다.

다음 코드 예에서는 단일 버튼을 화면 하단으로 이동하는 애니메이션을 보여주는 방법을 보여줍니다.

// MainActivity.kt

fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.keyframe_one)
    constraintLayout = findViewById(R.id.constraint_layout) // member variable
}

fun animateToKeyframeTwo() {
    val constraintSet = ConstraintSet()
    constraintSet.load(this, R.layout.keyframe_two)
    TransitionManager.beginDelayedTransition()
    constraintSet.applyTo(constraintLayout)
}
// layout/keyframe1.xml
// Keyframe 1 contains the starting position for all elements in the animation
// as well as final colors and text sizes.

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
// layout/keyframe2.xml
// Keyframe 2 contains another ConstraintLayout with the final positions.

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

추가 리소스

ConstraintLayoutSunflower 데모 앱에서 사용됩니다.