안드로이드 자바

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

teamnova 2023. 5. 28. 13:00
728x90

오늘 만들 예제에서 사용할 클래스는 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로 변경되는 예제가 완성되었습니다.