짱짱해커가 되고 싶은 나

05-1. 레이아웃 본문

모바일

05-1. 레이아웃

동로시 2021. 2. 17. 12:15

* 레이아웃 - LinearLayout, RelativeLayout, FrmaeLayout, TableLayout, GridLayout 등

AbsoluteLayout도 있었는데 해상도가 다른 안드로이드에서 문제가 발생해 더 이상 사용하지 않는다.

- orientation : 레이아웃 안에 배치할 위젯의 수직/수평 방향 설정(vertical/horizontal)

- gravity : 레이아웃 안에 배치할 위젯(자식)의 정렬 방향 설정(좌/우/중앙 등, 2개 조합도 가능)

- padding : 레이아웃 안에 배치할 위젯의 여백 설정

- layout_weight : 레이아웃이 전체 화면에서 차지하는 공간의 가중값 설정(여러 개의 레이아웃이 중복될 때 사용)

- baselineAligned : 레이아웃 안에 배치할 위젯을 보기 좋게 정렬(true/false, 디폴트가 트루)

 

추가) lyaout_gravity : 자신의 위치(위젯)를 부모(레이아웃)의 어디쯤에 위치시킬지

 

* LinearLayout(선형 레이아웃)

레이아웃의 왼쪽 위부터 수평/수직으로 배치

 

만약 한 화면에 수평과 수직으로 위젯이 다양하게 존재해야 할 경우 중복 리니어레이아웃을 사용한다.

리니어레이아웃 안에 다른 리니어레이아웃을 생성하는 방식이다.

이렇게 여러개의 리니어레이아웃을 사용할 경우 각 레이아웃의 크기를 지정해줘야 한다. (layout_weight)

레이아웃을 화면 전체에 채워야 하기 때문에 주로 %단위로 지정한다.

layout_weight을 1로 주고 height를 match_parent로 바꾸면 각 레이아웃의 높이들이 동일한 비율로 화면을 꽉 채운다.

다른 비율로 하고 싶다면 height를 0dp로 하고 weight를 원하는 비율로 설정하면 된다.

 

이런 모양으로 중복 레이아웃을 연습해보자..

<?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"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#ff0000"
        android:layout_weight="1"
        android:orientation="horizontal">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1">
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#f0f70b"
                android:orientation="horizontal">
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:layout_weight="1"
                android:background="#000000"
                android:orientation="vertical">
            </LinearLayout>

        </LinearLayout>

    </LinearLayout>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#0000ff"
        android:layout_weight="1">
    </LinearLayout>

</LinearLayout>

눈에 보이는 레이아웃의 수보다 더 많은 레이아웃이 들어가고 소분해야했다.  (빨(왼,오(노,검)),파)

 

xml 없이 java로도 코딩 가능하다.

package com.example.widget4;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Color;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

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

        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
        LinearLayout baseLayout = new LinearLayout(this);
        baseLayout.setOrientation(LinearLayout.VERTICAL);
        baseLayout.setBackgroundColor(Color.rgb(0,255,0));
        setContentView(baseLayout, params);

        Button btn = new Button(this);
        btn.setText("button");
        btn.setBackgroundColor(Color.MAGENTA);
        baseLayout.addView(btn);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getApplicationContext(), "java button", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

LinearLayout.LayoutParams()의 인자로 layout_width, layout_height의 값을 넣어준다. 

layout_weight를 쓰고 싶으면 3번째 인자로 값을 넣으면 된다.

버튼도 만든후 레이아웃에 addView로 추가하면 된다.

addView는 위젯 변수와 레이아웃 파라미터를 넘길 수 있는데 이렇게 레이아웃 파라미터를 생략했는데 디폴트로 width=match_parent, height=wrap_content가 된다.

* RelativeLayout(상대 레이아웃)

위젯이 속한 레이아웃의 (1)레이아웃의 상하좌우 위치를 지정하여 배치/ (2)다른 위젯으로부터 상대적인 위치를 지정

(1) 레이아웃의 상하좌우에 배치

가능한 위치 속성은 7가지가 있고 각 속성값은 true/false다.

(2) 다른 위젯으로부터 상대적인 위치에 배치

layout_속성 = "@id/상대앱id"

 

* TableLayout

위젯을 행과 열의 개수로 지정한 테이블 형태로 배열

<TableRow>(==행의 수)와 함께 사용, 열의 수는 TableRow에 포함된 위젯의 수로 결정 (열 번호는 0부터 시작)

- layout_span : 열을 합쳐서 표시(위젯 속성)

- layout_column : 지정된 열에 현재 위젯을 표시(위젯 속성)

- stretchColumns : 지정된 열의 폭을 늘림(테이블 레이아웃 속성)

stretchColumns="*" : 각 셀을 모두 같은 크기로 확장하여 꽉 차는 효과

 

    <TableRow>
        <EditText
            android:layout_span="5"
            android:hint="숫자 1 입력"
            android:id="@+id/n1"/>
    </TableRow>

이렇게 테이블 로우 안에 들어 있는 위젯들은 원래 <EditText> </EditText>의 형식으로 작성했지만 테이블 레이아웃의 경우 <EditText />형식으로 작성한다. (리니어레이아웃을 제외하고 다른 레이아웃들은 다 이런 형식)

