Android开发首页底部tab切换图标有动画效果

224 阅读2分钟
Android开发首页底部tab切换图标有动画效果

主页tab切换很正常,但往往加上写动画更好看

一、思路:

用属性动画,并且事先准备多张图片,用于切换后播放动画

二、效果图:

在这里插入图片描述

三、关键代码:
public class TabButtonGroup extends LinearLayout implements View.OnClickListener {

    private TabButton[] mTabButtons;
    private ViewPager mViewPager;
    private int mCurPosition;


    public TabButtonGroup(Context context) {
        this(context, null);
    }

    public TabButtonGroup(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TabButtonGroup(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        int childCount = getChildCount();
        if (childCount > 0) {
            mTabButtons = new TabButton[childCount];
            for (int i = 0; i < childCount; i++) {
                View v = getChildAt(i);
                v.setTag(i);
                v.setOnClickListener(this);
                mTabButtons[i] = (TabButton) v;
            }
        }
    }


    public void setCurPosition(int position) {
        if (position == mCurPosition) {
            return;
        }
        if (mClickIntercepter != null && mClickIntercepter.needIntercept(position)) {
            return;
        }
        mTabButtons[mCurPosition].setChecked(false);
        mTabButtons[position].setChecked(true);
        mCurPosition = position;
        if (mViewPager != null) {
            mViewPager.setCurrentItem(position, false);
        }
    }


    @Override
    public void onClick(View v) {
        Object tag = v.getTag();
        if (tag != null) {
            setCurPosition((int) tag);
        }
    }

    public void setViewPager(ViewPager viewPager) {
        mViewPager = viewPager;
    }

    public void cancelAnim() {
        if (mTabButtons != null) {
            for (TabButton tbn : mTabButtons) {
                if (tbn != null) {
                    tbn.cancelAnim();
                }
            }
        }
    }

    public ClickIntercepter mClickIntercepter;

    public void setClickIntercepter(ClickIntercepter intercepter) {
        mClickIntercepter = intercepter;
    }

    public interface ClickIntercepter {
        boolean needIntercept(int position);
    }


    public void btnPerformClick(int position){
        if (mTabButtons != null&&mTabButtons[position]!=null) {
            mTabButtons[position].performClick();
        }
    }
}
public class TabButton extends LinearLayout {

    private Context mContext;
    private float mScale;
    private String mTip;
    private int mIconSize;
    private int mTextSize;
    private int mTextColorChecked;
    private int mTextColorUnChecked;
    private boolean mChecked;
    private ImageView mImg;
    private TextView mText;
    private Drawable[] mDrawables;
    private int mDrawaleArrayLength;
    private ValueAnimator mAnimator;
    private int mDrawableIndex;

    public TabButton(Context context) {
        this(context, null);
    }

    public TabButton(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TabButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        mScale = context.getResources().getDisplayMetrics().density;
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TabButton);
        int iconArrayId = ta.getResourceId(R.styleable.TabButton_tbn_icon_array_id, 0);
        mTip = ta.getString(R.styleable.TabButton_tbn_tip);
        mIconSize = (int) ta.getDimension(R.styleable.TabButton_tbn_icon_size, 0);
        mTextSize = (int) ta.getDimension(R.styleable.TabButton_tbn_text_size, 0);
        mTextColorChecked = ta.getColor(R.styleable.TabButton_tbn_text_color_checked, 0);
        mTextColorUnChecked = ta.getColor(R.styleable.TabButton_tbn_text_color_unchecked, 0);
        mChecked = ta.getBoolean(R.styleable.TabButton_tbn_checked, false);
        ta.recycle();
        if (iconArrayId != 0) {
            TypedArray arr = getResources().obtainTypedArray(iconArrayId);
            int len = arr.length();
            int[] iconResArray = new int[len];
            for (int i = 0; i < len; i++) {
                iconResArray[i] = arr.getResourceId(i, 0);
            }
            arr.recycle();
            mDrawaleArrayLength = iconResArray.length;
            if (mDrawaleArrayLength > 0) {
                mDrawables = new Drawable[mDrawaleArrayLength];
                for (int i = 0; i < mDrawaleArrayLength; i++) {
                    mDrawables[i] = ContextCompat.getDrawable(context, iconResArray[i]);
                }
            }
        }
        mAnimator = ValueAnimator.ofFloat(1, mDrawaleArrayLength - 1);
        mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float v = (float) animation.getAnimatedValue();
                int index = (int) v;
                if (mDrawableIndex != index) {
                    mDrawableIndex = index;
                    if (mImg != null) {
                        mImg.setImageDrawable(mDrawables[index]);
                    }
                }
            }
        });
        mAnimator.setDuration(500);
        mAnimator.setInterpolator(new LinearInterpolator());
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        setOrientation(VERTICAL);
        setGravity(Gravity.CENTER_HORIZONTAL);
        mImg = new ImageView(mContext);
        LayoutParams params1 = new LayoutParams(mIconSize, mIconSize);
        params1.setMargins(0, dp2px(4), 0, 0);
        mImg.setLayoutParams(params1);
        if (mDrawables != null && mDrawaleArrayLength > 0) {
            if (mChecked) {
                mImg.setImageDrawable(mDrawables[mDrawaleArrayLength - 1]);
            } else {
                mImg.setImageDrawable(mDrawables[0]);
            }
        }
        mText = new TextView(mContext);
        LayoutParams params2 = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        mText.setLayoutParams(params2);
        mText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize);
        mText.setText(mTip);
        mText.setTextColor(mChecked ? mTextColorChecked : mTextColorUnChecked);
        addView(mImg);
        addView(mText);
    }

    public void setChecked(boolean checked) {
        mChecked = checked;
        if (mDrawables != null && mDrawaleArrayLength > 0) {
            if (mChecked) {
                if (mText != null) {
                    mText.setTextColor(mTextColorChecked);
                }
                if (mAnimator != null) {
                    mAnimator.start();
                }
            } else {
                if (mAnimator != null) {
                    mAnimator.cancel();
                }
                if (mImg != null) {
                    mImg.setImageDrawable(mDrawables[0]);
                }
                if (mText != null) {
                    mText.setTextColor(mTextColorUnChecked);
                }
            }
        }
    }

    private int dp2px(int dpVal) {
        return (int) (mScale * dpVal + 0.5f);
    }

    public void cancelAnim() {
        if (mAnimator != null) {
            mAnimator.cancel();
            mAnimator.removeAllUpdateListeners();
        }
    }

}
四、项目demo源码结构图:

在这里插入图片描述

有问题或者需要完整源码看简介联系我,或者私信我