본문 바로가기
개발(Development)/Android(안드로이드)

[안드로이드] LayoutParams(레이아웃 파라미터) 개념과 구조/종류

by 카레유 2021. 7. 12.

# 레이아웃 파라미터(LayoutParams)란?

부모 레이아웃 안에서 View(뷰)가 어떻게 배치될지를 정의하는 속성이다.

 

구글 개발자 사이트의 레퍼런스에는 아래와 같이 기술되어 있다.

"LayoutParams are used by views to tell their parents how they want to be laid out."

 

구체적으로 레이아웃 XML파일에서 앞에 layout_"이 붙는 속성들을 말하며, LayoutParams클래스의 필드값과 매핑된다.

따라서 코드 상에서 LayoutParams객체를 통해 뷰의 레이아웃 파라미터 속성을 다룰 수 있다.

 

아래의 activity_main.xml 파일에서 andorid:layout_width, andorid:layout_height 가 레이아웃 파라미터이다.

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".MainActivity">

    <TextView
        android:id="@+id/textView_01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />

</LinearLayout>

 

layout_width, layout_height는 뷰 자체의 너비와 높이인데 왜 부모 레이아웃과 관련된 속성인지 의하할 수 있다.

그러나 해당 속성 값으로 match_parent 라는 값을 설정할 수 있다는 걸 생각하면 고개가 끄덕여질 것 같다.

 

XML파일을 작성하고 setContentView(R.layout.activity_main) 메서드를 호출하면

내부적으로 LayoutInflater라는 객체가 XML에 정의된 내용을 뷰(View)로 전환/배치하여 메모리에 올려주기 때문에

개발자가 별도의 작업을 하지 않아도 화면이 쉽게 그려진다.

 

그러나 Java/Kotlin 코드로 뷰를 생성하고 배치할 때는

각 뷰의 일반 속성(텍스트, 색상 등)과 레이아웃 파라미터(크기, 배치 등)를 코드로 직접 정의해줘야 한다.

 

레이아웃 파라미터 속성을 정의하는 클래스가 바로 LayoutParams 이다.


# LayoutParams 클래스의 구조

LayoutParams은 아래와 같은 상속 구조를 갖고 있다. (대표적인 것만 간추린 것으로 사실 이것보다 더 많다)

 

ViewGroup.LayoutParams

    ㄴ AbsoluteLayout.LayoutParams

    ㄴ ViewGroup.MarginLayoutParams

         ㄴ GridLayout.LayoutParams

         ㄴ FrameLayout.LayoutParams

         ㄴ RelativeLayout.LayoutParams

         ㄴ LinearLayout.LayoutParams

             ㄴ TableLayout.LayoutParams

 

최상위의 ViewGroup.LayoutParams은 width, height 필드를 갖으며, 생성자는 아래와 같다.

 

LayoutParams(int width, int height)

 

여기서 정의한 width, height가 XML상의 layout_widht, layout_height와 매핑된다고 보면 된다.

 

따라서 하위의 LayoutParams들도 widht, height 필드를 갖으며,

각각의 레이아웃 스타일에 맞는 필드값을 추가로 갖는다.


# LayoutParams 속성 종류(필드값)

LayoutParams 클래스는 부모에게 상속받은 필드에 더하여 자신만의 필드를 추가로 사용할 수 있다.

아래 도표는 LinearLayout.LayoutParams 클래스의 속성을 정리한 것이다.

(다른 LayoutParams 의 필드값에 대해서는 레퍼런스를 참고)

 

부모 클래스 1차 상속 클래스 2차 상속 클래스 필드값
ViewGroup.
LayoutParams
    width, height
  ViewGroup.
MarginLayoutParams
  bottomMargin, ...
    LinearLayout.
LayoutParams
weight, gravity

 

위의 필드값들 앞에 layout_ 을 붙이면, XML의 속성값과 매칭된다고 보면 된다.

 

따라서 LinearLayout.LayoutParams 은 아래의 필드값들을 모두 설정할 수 있는 클래스가 된다.

1) 부모클래스의 필드: layout_width, layout_height

2) 1차 상속클래스의 필드: layout_marginBottom, layout_marginTop, ...

3) 본인의 필드: layout_weight, layout_gravity 

 

LayoutParams 클래스들은 다양한 필드 값을 갖지만,

생성자함수는 주로 width, height만을 매개변수로 받기 때문에 

다른 필드값들 설정하려면 따로 값을 할당하거나 setter 메서드를 사용해야 한다.


# LayoutParams 사용 방법

LayoutParams는 주로 코드로 뷰를 생성/배치할 때,

레이아웃 파라미터 속성을 설정하기 위해 addView(), setContentView() 메서드의 매개변수로 사용된다.

 

1. addView()메서드

: ViewGroup클래스에 정의된 메서드로 부모 뷰그룹에 자식뷰를 추가한다.

: 첫번째 매개변수로 추가할 자식뷰를, 두번째 매개변수로 레이아웃 파라미터 객체를 넣어준다.

 

- Java:  addView (View child, ViewGroup.LayoutParams params) 

- Kotlin:  addView(child: View!, params: ViewGroup.LayoutParams!) 

 

 

2. setContentView()메서드

: Activity클래스에 정의된 메서드로 액티비티의 화면을 그려준다.

: 첫번째 매개변수로 화면에 표시할 뷰를, 두번째 매개변수로 레이아웃 파라미터 객체를 넣어준다.

 