package com.example.widget4;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Color;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    EditText input1,input2;
    Button[] numButton = new Button[10];
    Integer[] numButtonId = {R.id.b0, R.id.b1, R.id.b2, R.id.b3, R.id.b4, R.id.b5, R.id.b6, R.id.b7, R.id.b8, R.id.b9};
    Button add, sub, mul, div;
    TextView textView;
    String n1, n2;
    Integer result;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setTitle("테이블레이아웃 계산기");

        input1 = (EditText)findViewById(R.id.n1);
        input2 = (EditText)findViewById(R.id.n2);
        add = (Button)findViewById(R.id.add);
        sub = (Button)findViewById(R.id.sub);
        mul = (Button)findViewById(R.id.mul);
        div = (Button)findViewById(R.id.div);
        textView = (TextView)findViewById(R.id.textView);
        for(int i=0; i<numButtonId.length; i++){
            numButton[i] = (Button)findViewById(numButtonId[i]);
        }

        for(int i=0; i<numButtonId.length; i++){
            final int index = i;

            numButton[index].setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(input1.isFocused() == true){
                        n1 = input1.getText().toString() + numButton[index].getText().toString();
                        input1.setText(n1);
                    } else if(input2.isFocused()){
                        n2 = input2.getText().toString() + numButton[index].getText().toString();
                        input2.setText(n2);
                    } else{
                        Toast.makeText(getApplicationContext(), "먼저 에디트텍스트를 선택하세요", Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }

        add.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                n1 = input1.getText().toString();
                n2 = input2.getText().toString();
                result = Integer.parseInt(n1) + Integer.parseInt(n2);
                textView.setText("계산 결과 : " + result.toString());
            }
        });

        sub.setOnTouchListener(new View.OnTouchListener(){
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                n1 = input1.getText().toString();
                n2 = input2.getText().toString();
                result = Integer.parseInt(n1) - Integer.parseInt(n2);
                textView.setText("계산 결과 : " + result.toString());
                return false;
            }
        });

        mul.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                n1 = input1.getText().toString();
                n2 = input2.getText().toString();
                result = Integer.parseInt(n1) * Integer.parseInt(n2);
                textView.setText("계산 결과 : " + result.toString());
                return false;
            }
        });

        div.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                n1 = input1.getText().toString();
                n2 = input2.getText().toString();
                result = Integer.parseInt(n1) / Integer.parseInt(n2);
                textView.setText("계산 결과 : " + result.toString());
                return false;
            }
        });

    }
}

테이블레아웃으로 만든 계산기인데 java 부분에서 몇 개 짚고 가자.

이렇게 버튼이 여러 개일 때는 배열을 이용해서 (버튼 배열 + 버튼 id 배열) 반복문을 통해 findViewById를 하면 편하다.

그리고 버튼이 눌렸을 때 EditText에 숫자를 집어 넣는 부분을 보면 i를 바로 쓰지 않고 index를 만들어 쓴다.

그 이유는 이 친구는 자바라. 저렇게 i 변수를 익명 클래스 안에서 쓰지 못한다. final 변수를 써야하기 때문에 final int index=i 와 같은 작업을 해주는 것이다.

 

TableLayout에 포함된 위젯은 layout_width/layout_height의 속성을 생략해도 된다.

* GridLayout

행/열로 확장하여 다양하게 배치 가능 (android 4.0부터 지원)

- rowCount : 행의 수

- columnCount : 열의 수

- orientation : 그리드를 수평/수직 방향 우선 선택

- layout_row : 위젯이 자신이 위치할 행 번호

- layout_column : 위젯이 자신이 위치할 열 번호

- layout_rowSpan : 위젯이 자신의 행 확장

- layout_columnSpan : 위젯이 자신의 열 확장

- layout_gravity : layout_rowSpan/layout_columnSpan으로 확장되었을 때 위젯을 확장된 셀에 꽉 채우는 효과

(fill, fill_vertical, fill_horizontal 등)

 

GridLayout에 포함된 위젯은 layout_width/layout_height의 속성을 생략해도 된다.

* FrameLayout

위젯을 왼쪽 위에 일률적으로 겹쳐서 배치(중복되어 보이는 효과)

여러 개의 위젯을 배치한 후 상황에 따라서 필요한 위젯을 보이는 방식에 주로 활용

- foreground : 프레임레이아웃의 전경 이미지 지정

- goregroundGravity : 전경 이미지의 위치 지정 ( fill, right, left, top, bottom 등)

 

* ConstraintLayout

RelativeLayout과 비슷하지만 개발자가 인터페이스를 더욱 풍부한 방식으로 표현할 수 있는 다양한 방법을 제공(2.2 이상부터 가능)

 

 

 

'모바일' 카테고리의 다른 글

06-2. 기타 위젯  (0) 2021.02.17
06-1. 시간 관련 위젯  (0) 2021.02.17
04-5. 위젯3  (0) 2021.02.16
04-4. 위젯2  (0) 2021.02.16
04-3. 간단한 계산기 앱  (0) 2021.02.15
Comments