Android 仿淘宝订单状态tab(可以滑动、带红点badge)

Android 滑动tab、仿淘宝订单状态滑动tab、带红点badge。可以单独使用和ViewPager+Fragment使用

说明

1、起初网上搜了个控件PagerSlidingTabStrip 发现已经很久不更新了,点击tab时候没有动画,不能自己单独使用,自己重写了他的功能即可以配合ViewPager亦可以单独使用
2、内部逻辑重新更改

实现效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实现代码

PagerSlidingTabStrip.java


import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas; 
import android.graphics.Paint;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
* Copyright (C), 2019, flyzhang
* Author: flyzhang
* Date: 2019/9/19 16:30
* Description:
*  <p>
* </p>     
* History:
* <author>      <time>      <version>      <desc>
* 作者姓名       修改时间     版本号         描述
*/
public class PagerSlidingTabStrip extends LinearLayout {

    private LinearLayout mTabsContainer;
    private ViewPager mViewPager = null;
    private Context mContext;
    private float mLastPosition = 0;//上次点击
    private onTabClickListener mOnTabClickListener;//tab 点击回调
    private boolean mSmoothScroll = false;//点击tab viewpager滚动
    private Paint mIndicatorPaint, mUnderLinePaint;//下划线 最下面线
    private int mIndicatorHeight = 2;//dp 底部滚动线高度
    private int mUnderLineWidth = 21;//dp 底部滚动线宽度
    private float mCurrentPosition = 0;//当前下标
    private float mImageOffset = 2.5f;//dp 减去小红点位置
    private boolean mAutoHideBadge = true;//默认自动滚到位置隐藏

    private int mSelectTabTextColor = 0xFF07AF39;//tab 选中字体颜色
    private int mUnSelectTabTextColor = 0xFF080808;//tab 未选中字体颜色
    private int mIndicatorColor = 0xFF1FB84D;//下划线color
    private int mUnderIndicatorRound = 2;
    private int mUnderLineHeight = 2;//下划线高度
    private int mUnderLineColor = 0xFFEFEFEF;//下划线颜色
    private int mUnderShadowColor = 0xFFEFEFEF;
    private int mUnderRadius = 5;//dp
    private int mUnderDx = 0;//dp
    private int mUnderDy = 2;//dp
    private int mTabTextSize = 14;//tab 字体大小
    private int SCREEN_HEIGHT = 0, SCREEN_WIDTH = 0;//屏幕宽高
    private int mTabWidth = 0;//每个tab宽
    private int mLayoutWeight = 0; //tab 样式 当weight == 1是默认评分屏幕




    public PagerSlidingTabStrip(Context context) {
        super(context);
        initView(context);
    }

    public PagerSlidingTabStrip(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }

