본문 바로가기
안드로이드 자바

[Android][Java] ConstraintSet클래스를 사용해 Chain Weight 유동적으로 변경하기

by teamnova 2023. 5. 28.

오늘 만들 예제에서 사용할 클래스는 ConstraintSet입니다.

 

ConstraintSet은 ConstraintLayout 라이브러리에서 사용되는 클래스로 먼저 ConstraintLayout이 뭔지 간단하게 알아보겠습니다.

 

ConstraintLayout은 안드로이드에서 사용하는 여러 레이아웃 중 하나로 레이아웃 구성 시 드래그앤드롭 기능과 Constraint를 사용해 유연하게 View를 배치할 수 있는 장점이 있습니다, 또 Chain기능을 사용해서 각 View들을 연결해 스마트폰에 크기와 상관없이 대응할 수 있는 화면도 구성할 수 있죠.

 

위 사진처럼 Constraint라는 제약을 사용해 모든 View들은 최소 가로 와 세로 각 1개씩 제약을 설정해야하며 이 제약을 통해 각 View의 위치를 조정할 수 있습니다.

 

위 사진은 Chain 기능에 관련된 사진으로 위와 같이 Chain으로 View들을 연결해 간격이나 배치등을 어떻게 할 지 설정할 수 있고 각 View의 크기 비중 또한 유동적으로 설정할 수 있습니다.

 

이런 ConstraintLayout의 제약와 Chain을 동적으로 설정하고 수정하는데 사용되는 클래스가 ConstraintSet입니다.

예를 들어 다른 레이아웃 요소와의 상대적인 위치, 크기, 간격 등을 제어할 수 있습니다.

 

그 중 저희는 오늘 ConstraintLayout을 사용할 때 각 View들을 연결할 때 쓰는 Horizontal Chain의 Horizontal Weight를 유동적으로 변경하는 예제를 해보겠습니다

 

activity_main.xml

<?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:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintHorizontal_weight="1"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#FF0000"
        app:layout_constraintBottom_toTopOf="@+id/imageView3"
        app:layout_constraintEnd_toStartOf="@+id/imageView2"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_weight="1"
        app:srcCompat="@drawable/ic_launcher_foreground" />

    <ImageView
        android:id="@+id/imageView4"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#00FF0A"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toEndOf="@+id/imageView3"
        app:layout_constraintTop_toBottomOf="@+id/imageView2"
        app:layout_constraintVertical_weight="1"
        app:srcCompat="@drawable/ic_launcher_foreground" />

    <ImageView
        android:id="@+id/imageView3"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#FFE500"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/imageView4"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView1"
        app:layout_constraintVertical_weight="1"
        app:srcCompat="@drawable/ic_launcher_foreground" />

    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#0027FF"
        app:layout_constraintBottom_toTopOf="@+id/imageView4"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toEndOf="@+id/imageView1"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_weight="1"
        app:srcCompat="@drawable/ic_launcher_foreground" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

MainActivity.java

import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;

import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

    ConstraintLayout root; // 변경할 ConstraintLayout

    ImageView img1; // 죄측 상단 이미지 1번
    ImageView img2; // 우측 상단 이미지 2번
    ImageView img3; // 좌측 하단 이미지 3번
    ImageView img4; // 우측 하단 이미지 4번

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 변경할 ConstraintLayout 초기화
        root = (ConstraintLayout)findViewById(R.id.root);

        // 이미지 변수 초기화
        img1 = (ImageView) findViewById(R.id.imageView1);
        img2 = (ImageView) findViewById(R.id.imageView2);
        img3 = (ImageView) findViewById(R.id.imageView3);
        img4 = (ImageView) findViewById(R.id.imageView4);

        // 현재 상태를 파악하기 위해 ImageView 변수에 tag 등록
        // 태그에 등록된 문자열은 해당 ImageView에 HorizontalWeight 표시
        img1.setTag("1");
        img2.setTag("1");
        img3.setTag("1");
        img4.setTag("1");

        // OnClickListener 객체 생성
        OnClickListener onClickListener = new OnClickListener();

        // 각 ImageView에 onclickListener를 등록
        img1.setOnClickListener(onClickListener);
        img2.setOnClickListener(onClickListener);
        img3.setOnClickListener(onClickListener);
        img4.setOnClickListener(onClickListener);

    }

    class OnClickListener implements View.OnClickListener {

        @Override
        public void onClick(View view) {
            switch (view.getId()){
                case R.id.imageView1:
                    // img1을 클릭했을 때
                    if(img1.getTag().equals("1")){
                        // 현재 img1의 HorizontalWeight가 1이면 2로 변경
                        setConstraintWeight(1, 2);
                    }else{
                        // 현재 img1의 HorizontalWeight가 2면 1로 변경
                        setConstraintWeight(1, 1);
                    }
                    break;
                case R.id.imageView2:
                    // img2을 클릭했을 때
                    if(img2.getTag().equals("1")){
                        setConstraintWeight(2, 2);
                    }else{
                        setConstraintWeight(2, 1);
                    }
                    break;
                case R.id.imageView3:
                    // img3을 클릭했을 때
                    if(img3.getTag().equals("1")){
                        setConstraintWeight(3, 2);
                    }else{
                        setConstraintWeight(3, 1);
                    }
                    break;
                case R.id.imageView4:
                    // img4을 클릭했을 때
                    if(img4.getTag().equals("1")){
                        setConstraintWeight(4, 2);
                    }else{
                        setConstraintWeight(4, 1);
                    }
                    break;
            }
        }
    }

    // constraintweight를 변경하는 메소드
    // 첫번째 매개변수는 몇번째 ImageView인지 구분
    // 두번째 매개변수는 변경할 HorizontalWeight 크기
    void setConstraintWeight(int imgNumber, int weight){
        // ConstraintLayout의 각 View의 Constraints를 유동적으로 변경하기 위해 사용하는 클래스
        ConstraintSet set = new ConstraintSet();
        set.clone(root); // 매개 변수로 받은 ConstraintLayout의 복사해 클론으로 만듬
        if(imgNumber == 1){
            // 1번 이미지의 태그를 변경하고 HorizontalWeight를 변경
            img1.setTag(String.valueOf(weight));
            set.setHorizontalWeight(img1.getId(), weight);
        }else if(imgNumber == 2){
            // 2번 이미지의 태그를 변경하고 HorizontalWeight를 변경
            img2.setTag(String.valueOf(weight));
            set.setHorizontalWeight(img2.getId(), weight);
        }else if(imgNumber == 3){
            // 3번 이미지의 태그를 변경하고 HorizontalWeight를 변경
            img3.setTag(String.valueOf(weight));
            set.setHorizontalWeight(img3.getId(), weight);
        }else{
            // 4번 이미지의 태그를 변경하고 HorizontalWeight를 변경
            img4.setTag(String.valueOf(weight));
            set.setHorizontalWeight(img4.getId(), weight);
        }
        // 변경 사항이 적용된 클론을 다시 기존 ConstraintLayout에 적용
        set.applyTo(root);
    }

}

 

각 이미지를 클릭할 때마다 해당 ImageView의 Horizontal Weight가 1이면 2로 변경되고 2면 1로 변경되는 예제가 완성되었습니다.