简单实现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")

    }

}
上一篇下一篇

猜你喜欢

热点阅读