332일차 - Custom BottomNavigaion (2)
2021. 12. 2. 19:39ㆍDiary/300~400
완성했다.
간단하게 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>
'Diary > 300~400' 카테고리의 다른 글
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 |