뷰 클래스 만들기

Compose 방법 사용해 보기
Jetpack Compose는 Android에 권장되는 UI 도구 키트입니다. Compose에서 레이아웃을 사용하는 방법을 알아보세요.

잘 설계된 맞춤 뷰는 잘 설계된 다른 클래스와 같습니다. 간단한 인터페이스로 특정 기능 집합을 캡슐화하고 CPU와 메모리를 효율적으로 사용하는 등의 이점이 있습니다. 맞춤 뷰는 잘 설계된 클래스일 뿐만 아니라 다음을 실행해야 합니다.

  • Android 표준을 준수합니다.
  • Android XML 레이아웃에서 작동하는 맞춤 스타일 속성을 제공합니다.
  • 접근성 이벤트를 전송합니다.
  • 여러 Android 플랫폼과 호환

Android 프레임워크에서는 이러한 요구사항을 모두 충족하는 뷰를 만드는 데 도움이 되는 일련의 기본 클래스와 XML 태그를 제공합니다. 이 과정에서는 Android 프레임워크를 사용하여 뷰 클래스의 핵심 기능을 만드는 방법을 설명합니다.

자세한 내용은 맞춤 뷰 구성요소를 참고하세요.

뷰 서브클래스 만들기

Android 프레임워크에 정의된 모든 뷰 클래스는 View를 확장합니다. 맞춤 뷰는 View를 직접 확장할 수도 있고, 아니면 Button와 같은 기존 뷰 서브클래스 중 하나를 확장하여 시간을 절약할 수 있습니다.

Android 스튜디오가 뷰와 상호작용할 수 있도록 하려면 최소한 ContextAttributeSet 객체를 매개변수로 사용하는 생성자를 제공해야 합니다. 이 생성자를 사용하면 Layout Editor에서 뷰의 인스턴스를 만들고 수정할 수 있습니다.

Kotlin

class PieChart(context: Context, attrs: AttributeSet) : View(context, attrs)

Java

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

커스텀 속성 정의

사용자 인터페이스에 내장 View를 추가하려면 이를 XML 요소에 지정하고 요소 속성으로 모양과 동작을 제어합니다. XML을 사용하여 맞춤 뷰를 추가하고 스타일을 지정할 수도 있습니다. 맞춤 뷰에서 이 동작을 사용 설정하려면 다음을 실행하세요.

  • <declare-styleable> 리소스 요소에 뷰의 맞춤 속성을 정의합니다.
  • XML 레이아웃에서 속성 값을 지정합니다.
  • 런타임 시 속성 값을 가져옵니다.
  • 가져온 속성 값을 뷰에 적용합니다.

이 섹션에서는 맞춤 속성을 정의하고 이 속성의 값을 지정하는 방법에 관해 설명합니다. 다음 섹션에서는 런타임 시 값을 검색하고 적용하는 방법을 설명합니다.

맞춤 속성을 정의하려면 프로젝트에 <declare-styleable> 리소스를 추가합니다. 일반적으로 이러한 리소스는 res/values/attrs.xml 파일에 배치합니다. 다음은 attrs.xml 파일의 예입니다.

<resources>
   <declare-styleable name="PieChart">
       <attr name="showText" format="boolean" />
       <attr name="labelPosition" format="enum">
           <enum name="left" value="0"/>
           <enum name="right" value="1"/>
       </attr>
   </declare-styleable>
</resources>

이 코드는 PieChart라는 스타일을 지정할 수 있는 항목에 속한 두 개의 맞춤 속성 showTextlabelPosition를 선언합니다. 스타일을 지정할 수 있는 항목의 이름은 규칙에 따라 맞춤 뷰를 정의하는 클래스 이름과 동일합니다. 이 규칙을 반드시 따를 필요는 없지만, 많은 인기 있는 코드 편집기에서는 이 이름 지정 규칙에 따라 명령문을 완성합니다.

맞춤 속성을 정의한 후에는 기본 제공 속성과 마찬가지로 레이아웃 XML 파일에서 이를 사용할 수 있습니다. 유일한 차이점은 맞춤 속성이 다른 네임스페이스에 속한다는 것입니다. 네임스페이스는 http://schemas.android.com/apk/res/android 네임스페이스에 속하지 않고 http://schemas.android.com/apk/res/[your package name]에 속합니다. 예를 들어, PieChart에 정의된 속성을 사용하는 방법은 다음과 같습니다.

<?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-auto">
 <com.example.customviews.charting.PieChart
     custom:showText="true"
     custom:labelPosition="left" />
</LinearLayout>

긴 네임스페이스 URI를 반복할 필요가 없도록 샘플에서는 xmlns 지시어를 사용합니다. 이 지시어는 custom 별칭을 http://schemas.android.com/apk/res/com.example.customviews 네임스페이스에 할당합니다. 네임스페이스에 사용할 별칭을 선택할 수 있습니다.

레이아웃에 맞춤 뷰를 추가하는 XML 태그의 이름을 확인하세요. 이 이름은 맞춤 뷰 클래스의 정규화된 이름입니다. 뷰 클래스가 내부 클래스인 경우 뷰의 외부 클래스 이름으로 추가로 한정합니다. 예를 들어 PieChart 클래스에는 PieView라는 내부 클래스가 있습니다. 이 클래스의 맞춤 속성을 사용하려면 com.example.customviews.charting.PieChart$PieView 태그를 사용합니다.