    private void initView(Context context) {
        setWillNotDraw(false);
        mContext = context;
        DisplayMetrics dm = getResources().getDisplayMetrics();
        mUnderLineWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mUnderLineWidth, dm);
        mImageOffset = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mImageOffset, dm);
        mIndicatorHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mIndicatorHeight, dm);
        mUnderRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mUnderRadius, dm);
        mUnderDx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mUnderDx, dm);
        mUnderDy = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mUnderDy, dm);
        mUnderIndicatorRound = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mUnderIndicatorRound, dm);
        mUnderLineHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mUnderLineHeight, dm);
        setOrientation(VERTICAL);
        mTabsContainer = new LinearLayout(mContext);
        mTabsContainer.setOrientation(LinearLayout.HORIZONTAL);
        mTabsContainer.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
        addView(mTabsContainer);


        mIndicatorPaint = new Paint();
        mIndicatorPaint.setColor(mIndicatorColor);
        mIndicatorPaint.setAntiAlias(true);
        mIndicatorPaint.setStyle(Paint.Style.FILL);

        mUnderLinePaint = new Paint();
        // 设定颜色
        mUnderLinePaint.setColor(mUnderLineColor);
        // 设定阴影(柔边, X 轴位移, Y 轴位移, 阴影颜色)
        mUnderLinePaint.setShadowLayer(mUnderRadius, mUnderDx, mUnderDy, mUnderShadowColor);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (SCREEN_HEIGHT == 0 || SCREEN_WIDTH == 0) {
            SCREEN_HEIGHT = getHeight();
            SCREEN_WIDTH = getWidth();
        }

        if(mTabWidth <=0){
            mTabWidth = mTabsContainer.getChildAt(0).getWidth();
        }

        int center = mTabWidth / 2;//每一个item 中间位置
        float start = center - mImageOffset;
        int temp = mUnderLineWidth / 2;
        //画底线的线
        canvas.drawRoundRect(mTabWidth * mCurrentPosition + start - temp, SCREEN_HEIGHT - mIndicatorHeight - mUnderLineHeight, mTabWidth * mCurrentPosition + center + temp, SCREEN_HEIGHT - mUnderLineHeight, mUnderIndicatorRound, mUnderIndicatorRound, mIndicatorPaint);
        //画最底下线 带阴影
        canvas.drawLine(0, SCREEN_HEIGHT - mUnderLineHeight, SCREEN_WIDTH, SCREEN_HEIGHT, mUnderLinePaint);

    }

    /**
     * 设置viewpager
     *
     * @param viewPager v
     */
    public void setViewPager(ViewPager viewPager) {
        mViewPager = viewPager;
        if (null == mViewPager.getAdapter()) {
            throw new IllegalStateException("ViewPager does not have adapter instance.");
        }

        int tabCount = mViewPager.getAdapter().getCount();
        mTabsContainer.removeAllViews();
        for (int i = 0; i < tabCount; i++) {
            CharSequence title = mViewPager.getAdapter().getPageTitle(i);
            if (title == null) {
                throw new IllegalStateException("ViewPager does not Override getPageTitle().");
            }
            addTextTab(i, title.toString());
        }

        mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                //监听组件的滑动。position为当前页面的索引,positionOffset为当前页面偏移的百分比,positionOffsetPixels为当前页面偏移的像素位置
                //Log.e("onPageScrolled", "position:" + position);
                // Log.e("onPageScrolled", "positionOffset:" + positionOffset);
                //Log.e("onPageScrolled", "positionOffsetPixels:" + positionOffsetPixels);
                move(position, positionOffset, positionOffsetPixels);
            }

            @Override
            public void onPageSelected(int position) {
                //监听组件的页面变化。position为当前页面的索引
                //Log.e("onPageSelected", "position:" + position);
                onTabClickListener(position);
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                /**
                 监听组件的滑动状态变化。state有3种取值:
                 ViewPager.SCROLL_STATE_IDLE = 0; 空闲状态,也是初始状态,此时组件是静止的。
                 ViewPager.SCROLL_STATE_DRAGGING = 1; 滑动状态,当手指在屏幕上滑动组件时的状态。
                 ViewPager.SCROLL_STATE_SETTLING = 2; 滑动后自然沉降的状态,当手指离开屏幕后,组件继续滑动时的状态。
                 */
                //Log.e("scrollStateChanged", "state:" + state);
            }
        });
    }

    /**
     * 设置tabs 不适用viewpager
     *
     * @param titles 标题
     */
    public void setTabs(String[] titles) {
        setTabs(titles, null);
    }

    /**
     * 设置tabs 不适用viewpager
     *
     * @param titles             标题
     * @param onTabClickListener 点击回调
     */
    public void setTabs(String[] titles, onTabClickListener onTabClickListener) {
        mTabsContainer.removeAllViews();
        if (null == titles || titles.length == 0) {
            throw new IllegalStateException("titles is null.");
        }
        if (null != onTabClickListener) {
            mOnTabClickListener = onTabClickListener;
        }
        for (int i = 0; i < titles.length; i++) {
            addTextTab(i, titles[i]);
        }

    }

    /**
     * 添加小红点
     *
     * @param p 位置
     */
    public void addBadge(int p) {
        if(mAutoHideBadge && p == 0){
            setBadge(p, false);
        }else{
            setBadge(p, true);
        }

    }

    /**
     * 隐藏小红点
     *
     * @param p 位置
     */
    public void hideBadge(int p) {
        setBadge(p, false);
    }

    /**
     * 隐藏所有小红点
     */
    public void hideAllBadge() {
        int count = mTabsContainer.getChildCount();
        for (int i = 0; i < count; i++) {
            setBadge(i, false);
        }
    }

    /**
     * 红点 显示隐藏
     *
     * @param p     红点位置
     * @param badge 是否显示
     */
    private void setBadge(int p, boolean badge) {
        View v = mTabsContainer.getChildAt(p);
        if (v != null) {
            if (badge) {
                v.findViewById(R.id.iv_msg).setVisibility(VISIBLE);
            } else {
                v.findViewById(R.id.iv_msg).setVisibility(INVISIBLE);
            }
        }
    }

    /**
     * 移动 跟随设置实时的位置
     *
     * @param position             当前选择位置(为当前页面的索引)
     * @param positionOffset       当前位置到下个位置的百分比(为当前页面偏移的百分比)
     * @param positionOffsetPixels 暂时没用(为当前页面偏移的像素位置)
     */
    private void move(int position, float positionOffset, int positionOffsetPixels) {
        mCurrentPosition = position + positionOffset;
        invalidate();
    }


    /**
     * 点击按钮滑动
     *
     * @param nowPosition  下个位置
     * @param smoothScroll 是否 动画
     */
    private void move(final int nowPosition, boolean smoothScroll) {
        if (!smoothScroll) {
            final ValueAnimator anim = ValueAnimator.ofFloat(mCurrentPosition, nowPosition);
            anim.setDuration(200);
            //anim.setInterpolator(new AccelerateInterpolator());
            anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    mCurrentPosition = (float) animation.getAnimatedValue();
                    invalidate();
                }
            });
            anim.start();
        }
        if (null != mViewPager) {
            mViewPager.setCurrentItem(nowPosition, smoothScroll);
        }


    }

    /**
     * 添加tab
     *
     * @param p     position
     * @param title 标题
     */
    private void addTextTab(final int p, String title) {
        View layoutView = View.inflate(getContext(), R.layout.foundation_sliding_tab_layout, null);
        layoutView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                move(p, mSmoothScroll);
                if (null == mViewPager) {
                    onTabClickListener(p);
                }

            }
        });
        if(mLayoutWeight == 1){
            layoutView.setLayoutParams(new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f));//设置是否item平分
        }else{
            layoutView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));//设置是否item平分
        }
        TextView tab = layoutView.findViewById(R.id.tv_content);
        tab.setGravity(Gravity.CENTER);
        //默认第一个位置选中
        if (p == 0) {
            tab.setTextColor(mSelectTabTextColor);
        } else {
            tab.setTextColor(mUnSelectTabTextColor);
        }
        tab.setText(title);
        tab.setTextSize(mTabTextSize);
        tab.setSingleLine();
        mTabsContainer.addView(layoutView);
    }

    /**
     * 点击回调
     *
     * @param p 位置
     */
    private void onTabClickListener(int p) {
        changeTabTextStatus(p, (int) mLastPosition, mAutoHideBadge);

        if (null != mOnTabClickListener && mLastPosition != p) {
            mOnTabClickListener.onTabClick(p);
        }
        mLastPosition = p;
    }

    /**
     * 切换text状态颜色
     *
     * @param current       当前选择tab
     * @param last          上次选择tab
     * @param autoHideBadge 自动隐藏红点
     */
    private void changeTabTextStatus(int current, int last, boolean autoHideBadge) {
        View currentLayoutTab = mTabsContainer.getChildAt(current);
        View lastLayoutTab = mTabsContainer.getChildAt(last);
        TextView currentTab = currentLayoutTab.findViewById(R.id.tv_content);
        if (autoHideBadge) {
            View v = currentLayoutTab.findViewById(R.id.iv_msg);
            if (null != v) {
                v.findViewById(R.id.iv_msg).setVisibility(INVISIBLE);
            }
        }
        TextView lastTab = lastLayoutTab.findViewById(R.id.tv_content);
        currentTab.setTextColor(mSelectTabTextColor);
        lastTab.setTextColor(mUnSelectTabTextColor);
    }

    public onTabClickListener getOnTabClickListener() {
        return mOnTabClickListener;
    }

    public void setOnTabClickListener(onTabClickListener mOnTabClickListener) {
        this.mOnTabClickListener = mOnTabClickListener;
    }

    public boolean isSmoothScroll() {
        return mSmoothScroll;
    }

    public void setSmoothScroll(boolean mSmoothScroll) {
        this.mSmoothScroll = mSmoothScroll;
    }

    public boolean isAutoHideBadge() {
        return mAutoHideBadge;
    }

    public void setAutoHideBadge(boolean mAutoHideBadge) {
        this.mAutoHideBadge = mAutoHideBadge;
    }

    public int getLayoutWeight() {
        return mLayoutWeight;
    }

    public void setLayoutWeight(int mLayoutWeight) {
        this.mLayoutWeight = mLayoutWeight;
    }

    /**
     * tab点击回调
     */
    public interface onTabClickListener {
        void onTabClick(int position);
    }

}

