본문 바로가기
Android/Java

[Android / Java] CustomView로 재사용성 높이기

by ghan2 2024. 6. 5.

이런 형태의 단순한 회원가입 창을 만들고 싶은데.. 내 코드는 이런 모양이 나왔다

회원가입 창

 

더보기
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/basic">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/title_view">
            <TextView
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:fontFamily="@font/notosans_medium_ttf"
                android:gravity="center"
                android:text="@string/edit_text_title"
                android:textSize="18sp" />
            <android.widget.ImageButton
                android:id="@+id/close_btn"
                android:layout_width="30dp"
                android:layout_height="46dp"
                android:layout_marginEnd="10dp"
                android:background="@drawable/btn_close"
                android:layout_alignParentEnd="true"
                android:layout_centerInParent="true"
                tools:ignore="MissingConstraints" />
        </RelativeLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="20dp"
            android:orientation="vertical"
            android:layout_below="@+id/title_view">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="@color/text_default_2"
                android:textSize="12sp"
                android:fontFamily="@font/notosans_regular_ttf"
                android:layout_weight="0"
                android:text="@string/edit_text_name" />
            <EditText
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:layout_gravity="center"
                android:paddingStart="10dp"
                android:fontFamily="@font/notosans_regular_ttf"
                android:textColor="@color/black"
                android:textSize="12sp"
                android:hint="@string/edit_text_name_hint"
                android:textColorHint="@color/gray"
                android:background="@drawable/login_main_edittext" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="18dp"
                android:textColor="@color/text_default_2"
                android:textSize="12sp"
                android:fontFamily="@font/notosans_regular_ttf"
                android:layout_weight="0"
                android:text="@string/edit_text_birth" />
            <EditText
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:layout_gravity="center"
                android:paddingStart="10dp"
                android:fontFamily="@font/notosans_regular_ttf"
                android:textColor="@color/black"
                android:textSize="12sp"
                android:hint="@string/edit_text_birth_hint"
                android:textColorHint="@color/gray"
                android:background="@drawable/login_main_edittext" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="18dp"
                android:textColor="@color/text_default_2"
                android:textSize="12sp"
                android:fontFamily="@font/notosans_regular_ttf"
                android:layout_weight="0"
                android:text="@string/edit_text_phone" />
            <EditText
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:layout_gravity="center"
                android:paddingStart="10dp"
                android:fontFamily="@font/notosans_regular_ttf"
                android:textColor="@color/black"
                android:textSize="12sp"
                android:hint="@string/edit_text_phone_hint"
                android:textColorHint="@color/gray"
                android:background="@drawable/login_main_edittext" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="18dp"
                android:textColor="@color/text_default_2"
                android:textSize="12sp"
                android:fontFamily="@font/notosans_regular_ttf"
                android:layout_weight="0"
                android:text="@string/edit_text_email" />
            <EditText
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:layout_gravity="center"
                android:paddingStart="10dp"
                android:fontFamily="@font/notosans_regular_ttf"
                android:textColor="@color/black"
                android:textSize="12sp"
                android:hint="@string/edit_text_email_hint"
                android:textColorHint="@color/gray"
                android:background="@drawable/login_main_edittext" />
            <EditText
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:layout_gravity="center"
                android:layout_marginTop="10dp"
                android:paddingStart="10dp"
                android:fontFamily="@font/notosans_regular_ttf"
                android:textColor="@color/black"
                android:textSize="12sp"
                android:hint="@string/edit_text_email_verify"
                android:textColorHint="@color/gray"
                android:background="@drawable/login_main_edittext" />

        </LinearLayout>

    </RelativeLayout>


</androidx.constraintlayout.widget.ConstraintLayout>

 

작성할 때도 번거로웠지만 이름, 생년월일, 휴대폰 번호, 이메일을 적는 칸이 글자만 다르고 모두 동일했다. input란도 마찬가지였다. 또 한번 margin을 바꾸려면 하나하나 바꿔줘야 하는 번거로운 작업이 수반됐다. 

이런 반복적인 요소들을 컴포넌트화 하여 재사용할 수 있다면 얼마나 좋을까?

 

해결할 수 있는 방법으로 include와 customView가 있는 것 같은데.. include는 전체 속성을 모두 오버라이드 해줘야 한다고 해서 좀더 찾아봐야 할 것 같고 오늘은 CustomView에 대해 알아보자!

 

1. layout xml 파일 생성

customView의 기본으로 쓰일 layout xml 파일을 만들어 준다. 

2. attrs.xml 설정

커스텀하게 바꿔줄 수 있는 속성들을 지정해주자. values -> attrs.xml 파일 아래에 내용을 추가하면 된다. 

이렇게 입력하면 후에 app:text=""형태로 쓰일 수 있고 문자열을 형식으로 받는다.

reference|string 형식은 Android에서 XML 속성을 정의할 때, 해당 속성이 리소스 참조(reference) 또는 문자열(string) 형태를 가질 수 있도록 하기 위해 사용된다. 예를 들어, 문자열 리소스(@string/example), 레이아웃 리소스(@layout/example), 색상 리소스(@color/example) 등 다양한 리소스 타입을 참조할 수 있는 것이다! 

 

3. CustomView 만들기

미리 보는 결과 화면
반복되던 코드를 단 5줄로 줄였다!! 너무 신기...

 

SignUpBox.java를 만들어 다음과 같이 작성한다.

package com.example.tiaapplication;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;

public class SignUpBox extends ConstraintLayout {
    TextView text;
    EditText editText;

    public SignUpBox(@NonNull Context context) {
        super(context);
        initView();
    }

    public SignUpBox(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        //attrs는 입력된 속성값이다.
        initView();
        getAttrs(attrs);
    }
    
    private void initView() {
        String infService = Context.LAYOUT_INFLATER_SERVICE;

        LayoutInflater li = (LayoutInflater) getContext().getSystemService(infService);
        View v = li.inflate(R.layout.edit_box, this, false);
		//아까 만들었던 edit_box 레이아웃을 inflate 시킴
        addView(v);
        //뷰를 자식 뷰로 추가시킨다. 

        text = (TextView) findViewById(R.id.text_name); // 레이아웃에서 아이디 값으로 해당 뷰를 찾아온다.
        editText = (EditText) findViewById(R.id.text_name_hint); //레이아웃에서 아이디 값으로 해당 뷰를 찾아온다.

    }
    private void getAttrs(AttributeSet attrs) {
        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.SignUpBox);
        setTypeArray(typedArray);
        // 이 부분이 이해가 안 갔었는데 한 줄로 요약하면 xml에 기록된 커스텀된 속성 값들을 
        // TypedArray형태로 가져오는 작업이다.
        
    }
    
    private void setTypeArray(TypedArray typedArray) {
        String text_string = typedArray.getString(R.styleable.SignUpBox_text);
        text.setText(text_string);
        String text_hint_string = typedArray.getString(R.styleable.SignUpBox_hint);
        editText.setHint(text_hint_string);
        typedArray.recycle();

    }
    void setText(String text_string) {
        text.setText(text_string);

    }
    void setText(int text_resID) {
        text.setText(text_resID);
    }
    void setEditText(String hint_string) {
        editText.setText(hint_string);
    }
}

 

커스텀 뷰 완성!

 

 

 


reference

https://gun0912.tistory.com/38