커스텀 속성 적용

XML 레이아웃에서 뷰를 만들면 XML 태그의 모든 속성을 리소스 번들에서 읽어 뷰의 생성자에 AttributeSet로 전달합니다. AttributeSet에서 직접 값을 읽을 수 있지만 그렇게 하면 몇 가지 단점이 있습니다.

  • 속성 값 내의 리소스 참조가 확인되지 않았습니다.
  • 스타일은 적용되지 않습니다.

대신 AttributeSetobtainStyledAttributes()에 전달하세요. 이 메서드는 이미 역참조되고 스타일이 지정된 값의 TypedArray 배열을 다시 전달합니다.

Android 리소스 컴파일러는 obtainStyledAttributes()를 더 쉽게 호출할 수 있도록 많은 작업을 실행합니다. 생성된 R.javares/ 디렉터리에 있는 각 <declare-styleable> 리소스의 경우 속성 ID 배열과 배열에 있는 각 속성의 색인을 정의하는 상수 집합을 모두 정의합니다. 사전 정의된 상수를 사용하여 TypedArray에서 속성을 읽습니다. PieChart 클래스에서 속성을 읽는 방법은 다음과 같습니다.

Kotlin

init {
    context.theme.obtainStyledAttributes(
            attrs,
            R.styleable.PieChart,
            0, 0).apply {

        try {
            mShowText = getBoolean(R.styleable.PieChart_showText, false)
            textPos = getInteger(R.styleable.PieChart_labelPosition, 0)
        } finally {
            recycle()
        }
    }
}

Java

public PieChart(Context context, AttributeSet attrs) {
   super(context, attrs);
   TypedArray a = context.getTheme().obtainStyledAttributes(
        attrs,
        R.styleable.PieChart,
        0, 0);

   try {
       mShowText = a.getBoolean(R.styleable.PieChart_showText, false);
       textPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
   } finally {
       a.recycle();
   }
}

TypedArray 객체는 공유 리소스이므로 사용 후 재활용해야 합니다.

속성 및 이벤트 추가

속성은 뷰의 동작과 모양을 제어하는 강력한 방법이지만 뷰를 초기화할 때만 읽을 수 있습니다. 동적 동작을 제공하려면 각 맞춤 속성의 속성 getter 및 setter 쌍을 노출합니다. 다음 스니펫은 PieChartshowText라는 속성을 노출하는 방법을 보여줍니다.

Kotlin

fun isShowText(): Boolean {
    return mShowText
}

fun setShowText(showText: Boolean) {
    mShowText = showText
    invalidate()
    requestLayout()
}

Java

public boolean isShowText() {
   return mShowText;
}

public void setShowText(boolean showText) {
   mShowText = showText;
   invalidate();
   requestLayout();
}

setShowTextinvalidate()requestLayout()를 호출합니다. 이러한 호출은 뷰가 안정적으로 동작하도록 하는 데 중요합니다. 모양이 변경될 수 있는 속성이 변경된 후에는 뷰를 무효화해야 합니다. 그래야 뷰를 다시 그려야 한다는 것을 시스템에서 알 수 있습니다. 마찬가지로 뷰의 크기나 모양에 영향을 줄 수 있는 방식으로 속성이 변경되면 새 레이아웃을 요청해야 합니다. 이러한 메서드 호출을 잊어버리면 찾기 어려운 버그가 발생할 수 있습니다.

또한 사용자설정 뷰는 중요한 이벤트를 전달할 수 있도록 이벤트 리스너를 지원해야 합니다. 예를 들어 PieChartOnCurrentItemChanged라는 맞춤 이벤트를 노출하여 사용자가 새 원형 슬라이스에 집중하기 위해 원형 차트를 회전했음을 리스너에게 알립니다.

특히 맞춤 뷰의 유일한 사용자인 경우 속성 및 이벤트 노출을 잊어버리기 쉽습니다. 뷰의 인터페이스를 신중하게 정의하는 데 시간을 들이면 향후 유지보수 비용을 줄일 수 있습니다. 따라야 할 좋은 규칙은 맞춤 뷰의 시각적 모양이나 동작에 영향을 미치는 모든 속성을 항상 노출하는 것입니다.

접근성을 고려한 디자인

맞춤 뷰는 다양한 사용자를 지원해야 합니다. 여기에는 터치스크린을 보거나 사용하지 못하는 장애가 있는 사용자도 포함됩니다. 장애가 있는 사용자를 지원하려면 다음 단계를 따르세요.

  • android:contentDescription 속성을 사용하여 입력 필드에 라벨을 지정합니다.
  • 필요한 경우 sendAccessibilityEvent()를 호출하여 접근성 이벤트를 전송합니다.
  • D패드 또는 트랙볼과 같은 대체 컨트롤러를 지원합니다.

접근성 높은 뷰 만들기에 관한 자세한 내용은 더욱 접근성 높은 앱 만들기를 참고하세요.