foundation_sliding_tab_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rl_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center">
    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:minWidth="62.5dp"
        android:gravity="center">

        <TextView
            android:id="@+id/tv_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/foundation_app_name" />

        <ImageView
            android:id="@+id/iv_msg"
            android:layout_width="5dp"
            android:layout_height="5dp"
            android:layout_alignTop="@+id/tv_content"
            android:layout_centerVertical="true"
            android:layout_toRightOf="@+id/tv_content"
            android:visibility="invisible"
            android:src="@drawable/foundation_sliding_tab_dot"  />
    </RelativeLayout>

</RelativeLayout>


用法

tabs.setLayoutWeight(0);//设置是否平分充满屏幕 1充满屏幕
tabs.setSmoothScroll(true);//点击tab是否ViewPager进行动画滚动
//tabs.setViewPager(pager);//设置pager 或者设置titles
tabs.setTabs(new String[]{"已完成","已收货","待评价"});//不能和setViewPager同时使用
tabs.setOnTabClickListener(null);//设置点击tab或者活动ViewPager回调
tabs.setAutoHideBadge(true);//设置滚动tab位置自动隐藏小红点
tabs.addBadge(0);//添加小红点位置
tabs.hideAllBadge();
tabs.hideBadge(0);

发布了18 篇原创文章 · 获赞 11 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/INTKILOW/article/details/101080698