简单实现QQ空间同款切换Tab
2020-02-10 本文已影响0人
songdehuai
首先来看看QQ空间的Tab栏,中间一个加号,四个切换tab,接下来使用自定义VIew的方式来简单的实现这个Tab切换栏
image.png与实际不同的效果都可以通过微调+换图片的方式来调整
来看看自定义出来的效果
屏幕录制2020-02-10上午12.15.25.2020-02-10 00_19_08.gif接下来来看看如何实现
1,首先使用xml拼出来这个Tab栏的基本样式
<?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"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:weightSum="5"
app:layout_constraintBottom_toBottomOf="parent">
<View1
android:layout_weight="1"
...
/>
<View2
android:layout_weight="1"
...
/>
<View3
android:layout_weight="1"
...
/>
<View4
android:layout_weight="1"
...
/>
<View5
android:layout_weight="1"
...
/>
</LinearLayout>
这里是使用LinearLayout的权重,来放5个View,里面使用任意布局,任意控件排列组合出基本样式,下面给出一个Tab的样式。最后放完整xml代码
<LinearLayout
android:id="@+id/ll_home"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_home"
android:layout_width="24dp"
android:layout_height="24dp"
android:background="@drawable/selector_home" />
<TextView
android:id="@+id/tv_home"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="首页"
android:textColor="#1186DE" />
</LinearLayout>
2,接下来创建自定义view代码,用于切换各个Tab的样式和状态
package com.qquaze.widget
import android.content.Context
import android.graphics.Color
import android.util.AttributeSet
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.qquaze.R
/**
* QQ空间简单切换控件
* @author songdehuai
*/
class MainTabView : LinearLayout {
private val tvHome by lazy { findViewById<TextView>(R.id.tv_home) }
private val tvPerson by lazy { findViewById<TextView>(R.id.tv_person) }
private val tvMsg by lazy { findViewById<TextView>(R.id.tv_msg) }
private val tvVideo by lazy { findViewById<TextView>(R.id.tv_video) }
private val ivHome by lazy { findViewById<ImageView>(R.id.iv_home) }
private val ivPerson by lazy { findViewById<ImageView>(R.id.iv_person) }
private val ivMsg by lazy { findViewById<ImageView>(R.id.iv_msg) }
private val ivVideo by lazy { findViewById<ImageView>(R.id.iv_video) }
private val llHome by lazy { findViewById<LinearLayout>(R.id.ll_home) }
private val llAdd by lazy { findViewById<LinearLayout>(R.id.ll_add) }
private val llPerson by lazy { findViewById<LinearLayout>(R.id.ll_person) }
private val llMsg by lazy { findViewById<LinearLayout>(R.id.ll_msg) }
private val llVideo by lazy { findViewById<LinearLayout>(R.id.ll_video) }
private lateinit var mListener: ListenerBuilder
var select = 0
set(value) {
switchStatus(value)
field = value
}
fun setListener(listenerBuilder: ListenerBuilder.() -> Unit) {
mListener = ListenerBuilder().also(listenerBuilder)
}
constructor(context: Context?) : super(context) {
initViews()
}
constructor(context: Context?, attrs: AttributeSet?) : super(
context,
attrs
) {
initViews()
}
constructor(
context: Context?,
attrs: AttributeSet?,
defStyleAttr: Int
) : super(context, attrs, defStyleAttr) {
initViews()
}
private fun initViews() {
//绑定xml
inflate(context, R.layout.view_tab, this)
//设置初始样式
ivHome.isSelected = true
//为每个Tab设置点击事件
llHome.setOnClickListener {
select = 0
mListener.mTabClickAction?.invoke(select)
switchStatus(select)
}
llMsg.setOnClickListener {
select = 1
mListener.mTabClickAction?.invoke(select)
switchStatus(select)
}
llAdd.setOnClickListener { mListener.mAddClickAction?.invoke() }
llPerson.setOnClickListener {
select = 3
mListener.mTabClickAction?.invoke(select)
switchStatus(select)
}
llVideo.setOnClickListener {
select = 4
mListener.mTabClickAction?.invoke(select)
switchStatus(select)
}
}
/**
* 切换选中项的状态
*/
private fun switchStatus(select: Int) {
when (select) {
0 -> {
switchView(tvHome, ivHome)
}
1 -> {
switchView(tvMsg, ivMsg)
}
2 -> {
//选中项为Add的时候,不做任何切换处理
}
3 -> {
switchView(tvPerson, ivPerson)
}
4 -> {
switchView(tvVideo, ivVideo)
}
}
}
/**
* 切换选择控件的状态
* 这里做一个比较懒的方法,
* 即先把所有View的状态改为未选中的样式,
* 之后在把需要设置成选中状态的view改为选中状态,
* 逻辑上不是很对,不过不影响使用,也看不出来瑕疵
*/
private fun switchView(tv: TextView, iv: ImageView) {
tvHome.setTextColor(Color.parseColor("#767678"))
tvPerson.setTextColor(Color.parseColor("#767678"))
tvMsg.setTextColor(Color.parseColor("#767678"))
tvVideo.setTextColor(Color.parseColor("#767678"))
ivHome.isSelected = false
ivPerson.isSelected = false
ivMsg.isSelected = false
ivVideo.isSelected = false
tv.setTextColor(Color.parseColor("#FDC90F"))
iv.isSelected = true
}
/**
* 监听
*/
inner class ListenerBuilder {
internal var mAddClickAction: (() -> Unit)? = null
internal var mTabClickAction: ((Int) -> Unit)? = null
fun onAddClick(action: () -> Unit) {
mAddClickAction = action
}
fun onTabClick(action: (Int) -> Unit) {
mTabClickAction = action
}
}
}
完整的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="50dp"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:weightSum="5"
app:layout_constraintBottom_toBottomOf="parent">
<LinearLayout
android:id="@+id/ll_home"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_home"
android:layout_width="24dp"
android:layout_height="24dp"
android:background="@drawable/selector_home"
tools:src="@drawable/ic_home_yes" />
<TextView
android:id="@+id/tv_home"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="首页"
android:textColor="#FDC90F" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_msg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_msg"
android:layout_width="24dp"
android:layout_height="24dp"
android:background="@drawable/selector_msg" />
<TextView
android:id="@+id/tv_msg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="消息"
android:textColor="#767678" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:gravity="center">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:background="#FDC90F" />
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_centerInParent="true"
android:src="@drawable/ic_add_center" />
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/ll_person"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_person"
android:layout_width="24dp"
android:layout_height="24dp"
android:background="@drawable/selector_person" />
<TextView
android:id="@+id/tv_person"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="我的"
android:textColor="#767678" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_video"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_video"
android:layout_width="24dp"
android:layout_height="24dp"
android:background="@drawable/selector_video" />
<TextView
android:id="@+id/tv_video"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="首页"
android:textColor="#767678" />
</LinearLayout>
</LinearLayout>
给出其中一个selector_video的代码,其余就是换个图片
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_home_yes" android:state_selected="true" />
<item android:drawable="@drawable/ic_home_no" android:state_selected="false" />
</selector>
3,接下来看看如何使用
tab_main.setListener {
onAddClick {
toast("添加")
}
onTabClick {
toast("点击了:$it")
}
}