핀수로그
  • [Android] 커스텀뷰 만들기
    2023년 10월 04일 22시 38분 31초에 업로드 된 글입니다.
    작성자: 핀수
    728x90
    반응형

    커스텀뷰

    xml (view)에서의 모듈화는 CustomView로 해결이 가능하다.

     

    이렇게 생긴 버튼이 있다.

    <androidx.appcompat.widget.AppCompatButton
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:autoSizeMaxTextSize="20sp"
            android:autoSizeStepGranularity="1sp"
            android:autoSizeTextType="uniform"
            android:background="@drawable/bg_responsive_button"
            android:gravity="center"
            android:text="Sign up with Google"
            android:textAllCaps="false"
            android:textColor="@color/black"
            app:layout_constraintEnd_toStartOf="@+id/guideline6"
            app:layout_constraintHeight_percent="0.06"
            app:layout_constraintStart_toStartOf="@+id/guideline3"
            app:layout_constraintTop_toTopOf="@+id/guideline4" />

    이런 화면을 만들어야 한다고 할때,

    저 버튼 네개를 복붙해서 만들면 되겠지? 라고 생각할 수 있다.

    그렇지만 만약 어떤 수정사항이 생긴다면? 네번 수정을 해주어야 한다.

    그러다 보면 그 과정에서 생기는 오류나 실수는 아주 자연스러운 수순이 된다. (경험담

    이를 방지하고자 style을 사용했지만..좀 더 쌈빡한 방법은 없을까? 라고 생각이 되어질 때 쯤에서야

    CustomView를 알게 되었다…….늦었다고 생각할 때가 가장 빠른 법

    얼른 알아보자.

    만들기

    1. xml 작업하기

    생성할 커스텀 뷰의 xml 작업을 먼저 진행해준다.

    나의 경우 앞에 아이콘이 붙은 버튼을 하나 만들었다.

    이제 여기서 아이콘과 텍스트를 받도록 할 것이다.

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 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:padding="8dp"
        android:background="@drawable/bg_responsive_button">
    
        <ImageView
            android:id="@+id/symbol"
            android:layout_width="0dp"
            android:layout_height="50dp"
            android:padding="4dp"
            app:layout_constraintHorizontal_weight="1"
            android:src="@drawable/img_google_logo"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/text"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <TextView
            android:id="@+id/text"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="Sign up with Google"
            style="@style/JoinText"
            app:layout_constraintHorizontal_weight="9"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/symbol"
            app:layout_constraintTop_toTopOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>

    2. attrs.xml 만들기

    커스텀뷰에 들어갈 속성을 정의한다.

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="JoinViaSocialButton">
            <attr name="bg" format="reference|integer" />
            <attr name="symbol" format="reference|integer" />
            <!-- 이 attr은 나중에 app:text="....." 로 쓰일수 있으며 '가나다라' 같은 직접적인 String과 @string/aaaa 같은 reference를 넣어줄 수 있습니다.  -->
            <attr name="text" format="reference|string" />
            <attr name="textColor" format="reference|integer" />
        </declare-styleable>
    </resources>

    3. CustomView 만들기

    1) 생성자

    class JoinViaSocialButton : ConstraintLayout {
    		constructor(context: Context): super(context) { initView() }
    		constructor(context: Context, attrs: AttributeSet): super(context, attrs){
    		    initView()
    		    getAttrs(attrs)
    		}
    	...
    }

    2) initView

    ViewBinding 기준으로 작성

    - 미리 만들어둔 xml 파일을 할당

    - 각각의 view 설정

    private lateinit var bg: ConstraintLayout
    private lateinit var symbol: ImageView
    private lateinit var text: TextView
    
    private val binding: JoinViaSocialButtonBinding by lazy {
        JoinViaSocialButtonBinding.bind(
            LayoutInflater.from(context).inflate(R.layout.join_via_social_button, this, false)
        )
    }
    
    private fun initView(){
        addView(binding.root)
    
        bg = binding.root
        symbol = binding.symbol
        text = binding.text
    }

    3) getAttrs()

    attrs.xml 에 선언해둔 속성들을 이용해 각각의 view에 설정

    private fun getAttrs(attrs: AttributeSet){
        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.JoinViaSocialButton)
        setTypeArray(typedArray)
    }
    
    private fun setTypeArray(typedArray: TypedArray){
        binding.run {
            val bgId = typedArray.getResourceId(R.styleable.JoinViaSocialButton_bg, R.drawable.bg_responsive_button)
            bg.setBackgroundResource(bgId)
    
            val symbolId = typedArray.getResourceId(R.styleable.JoinViaSocialButton_symbol, R.drawable.img_google_logo)
            symbol.setImageResource(symbolId)
    
            val defColorId = context.resources.getColor(R.color.black, null)
            val textColor = typedArray.getColor(R.styleable.JoinViaSocialButton_textColor, defColorId)
            text.setTextColor(textColor)
    
            val textString = typedArray.getString(R.styleable.JoinViaSocialButton_text)
            text.text = textString
    
            typedArray.recycle()
        }
    }

    4) 나머지 코드 작성

    fun setBg(resourceId: Int){
        bg.setBackgroundResource(resourceId)
    }
    
    fun setSymbol(resourceId: Int) {
        symbol.setImageResource(resourceId)
    }
    
    fun setTextColor(colorId: Int){
        text.setTextColor(colorId)
    }
    
    fun setText(textString: String){
        text.text = textString
    }
    
    fun setText(textId: Int){
        text.text = context.getText(textId)
    }

    사용하기

        <com.pinslog.navermapsample.view.custom.JoinViaSocialButton
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:text="Sign up with Google"
            app:layout_constraintEnd_toStartOf="@+id/guideline6"
            app:layout_constraintHeight_percent="0.06"
            app:layout_constraintStart_toStartOf="@+id/guideline3"
            app:layout_constraintTop_toTopOf="@+id/guideline4" />


    공부하며 작성된 글이라 잘못된 정보가 있을 수 있습니다.

    말씀해주시면 수정하겠습니다. 감사합니다.

    References

    아래 글을 참고하여 작성 되었습니다.

     

    [Android] Custom View로 생산성 높이기

    사용성 증가

    velog.io

     

     

    [안드로이드/Android]CustomView를 만들어서 재사용하기

    이전 포스팅에서 Style테마를 이용하여 일정한 레이아웃의 속성을 만들고 이를 재사용하는 방법에 대해서 알아 보았습니다.[안드로이드]style테마 활용으로 노가다코딩 줄이는 방법 이 방법보다

    gun0912.tistory.com

     

     

    728x90
    반응형
    댓글