기록

androidStudio/kotlin/cutomview 본문

Moblie/Android

androidStudio/kotlin/cutomview

youngyin 2022. 4. 25. 14:30

CustomView

라이브러리에서 제공하는 뷰가 없다면 직접 만들어야 한다.

커스텀 뷰를 만드는 방법은 다음 세가지로 나누어 생각할 수 있다.

  • API에서 제공하는 뷰를 그대로 이용하면서 약간 변형시킨 뷰
  • 여러 뷰를 합쳐서 한번에 출력하기 위한 뷰
  • 기존 API에 전혀 존재하지 않는 뷰

아래에서는 TextView 2개를 합쳐 놓은 customveiw를 만들어 봤다.

FLOW

  1. [customveiw.xml] customview layout 작성
  2. [attrs.xml] view의 속성과 타입을 지정
  3. [CustomView.kt] 생성자와 속성에 따라 뷰를 어떻게 처리할지 코드를 작성
  4. [activity_main.xml] customview를 불러와서 사용하기 

CODE

customview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_key"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:textSize="18sp"
        android:text="my-key"
        android:textStyle="bold"
        android:paddingBottom="8dp"/>

    <TextView
        android:id="@+id/tv_value"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:textSize="16sp"
        android:text="my-value"
        android:paddingBottom="8dp"/>

</LinearLayout>

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="customView">
        <attr name="keyString" format="reference|string" />
        <attr name="keyTextColor" format="reference|integer"/>
        <attr name="valueString" format="reference|string" />
        <attr name="valueTextColor" format="reference|integer"/>
    </declare-styleable>
</resources>

CustomView.kt

커스텀 뷰를 작성할 때 생성자 부분에 주의해야 한다. 작성된 커스텀 뷰를 액티비티에서 이용하려면, (1) 자바 코드로 뷰를 직접 생성하거나 (2) 레이아웃 xml에 등록해야 한다. (1) 자바 코드로 생성해서 이용한다면 생성자는 하나만 정의해도 된다. 하지만 (2) 레이아웃 xml에 등록하여 사용할 때, 생성자가 하나만 정의되어 있으면 에러가 발생한다. 따라서, 커스텀뷰를 레이아웃 xml에 등록해서 이용하려면 생성자 3개를 모두 정의해 주어야 한다.

class CustomView: LinearLayout {
    lateinit var layout : LinearLayout
    lateinit var tvKey : TextView
    lateinit var tvValue : TextView

    constructor(context: Context?) : super(context){
        init(context)
    }
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs){
        init(context)
        getAttrs(attrs)

    }
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : 
    super(context, attrs, defStyleAttr){
        init(context)
        getAttrs(attrs,defStyleAttr)
    }

    private fun init(context:Context?){
        val view = LayoutInflater.from(context).inflate(R.layout.customview,this,false)
        addView(view)

        layout = findViewById(R.id.layout)
        tvKey = findViewById(R.id.tv_key)
        tvValue = findViewById(R.id.tv_value)
    }

    private fun getAttrs(attrs:AttributeSet?){
        val typedArray = context.obtainStyledAttributes(attrs,R.styleable.customView)
        setTypeArray(typedArray)
    }

    private fun getAttrs(attrs:AttributeSet?, defStyle:Int){
        val typedArray = context.obtainStyledAttributes(attrs,R.styleable.customView,defStyle,0)
        setTypeArray(typedArray)
    }

    private fun setTypeArray(typedArray : TypedArray){
        // key string
        val keyString = typedArray.getText(R.styleable.customView_keyString)
        val keyColor = typedArray.getColor(R.styleable.customView_keyTextColor,0)
        tvKey.text = keyString
        tvKey.setTextColor(keyColor)
        
        // value string
        val valueString = typedArray.getText(R.styleable.customView_valueString)
        val valueColor = typedArray.getColor(R.styleable.customView_valueTextColor,0)
        tvValue.text = valueString
        tvValue.setTextColor(valueColor)

        typedArray.recycle()
    }
}

activity_main.xml

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

    <com.example.view.CustomView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:keyString = "test-ing"
        app:keyTextColor="@color/black"
        app:valueString = "test-ing"
        app:valueTextColor="@color/gray" />
</LinearLayout>

RESULT

참고자료

깡샘의 안드로이드 프로그래밍 13장(397~426p)

Comments