一手遮天 Android - view(导航类): TabBar 自己实现

项目地址 https://github.com/webabcd/AndroidDemo
作者 webabcd

一手遮天 Android - view(导航类): TabBar 自己实现

示例如下:

/view/navigation/TabBarDemo1.java

/**
 * 虽然没有官方的 TabBar 控件,但是可以自己实现一个,参见 view/navigation/TabBarDemo1_MyTabBar.java
 */

package com.webabcd.androiddemo.view.navigation;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

import com.webabcd.androiddemo.R;

public class TabBarDemo1 extends AppCompatActivity {

    private TabBarDemo1_MyTabBar mTabBar1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_navigation_tabbardemo1);

        mTabBar1 = findViewById(R.id.tabBar1);

        // 选中的 tab 项发生变化时的回调
        mTabBar1.setOnItemChangedListener(new TabBarDemo1_MyTabBar.OnItemChangedListener() {
            @Override
            public void onItemChanged(int itemIndex) {
                Toast.makeText(TabBarDemo1.this, "selected tab: " + itemIndex, Toast.LENGTH_SHORT).show();
            }
        });
    }
}

\view\navigation\TabBarDemo1_MyTabBar.java

/**
 * 自定义 TabBar 控件,继承自 LinearLayout
 *
 * 本身 LinearLayout 用于水平排列每个 tab 项
 * 每个 tab 项是一个 LinearLayout,用于垂直排列此 tab 项的图标和文本
 */

package com.webabcd.androiddemo.view.navigation;

import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.webabcd.androiddemo.R;
import com.webabcd.androiddemo.utils.Helper;

public class TabBarDemo1_MyTabBar extends LinearLayout {

    // TabBar 的文字
    private String[] mTextList = {"tab1", "tab2", "tab3"};
    // TabBar 的图标(非选中状态)
    private int[] mIconDefaultList = {R.drawable.ic_expand_less, R.drawable.ic_expand_less, R.drawable.ic_expand_less};
    // TabBar 的图标(选中状态)
    private int[] mIconSelectedList = {R.drawable.ic_expand_more, R.drawable.ic_expand_more, R.drawable.ic_expand_more};
    // TabBar 的文字颜色(非选中状态)
    private int mColorDefault = getResources().getColor(R.color.red);
    // TabBar 的文字颜色(选中状态)
    private int mColorSelected = getResources().getColor(R.color.green);
    // TabBar 的背景颜色
    private int mColorBackground = getResources().getColor(R.color.white);

    // 当前选中的 tab 项的索引位置
    private int mSelectedIndex = 0;

    public TabBarDemo1_MyTabBar(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);

        // 本身 LinearLayout 用于水平排列每个 tab 项
        setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, Helper.dp2px(context, 60)));
        setBackgroundColor(mColorBackground);

        // 构造每个 tab 项
        for (int i = 0; i < mTextList.length; i++) {

            // 每个 tab 项是一个 LinearLayout(用于垂直排列此 tab 项的图标和文本)
            final LinearLayout linearLayoutChild = new LinearLayout(context);
            linearLayoutChild.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT, 1));
            linearLayoutChild.setGravity(Gravity.CENTER);
            linearLayoutChild.setOrientation(LinearLayout.VERTICAL);
            linearLayoutChild.setWeightSum(1);
            linearLayoutChild.setTag(i); // tag 值与当前 tab 的索引位置关联
            addView(linearLayoutChild);

            // 某个 tab 项的图标
            LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(Helper.dp2px(context, 26), Helper.dp2px(context, 26));
            lp.setMargins(0, 5, 0, 0);
            ImageView imageView = new ImageView(context);
            imageView.setLayoutParams(lp);
            imageView.setImageResource(mIconDefaultList[i]);
            imageView.setTag("image_" + i); // tag 值与当前 tab 的索引位置关联
            linearLayoutChild.addView(imageView);

            // 某个 tab 项的文字
            lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            lp.setMargins(0, 10, 0, 0);
            TextView textView = new TextView(context);
            textView.setText(mTextList[i]);
            textView.setTextSize(14);
            textView.setTextColor(mColorDefault);
            textView.setGravity(Gravity.CENTER);
            textView.setLayoutParams(lp);
            textView.setTag("text_" + i); // tag 值与当前 tab 的索引位置关联
            linearLayoutChild.addView(textView);

            // 某个 tab 项的点击事件
            linearLayoutChild.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    // 指定当前选中的 tab 项
                    setSelectedTab(v);
                }
            });
        }

        // 初始化选中的 tab 项的图片
        ImageView imageView = findViewWithTag("image_" + mSelectedIndex);
        imageView.setImageResource(mIconSelectedList[mSelectedIndex]);

        // 初始化选中的 tab 项的文本颜色
        TextView textView = findViewWithTag("text_" + mSelectedIndex);
        textView.setTextColor(mColorSelected);

    }

    // 指定当前选中的 tab 项
    private void setSelectedTab(View view) {
        if (mSelectedIndex != (int) view.getTag()) {

            // 设置上一次被选中的 tab 项的图片(现在变为未选中)
            ImageView imageView1 = findViewWithTag("image_" + mSelectedIndex);
            imageView1.setImageResource(mIconDefaultList[mSelectedIndex]);

            // 设置上一次被选中的 tab 项的文本颜色(现在变为未选中)
            TextView textView1 = findViewWithTag("text_" + mSelectedIndex);
            textView1.setTextColor(mColorDefault);

            // 设置当前选中的 tab 项的索引位置
            mSelectedIndex = (int) view.getTag();

            // 设置当前选中的 tab 项的图片
            ImageView imageView = view.findViewWithTag("image_" + mSelectedIndex);
            imageView.setImageResource(mIconSelectedList[mSelectedIndex]);

            // 设置当前选中的 tab 项的文本颜色
            TextView textView = view.findViewWithTag("text_" + mSelectedIndex);
            textView.setTextColor(mColorSelected);

            // 触发选中的 tab 项发生变化时的事件
            performItemChanged(mSelectedIndex);
        }
    }

    // 选中的 tab 项发生变化时的回调
    private OnItemChangedListener mOnItemChangedListener;
    public interface OnItemChangedListener {
        void onItemChanged(int itemIndex);
    }
    public void setOnItemChangedListener(OnItemChangedListener listener) {
        mOnItemChangedListener = listener;
    }
    protected void performItemChanged(int itemIndex) {
        if (mOnItemChangedListener != null) {
            mOnItemChangedListener.onItemChanged(itemIndex);
        }
    }
}

/layout/activity_view_navigation_tabbardemo1.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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!--
        自定义 TabBar 控件(参见 view/navigation/TabBarDemo1_MyTabBar.java)
    -->
    <com.webabcd.androiddemo.view.navigation.TabBarDemo1_MyTabBar
        android:id="@+id/tabBar1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

项目地址 https://github.com/webabcd/AndroidDemo
作者 webabcd

上一篇:Android LinearLayout布局 实现十二生肖的跳转


下一篇:Android笔记——线性布局(LinearLayout)