332일차 - Custom BottomNavigaion (2)

2021. 12. 2. 19:39·아카이브/일기
반응형

완성했다.

간단하게 XML로 사용하면서

가장 필요한 기능인

어느 화면으로 전환할지에 대한

액션 값을 받아오게끔 했다.

 

 

< BottomNavigationItem >

package navigation

import android.content.Context
import android.content.res.ColorStateList
import android.content.res.Resources
import android.content.res.XmlResourceParser
import android.graphics.Color
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.widget.Checkable
import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView
import com.kwon.mywidgetcollection.R

class BottomNavigationItem(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs), Checkable {
    lateinit var action: String
    lateinit var imageView: AppCompatImageView
    lateinit var textView:AppCompatTextView
    private lateinit var defaultColor: String
    private lateinit var focusColor: String
    private lateinit var disableColor: String
    private val Int.dp: Int get() = (this * Resources.getSystem().displayMetrics.density + 0.5f).toInt()

    init {
        context?.let { con ->
            attrs?.let { attr ->
                initAttrs(con, attr)
            }
        }
    }

    private fun initAttrs(context: Context, attrs: AttributeSet) {
        orientation = VERTICAL
        gravity = Gravity.CENTER

        context.obtainStyledAttributes(attrs, R.styleable.BottomNavigationItem)?.let { typedArray ->
            action = typedArray.getString(R.styleable.BottomNavigationItem_nv_action)!!

            imageView = AppCompatImageView(context)
            with(imageView) {
                val layout = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1f)
                layout.setMargins(0, 0, 0, 4.dp)
                layoutParams = layout
                adjustViewBounds = true
                setImageResource(typedArray.getResourceId(R.styleable.BottomNavigationItem_nv_image_src, 0))
                setBackgroundColor(Color.TRANSPARENT)
                isClickable = false
                addView(this)
            }

            textView = AppCompatTextView(context)
            with(textView) {
                layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
                textAlignment = TextView.TEXT_ALIGNMENT_CENTER
                textView.includeFontPadding = false
                typedArray.getString(R.styleable.BottomNavigationItem_nv_text)?.let {
                    text = it
                }
                addView(textView)
            }

            typedArray.recycle()
        }

    }

    fun itemInit(view: BottomNavigationItem) {
        view.isChecked = false
    }

    fun setTextStyle(id:Int) {
        textView.setTextAppearance(id)
    }

    fun setItemSelector(id: Int) {
        parseXml(resources.getXml(id))
    }

    private fun parseXml(parser: XmlResourceParser) {
        var eventType = -1
        val namespace = "http://schemas.android.com/apk/res/android"

        while (eventType != XmlResourceParser.END_DOCUMENT) {
            if (eventType == XmlResourceParser.START_TAG) {
                if (parser.name == "item") {
                    val stateFocused: String? = parser.getAttributeValue(namespace, "state_focused")
                    val stateEnabled: String? = parser.getAttributeValue(namespace, "state_enabled")
                    val color = resources.getString(parser.getAttributeResourceValue(namespace, "drawable", 0))
                    if(stateFocused != null) {
                        if(stateFocused == "true") focusColor = color else defaultColor = color
                    }
                    if(stateEnabled != null) {
                       disableColor = color
                    }
                }
            }
            eventType = parser.next()
        }
    }

    interface OnCheckedChangeListener {
        fun onCheckedChanged(checkableView: View?, isChecked: Boolean)
    }

    private val checkedStateSet = intArrayOf(android.R.attr.state_checked)
    private var mChecked = false
    private var mOnCheckedChangeListener: OnCheckedChangeListener? = null

    override fun isChecked(): Boolean {
        return mChecked
    }

    override fun setChecked(checked: Boolean) {
        if (checked != mChecked) {
            if(checked) {
                imageView.imageTintList = ColorStateList.valueOf(Color.parseColor(focusColor))
                textView.setTextColor(Color.parseColor(focusColor))
            } else {
                imageView.imageTintList = ColorStateList.valueOf(Color.parseColor(defaultColor))
                textView.setTextColor(Color.parseColor(defaultColor))
            }
            mChecked = checked
            refreshDrawableState()
            if (mOnCheckedChangeListener != null) {
                mOnCheckedChangeListener!!.onCheckedChanged(this, mChecked)
            }
        }
    }

    override fun toggle() {
        isChecked = !mChecked
    }

    override fun onCreateDrawableState(extraSpace: Int): IntArray? {
        val drawableState = super.onCreateDrawableState(extraSpace + 1)
        if (isChecked) {
            mergeDrawableStates(drawableState, checkedStateSet)
        }
        return drawableState
    }

    fun setOnCheckedChangeListener(listener: OnCheckedChangeListener?) {
        mOnCheckedChangeListener = listener
    }
}

 

