본문 바로가기
별밤 일지/개발

[Android] CustomView 를 활용한 효율적인 나만의 View 만들기

by 별밤 에디터 2023. 12. 13.

개요 및 배경

<별 헤는 밤> 메인 페이지에 새로운 기능인 관심지역 날씨 카드 기능을 맡게 되었다.

 

간단히 말하면 위 그림과 같은 기능인데, 즐겨찾기 기능이라고 보면 된다.

총 3개까지 관심 지역을 설정할 수 있고, 아래처럼 관심 지역이 2개 이하일 때는 추가할 수 있는 + 버튼이 나오게 된다.

 

지금까지 위와 같은 동적으로 반복적인 요소를 생성할 때는 RecyclerView를 사용했었지만, 이번에 새로운 기능을 사용해보고 싶어 CustomView를 활용하여 해당 기능을 구현하게 되었다.

 


CustomView 생성

자바의 중요 개념들 중에는 부모 클래스, 자식 클래스, 상속이 있는데 CustomView 도 이와 비슷한 개념을 사용한다.

안드로이드에서 View는 모든 안드로이드 화면의 기본 구성 요소이다. 자바에서의 Object (최상위 객체)와 비슷하다고 생각하면 이해가 쉽다.

class CustomInterestAreaView extends View {
    public CustomInterestAreaView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}

 

위 코드처럼, View를 상속받아 원하는 CustomView 클래스를 생성한다. (물론, View 가 아닌 LinearLayout이나 Button 등 원하는 서브클래스를 상속받을 수도 있다.)

추가로 뷰와 상호작용을 위해 Context, AttributeSet 파라미터로 받는 생성자를 필수로 작성한다.

 

 

내부 속성 정의

CustomView의 내부 속성을 xml 코드에서 바로 사용하고 싶다면, 아래와 같은 설정이 필요하다.

<resources>
		<declare-styleable name="CustomInterestAreaView">
		    <attr name="name" format="string"/>
		    <attr name="observationalFit" format="string"/>
		</declare-styleable>
</resources>

attrs.xml

attrs.xml (위치: app/src/main/res/values/attrs.xml) 파일에 <declare-styleable> 태그를 사용하여 CustomView의 원하는 속성을 정의한다.

위와 같이 CustomInterestAreaView의 내부 속성으로 name, observationFit을 정의하면, 런타임에 값을 적용할 수 있다.

<?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       xmlns:custom="http://schemas.android.com/apk/res/com.example.customviews">
     <com.starrynight.tourapiproject.mainPage.interestArea.CustomInterestAreaView
         custom:name="별마로 천문대"
				 custom:observationFit ="70%" />
    </LinearLayout>

 

 

내부 속성 적용

안드로이드에서는 xml로 뷰를 만들면, resource bundle에서 xml 태그의 모든 속성을 읽어 뷰 생성자에 AttributeSet으로 전달한다.

하지만 AttributeSet에서 직접 값을 읽게 되면 스타일이 적용되지 않기 때문에 obtainStyledAttributes() 메서드를 사용해야 한다.

AttributeSet를 obtainStyledAttributes() 메서드에 넘기면 스타일이 적용된 TypedArray를 리턴하는데, 이를 활용하여 런타임 속성을 가져올 수 있다.

public CustomInterestAreaView(Context context, AttributeSet attrs) {
   super(context, attrs);

   TypedArray typedArray = context.getTheme().obtainStyledAttributes(
        attrs,
        R.styleable.CustomInterestAreaView,
        0, 0);

	 nameText = typedArray.getString(R.styleable.CustomInterestAreaView_name);
	 observationalFitText = typedArray.getString(R.styleable.CustomInterestAreaView_observationalFit);

}

 

 

동적 속성 적용

동적으로 속성의 값을 get, set 하려면 추가로 메서드를 작성해야 한다.

public void setNameText(String name) {
   nameText = name;
   invalidate();
   requestLayout();
}

위 setNameText() 메서드에서 invalidate(), requestLayout()를 호출하는데, 이는 뷰가 안정적으로 작동하기 위해 필수로 적용해줘야 한다.

 


마무리

이번 시간에는 RecyclerView 가 아닌 CustomView를 사용하여 동적인 뷰를 만들어보았다. 사실 관심 지역 카드 기능은 최대 3개까지만 표출되기 때문에 CustomView를 사용해도 별다른 성능에 영향이 없었는데, 만약 데이터의 개수가 매우 많다면 RecyclerView를 사용하는 것이 좀 더 효율적일 것 같다는 생각이 들었다. 하지만 런타임으로 속성을 설정하고, 좀 더 복잡한 구조의 커스텀 뷰를 만들고 싶다면 CustomView를 활용해 보는 것도 좋은 것 같다.

 


<별 헤는 밤> 놀러가기 😊

 

별 헤는 밤: 밤하늘, 별자리, 여행정보와 날씨예보까지 - Google Play 앱

오늘부터 별잘알! 오늘밤 별자리 정보, 날씨·광공해·월령까지 고려한 '관측적합도', 주변 관측지 검색으로 누구나 쉽게 밤하늘을 즐겨보세요.

 

 

play.google.com