자바 안드로이드 앱개발 강좌, 표 형태로 배치 – GridLayout

안드로이드 개발에서 UI 레이아웃을 구성하는 것은 애플리케이션의 사용자 경험을 결정하는 중요한 요소입니다. 여러 가지 레이아웃 옵션 중 GridLayout은 요소를 일정한 그리드 형태로 배치할 수 있는 유용한 레이아웃 매니저입니다. 이 강좌에서는 GridLayout의 개념, XML 예제, Java 코드로의 구현과 사용 방법에 대해 자세히 살펴보겠습니다.

1. GridLayout 개요

GridLayout은 안드로이드에서 제공하는 레이아웃 중 하나로, 자식 뷰들을 2차원 그리드 형태로 배치할 수 있습니다. 각 뷰는 행과 열에 위치하여 차례대로 배치되며, 뷰의 크기 및 위치를 유연하게 설정할 수 있습니다.

1.1 GridLayout의 장점

  • 정렬 및 배치가 용이하다.
  • 다양한 크기와 비율로 뷰를 배치할 수 있다.
  • 복잡한 UI를 간단하게 구성할 수 있다.

1.2 GridLayout의 속성

GridLayout은 아래와 같은 주요 속성을 제공합니다:

  • rowCount: 그리드의 행 수를 지정합니다.
  • columnCount: 그리드의 열 수를 지정합니다.
  • layout_row: 특정 뷰가 위치할 행을 지정합니다.
  • layout_column: 특정 뷰가 위치할 열을 지정합니다.
  • layout_rowSpan: 한 뷰가 가로로 몇 개의 행을 차지할지를 설정합니다.
  • layout_columnSpan: 한 뷰가 세로로 몇 개의 열을 차지할지를 설정합니다.

2. GridLayout을 사용한 기본 예제

다음은 GridLayout을 사용하여 간단한 계산기 앱을 구현하는 예제입니다.

2.1 XML 레이아웃 파일

먼저, activity_main.xml 파일을 작성하겠습니다. 이 파일에서는 버튼과 텍스트뷰를 그리드 형태로 배치합니다:

<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:rowCount="5"
    android:columnCount="4"
    android:padding="16dp">

    <TextView
        android:id="@+id/resultTextView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnSpan="4"
        android:gravity="end"
        android:textSize="32sp"
        android:padding="16dp"
        android:text="0"/>

    <Button
        android:text="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

    <Button
        android:text="2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

    <Button
        android:text="3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

    <Button
        android:text="+"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

    <Button
        android:text="4"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

    <Button
        android:text="5"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

    <Button
        android:text="6"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

    <Button
        android:text="-"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

    <Button
        android:text="7"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

    <Button
        android:text="8"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

    <Button
        android:text="9"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

    <Button
        android:text="*"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

    <Button
        android:text="C"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

    <Button
        android:text="0"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

    <Button
        android:text="="
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

    <Button
        android:text="/"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

</GridLayout>

2.2 Java 코드 구현

