package com.example.smart.widget import android.content.Context import android.graphics.Color import android.os.Parcel import android.os.Parcelable import android.util.AttributeSet import android.view.ViewGroup import android.view.ViewTreeObserver import android.view.animation.AccelerateDecelerateInterpolator import android.view.animation.Interpolator import android.widget.LinearLayout import androidx.annotation.DrawableRes import androidx.core.view.ViewCompat import com.example.smart.observer.TabEventProvider import java.util.* /** * desc: 首页底部导航栏 */ class HomeTabLayout @JvmOverloads constructor( context: Context, val tabProvider: TabEventProvider, attrs: AttributeSet? = null, defStyleAttr: Int = 0, ) : LinearLayout(context, attrs, defStyleAttr) { private val TRANSLATE_DURATION_MILLIS = 200 private val mInterpolator: Interpolator = AccelerateDecelerateInterpolator() private var mVisible = true private lateinit var mTabLayout: LinearLayout private lateinit var mTabParams: LayoutParams private var mCurrentPosition = 0 private lateinit var itemTabs: MutableList companion object { fun create(context: Context, tabProvider: TabEventProvider) = HomeTabLayout(context, tabProvider) fun buildItem(context: Context, @DrawableRes icon: Int?, tabName: String?) = HomeTabView(context, icon, tabName) } init { initView() } private fun initView() { itemTabs = ArrayList() mTabLayout = LinearLayout(context) mTabLayout.setBackgroundColor(Color.WHITE) mTabLayout.orientation = HORIZONTAL addView( mTabLayout, LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT ) ) } fun addItem(tab: HomeTabView): HomeTabLayout { // itemTabs.add(tab) tab.setTabPosition(mTabLayout.childCount) mTabParams = LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT) mTabParams.weight = 1f tab.layoutParams = mTabParams tab.setOnClickListener { val pos = tab.getTabPosition() if (mCurrentPosition == pos) { tabProvider.tabClick(pos, pos) } else { tab.isSelected = true mTabLayout.getChildAt(mCurrentPosition).isSelected = false tabProvider.tabClick(pos, mCurrentPosition) mCurrentPosition = pos } } mTabLayout.addView(tab) return this } fun setCurrentItem(position: Int) { mTabLayout.post { mTabLayout.getChildAt(position).performClick() } } override fun onSaveInstanceState(): Parcelable { val superState = super.onSaveInstanceState() return SavedState(superState, mCurrentPosition) } override fun onRestoreInstanceState(state: Parcelable) { val ss = state as SavedState super.onRestoreInstanceState(ss.superState) if (mCurrentPosition != ss.position) { mTabLayout.getChildAt(mCurrentPosition).isSelected = false mTabLayout.getChildAt(ss.position).isSelected = true } mCurrentPosition = ss.position } class SavedState : BaseSavedState { var position = 0 constructor(source: Parcel) : super(source) { position = source.readInt() } constructor(superState: Parcelable?, position: Int) : super(superState) { this.position = position } override fun writeToParcel(out: Parcel, flags: Int) { super.writeToParcel(out, flags) out.writeInt(position) } companion object CREATOR : Parcelable.Creator { override fun createFromParcel(parcel: Parcel): SavedState { return SavedState(parcel) } override fun newArray(size: Int): Array { return arrayOfNulls(size) } } } fun hide() { hide(true) } fun show() { show(true) } fun hide(anim: Boolean) { toggle(false, anim, false) } fun show(anim: Boolean) { toggle(true, anim, false) } fun isVisible(): Boolean { return mVisible } fun toggle(visible: Boolean, anim: Boolean, force: Boolean) { if (mVisible != visible || force) { mVisible = visible val height = height if (height == 0 && !force) { val vto = viewTreeObserver if (vto.isAlive) { // view树完成测量并且分配空间而绘制过程还没有开始的时候播放动画。 vto.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener { override fun onPreDraw(): Boolean { val currentVto = viewTreeObserver if (currentVto.isAlive) { // currentVto.removeOnPreDrawListener(object) } toggle(visible, anim, true) return true } }) return } val translationY = if (visible) 0 else height if (anim) { animate().setInterpolator(mInterpolator) .setDuration(TRANSLATE_DURATION_MILLIS.toLong()) .translationY(translationY.toFloat()) } else { ViewCompat.setTranslationY(this, translationY.toFloat()) } } } } }