< 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"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/main_frag"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/main_nav"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent">
    </FrameLayout>

    <navigation.BottomNavigationContainer
        android:id="@+id/main_nav"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:background="#ffffff"
        app:nv_text_styles="@style/bottom_nav_text"
        app:nv_item_selector="@drawable/checkable_bottom_nav"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        >

        <navigation.BottomNavigationItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:nv_image_src="@drawable/bottom_life_record"
            app:nv_text="@string/life_record"
            app:nv_action="@string/action_test"
            />

        <navigation.BottomNavigationItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:nv_image_src="@drawable/bottom_record"
            app:nv_text="@string/record"
            app:nv_action="@string/action_record"
            />

        <navigation.BottomNavigationItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:nv_image_src="@drawable/bottom_home"
            app:nv_text="@string/home"
            app:nv_action="@string/action_home"
            />

        <navigation.BottomNavigationItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:nv_image_src="@drawable/bottom_calendar"
            app:nv_text="@string/calendar"
            app:nv_action="@string/action_calendar"
            />

        <navigation.BottomNavigationItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:nv_image_src="@drawable/bottom_exam"
            app:nv_text="@string/exam"
            app:nv_action="@string/action_exam"
            />


    </navigation.BottomNavigationContainer>

</androidx.constraintlayout.widget.ConstraintLayout>
반응형

'아카이브 > 일기' 카테고리의 다른 글

336일차 - Custom Tap Layout (1)  (0) 2021.12.06
335일차 - IT 영단어 기획서 V.1.1  (0) 2021.12.05
334일차 - 간단한 일기  (0) 2021.12.04
333일차 - 프레그먼트 화면 전환  (0) 2021.12.03
331일차 - Custom BottomNavgation (1)  (0) 2021.12.01
330일차 - 구글 클라우드 플랫폼에서 인보이스가 날라왔다  (0) 2021.11.30
329일차 - IT 영단어 기획서 V1.0  (0) 2021.11.29
328일차 - 휴식  (0) 2021.11.22
'아카이브/일기' 카테고리의 다른 글
  • 334일차 - 간단한 일기
  • 333일차 - 프레그먼트 화면 전환
  • 331일차 - Custom BottomNavgation (1)
  • 330일차 - 구글 클라우드 플랫폼에서 인보이스가 날라왔다
권퓨터
권퓨터
만드는 걸 좋아하는 개발자의 기록. 코드든 글이든, 일단 만들어 봅니다.
  • 권퓨터
    권퓨터: Kwonputer
    권퓨터
  • 티스토리 홈 관리자
  • 전체
    오늘
    어제
    • 분류 전체보기 (559)
      • 개발 (56)
        • 프로젝트 (5)
        • 모바일 (44)
        • 프론트엔드 (0)
        • 백엔드 (2)
        • 인프라 (0)
        • AI · 머신러닝 (4)
      • IT · 테크 (10)
        • 기술 트렌드 (3)
        • 도구 · 생산성 (1)
        • 제품 리뷰 · 추천 (0)
        • 마케팅 · 수익화 (6)
      • 자기계발 (7)
        • 공부법 · 언어 (0)
        • 취업 · 커리어 (7)
      • 아카이브 (486)
        • 일기 (480)
        • 취미 (6)
  • 블로그 메뉴

    • 홈
  • 링크

    • 블로그 이전
  • 공지사항

    • 서브 블로그 => https://kwonputer.com/
  • 인기 글

  • 태그

    내러티브 게임
    https://www.kwonputer.shop/
    Single Table Design
    콘텐츠자동화
    Prompt Engineering
    https://github.com/kwongeneral/kortfolio.git
    서버리스 아키텍처
    파이썬
    aws lambda
    OpenAI GPT
    dynamodb
    python
    injectable
    riverpod
    next.js
    AI블로그
    flutter 면접 질문
    ai 게임 개발
    블로그수익화
    flutter 개발자
    다국어 블로그
    FACEBOOK광고
    python 기초
    AWS CDK
    kotlin
    flutter
    클린 아키텍처
    상태관리
    Clean Architecture
    TypeScript
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
권퓨터
332일차 - Custom BottomNavigaion (2)
상단으로

티스토리툴바