XML에서 정의한 레이아웃에 대한 로직을 구현하기 위해 MainActivity.java 파일을 작성합니다:

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private TextView resultTextView;
    private StringBuilder currentInput = new StringBuilder();
    private String operator = "";
    private double operand1 = 0;

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

        resultTextView = findViewById(R.id.resultTextView);

        int[] buttonIds = {
            R.id.button1, R.id.button2, R.id.button3, R.id.button4, 
            R.id.button5, R.id.button6, R.id.button7, R.id.button8, 
            R.id.button9, R.id.button0, R.id.buttonPlus, 
            R.id.buttonMinus, R.id.buttonMultiply, R.id.buttonDivide, 
            R.id.buttonClear, R.id.buttonEqual
        };

        for (int id : buttonIds) {
            Button button = findViewById(id);
            button.setOnClickListener(this::onButtonClick);
        }
    }

    private void onButtonClick(View view) {
        Button button = (Button) view;
        String text = button.getText().toString();

        switch (text) {
            case "C":
                currentInput.setLength(0);
                operator = "";
                operand1 = 0;
                break;
            case "=":
                calculate();
                return;
            default:
                currentInput.append(text);
                break;
        }
        resultTextView.setText(currentInput.toString());
    }

    private void calculate() {
        if (currentInput.length() == 0) return;

        if (operator.isEmpty()) {
            operand1 = Double.parseDouble(currentInput.toString());
        } else {
            double operand2 = Double.parseDouble(currentInput.toString());
            switch (operator) {
                case "+":
                    operand1 += operand2;
                    break;
                case "-":
                    operand1 -= operand2;
                    break;
                case "*":
                    operand1 *= operand2;
                    break;
                case "/":
                    if (operand2 != 0) {
                        operand1 /= operand2;
                    }
                    break;
            }
        }
        currentInput.setLength(0);
        currentInput.append(operand1);
        resultTextView.setText(currentInput.toString());
    }
}

3. GridLayout의 고급 사용법

GridLayout은 기본 사용법 외에도 다양한 기능을 제공합니다. 여기서는 layout_rowSpanlayout_columnSpan 속성이 어떻게 동작하는지 살펴보겠습니다.

3.1 RowSpan과 ColumnSpan

GridLayout에서는 각 뷰가 연속되는 행이나 열을 차지하도록 설정할 수 있습니다. 다음은 이러한 속성을 활용한 예제입니다:

<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:rowCount="4"
    android:columnCount="3">

    <Button
        android:text="Button 1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_rowSpan="2"
        android:layout_columnSpan="2"
        android:layout_columnWeight="1"/>

    <Button
        android:text="Button 2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

    <Button
        android:text="Button 3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

    <Button
        android:text="Button 4"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_columnWeight="1"/>

</GridLayout>

위의 코드에서 Button 1은 2행과 2열을 차지하게 설정되었습니다. 이와 같은 방식으로 여러 뷰를 설정하여 복잡한 UI를 구성할 수 있습니다.

4. GridLayout의 동적 생성

코드로 GridLayout을 동적으로 생성할 수도 있습니다. 이 방법은 사용자가 예상치 못한 상황에서도 유용하게 활용될 수 있습니다:

GridLayout gridLayout = new GridLayout(this);
gridLayout.setRowCount(3);
gridLayout.setColumnCount(3);

for (int i = 0; i < 9; i++) {
    Button button = new Button(this);
    button.setText("Button " + (i + 1));
    GridLayout.LayoutParams params = new GridLayout.LayoutParams();
    params.rowSpec = GridLayout.spec(i / 3);
    params.columnSpec = GridLayout.spec(i % 3);
    button.setLayoutParams(params);
    gridLayout.addView(button);
}

setContentView(gridLayout);

위의 예제 코드는 3×3 크기의 GridLayout을 코드로 생성하여 각 셀에 버튼을 배치합니다. 이를 통해 유연한 UI 구성이 가능합니다.

5. 결론

GridLayout은 안드로이드 앱 개발에서 매우 유용한 레이아웃 옵션입니다. 이 강좌를 통해 GridLayout의 기본 개념, XML 레이아웃 구성, Java 코드 구현 및 고급 사용법을 알아보았습니다. GridLayout을 사용하여 다양한 UI 요소를 효과적으로 배치할 수 있으며, 복잡한 레이아웃을 쉽게 관리할 수 있습니다.

실습과 과제

당신의 앱을 더욱 발전시키기 위해, GridLayout을 활용하여 실제 앱 프로젝트를 진행해보세요. 다양한 크기의 사용자 정의 버튼, 사용자 인터페이스를 구성하고 더 많은 기능을 추가하는 과제를 수행해 보세요.

이 강좌가 여러분의 안드로이드 앱 개발 여정에 도움이 되길 바랍니다!