- Java:  setContentView(View view , ViewGroup.LayoutParams params) 

- Kotlin:  setContentView(view: View!, params: ViewGroup.LayoutParams!) 

 

* setContentView() 메서드는 보통 두번째 인자인 LayoutParmas를 생략하는데, 디폴트로 너비와 높이가 match_parent로 설정된다.

 

구체적인 사용 방법은 아래 코드로 대체한다.(최선을 다해 주석을 달았다)

1) LinearLayout 생성

2) TextView 2개 생성

3) LinearLayout, TextView 2개를 배치하기 위한 LayoutParams 객체 생성

4) LinearLayout의 자식으로 TextView 2개 추가: addView(TextView, LayoutParams) 

5) Activity의 화면을 LinearLayout으로 설정: setContentView(LinearLayout, LayoutParams) 

 

 

- Java(자바) 코드 파일

 

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // LinearLayout 생성
        LinearLayout linearLayout = new LinearLayout(this);
        linearLayout.setOrientation(LinearLayout.VERTICAL);
        linearLayout.setBackgroundColor(Color.GRAY);


        // 1번째 TextView 생성
        TextView textView_01 = new TextView(this);
        textView_01.setBackgroundColor(Color.GREEN);
        textView_01.setText("1번째 텍스트뷰 - 초록색");

        // 2번째 TextView 생성
        TextView textView_02 = new TextView(this);
        textView_02.setBackgroundColor(Color.YELLOW);
        textView_02.setText("2번째 텍스트뷰 - 노란색");


        // LinearLayout.LayoutParams 생성: LinearLayout 배치용
        LinearLayout.LayoutParams layoutLayoutParams = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.MATCH_PARENT
        );

        // LinearLayout.LayoutParams 생성: 1번재 TextView 배치용
        LinearLayout.LayoutParams textViewLayoutParams_01 = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.WRAP_CONTENT, // layout_width 설정
                LinearLayout.LayoutParams.WRAP_CONTENT // layout_height 설정
        );

        // LinearLayout.LayoutParams 생성: 2번재 TextView 배치용
        LinearLayout.LayoutParams textViewLayoutParams_02 = new LinearLayout.LayoutParams(
                500, // layout_width 설정
                200 // layout_height 설정
        );

        textViewLayoutParams_02.setMarginStart(100); // layout_marginStart 설정


        // TextView를 LinearLayout에 추가
        // LayoutParams객체로 배치 정보를 넣어준다.
        linearLayout.addView(textView_01, textViewLayoutParams_01);
        linearLayout.addView(textView_02, textViewLayoutParams_02);


        // LinearLayout으로 화면 그리기 
        // LayoutParams 객체로 배치 정보를 넣어준다.
        setContentView(linearLayout, layoutLayoutParams);

    }
}

 

 

- Kotlin(코틀린) 코드 파일

 

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 리니어 레이아웃 생성
        val linearLayout = LinearLayout(this);
        linearLayout.orientation = LinearLayout.VERTICAL;

        // 1번째 텍스트 뷰 생성
        val textView01 = TextView(this);
        textView01.setBackgroundColor(Color.GREEN);
        textView01.text = "1번째 텍스트뷰 - 초록색";

        // 2번째 텍스트 뷰 생
        val textView02 = TextView(this);
        textView02.setBackgroundColor(Color.YELLOW);
        textView02.text = "2번째 텍스트뷰 - 노란색";


        // LayoutParams 생성: 리니어 레이아웃 용
        val layoutLayoutParam = LinearLayout.LayoutParams(
            LinearLayout.LayoutParams.MATCH_PARENT,
            LinearLayout.LayoutParams.MATCH_PARENT
        );

        // LayoutParams 생성: 1번째 텍스트뷰 용
        val textViewtLayoutParam01 = LinearLayout.LayoutParams(
            LinearLayout.LayoutParams.WRAP_CONTENT,
            LinearLayout.LayoutParams.WRAP_CONTENT
        );

        // LayoutParams 생성: 2번째 텍스트뷰 용
        val textViewtLayoutParam02 = LinearLayout.LayoutParams(
            500,
            200
        );
        textViewtLayoutParam02.marginStart = 100;


        // 리니어레이아웃에 텍스트뷰 추가
        linearLayout.addView(textView01, textViewtLayoutParam01);
        linearLayout.addView(textView02, textViewtLayoutParam02);

        
        // 레이아웃을 화면에 표시
        setContentView(linearLayout, layoutLayoutParam);
    }
}

 

 

- 실행결과

 


# LayoutParams의 필요성

뷰의 backgroundColor나 text등은 뷰 객체의 일반 속성으로 바로 설정하는데,

weight, height, margin, gravity 등 레이아웃 파리미터는 왜 LayoutParams 객체로 따로 설정할까?

 

레이아웃 파라미터는 뷰 단독으로 설정될 수 없는 속성이기 때문이다.

 

margin, gravity, weight 등의 속성은 뷰 자체적으로 설정될 수 없으며,

부모 레이아웃 안에서 주변과의 관계를 통해서만 설정되어지는 값들이다.

(width, height도 마찬가지다.)

 

이러한 이유로 안드로이드는 LayoutParams를 통해 뷰의 크기와 위치 관련 속성을 따로 관리하고 배치한다.

 

 

 

댓글