流畅切换的彩色菜单栏:ColorfulNavigationBar

ColorfulNavigationBar

首先附上github项目地址;github.com/csming1995/…

之前在github上看到了一个iOS版本的彩色的菜单栏觉得很有趣,于是模仿了一套Android版本的,并且加上了回弹的效果,让动画看起来更流畅。


这个开源库主要是出于兴趣写的,花了差不多一个下午写了一下。应该还有很多漏洞。

效果如下:

先看一下调用者所需要编写的源码;

public class MainActivity extends AppCompatActivity {

    private ColorfulNavigation mColorfulNavigation;

    private static final int ID_1 = 1;
    private static final int ID_2 = 2;
    private static final int ID_3 = 3;
    private static final int ID_4 = 4;
    private static final int ID_5 = 5;

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

        mColorfulNavigation = findViewById(R.id.colorful_navigation);
        mColorfulNavigation.add(new ColorfulNavigation.Item(ID_1, R.drawable.ic_home_black_24dp, R.color.test1, "Item 1"));
        mColorfulNavigation.add(new ColorfulNavigation.Item(ID_2, R.drawable.ic_home_black_24dp, R.color.test2, "Item 2"));
        mColorfulNavigation.add(new ColorfulNavigation.Item(ID_3, R.drawable.ic_home_black_24dp, R.color.test3, "Item 3"));
        mColorfulNavigation.add(new ColorfulNavigation.Item(ID_4, R.drawable.ic_home_black_24dp, R.color.test4, "Item 4"));
        mColorfulNavigation.add(new ColorfulNavigation.Item(ID_5, R.drawable.ic_home_black_24dp, R.color.test5, "Item 5"));

        mColorfulNavigation.setOnItemSelectedListener(new ColorfulNavigation.OnItemSelectedListener() {
            @Override
            public void onItemSelected(ColorfulNavigation.Item item) {
//                Toast.makeText(MainActivity.this, "" + item.getId(), Toast.LENGTH_SHORT).show();
                switch(item.getId()) {
                    case ID_1 :{
                        break;
                    }
                    case ID_2: {
                        break;
                    }
                    case ID_3 :{
                        break;
                    }
                    case ID_4: {
                        break;
                    }
                    case ID_5: {
                        break;
                    }
                    default:{
                        break;
                    }
                }
            }
        });
    }
}
复制代码

这边使用的时候,在获取到ColorfulNavigation实例后,依次将菜单item的信息new出来后add到ColorfulNavigation中。这边的add方法,内部实现如下:

public void add(@NonNull Item item) {
    ColorfulNavigationItem colorfulNavigationItem = new ColorfulNavigationItem(getContext());
    colorfulNavigationItem.setItem(item);

    LayoutParams layoutParams = new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1f);
    colorfulNavigationItem.setLayoutParams(layoutParams);
    addView(colorfulNavigationItem);

    mIndex = mItems.size();
    item.index = mIndex;
    mItems.add(item);
    mColorfulNavigationItems.add(colorfulNavigationItem);

    mPaint.setColor(getResources().getColor(item.color));
    mRightPaint.setColor(getResources().getColor(item.color));
    requestLayout();
    }
复制代码

先说明一下,ColorfulNavigation的是一个继承于LinearLayout的控件,并且Orientation设置为HORIZONTAL,此处创建一个ColorfulNavigationItem的实例,将其LayoutParams设置为:width=0, weight=1;于是加入到ColorfulNavigation之后会将所有的ColorfulNavigationItem作平铺处理。

动画处理

在用户点击到ColorfulNavigationItem的时候会触发动画效果,以及回调事件。

private void startAnimator(int targetIndex) {
    boolean isRight = mIndex < targetIndex;
    mIndex = targetIndex;
    int targetLeft = mItemWidth * mIndex;
    if (targetLeft != mRectF.left) {
        if (mValueAnimator == null) {
            mValueAnimator = new ValueAnimator();
            mValueAnimatorListener = new ValueAnimatorListener();
            mValueAnimator.addUpdateListener(mValueAnimatorListener);
        }
        mValueAnimator.setFloatValues(mRectF.left, targetLeft, targetLeft + (isRight? 20: - 20), targetLeft);
        mValueAnimator.setDuration(380);
        mValueAnimator.cancel();
        mValueAnimator.start();
    }
}

private class ValueAnimatorListener implements ValueAnimator.AnimatorUpdateListener {

    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        mRectF.left = (float) valueAnimator.getAnimatedValue();
        mRectF.right = mRectF.left + mItemWidth;
        mDrawIndex =  (int) mRectF.left / mItemWidth;
        mRightRectF.left = (mDrawIndex + 1) * mItemWidth;
        mRightRectF.right = mRectF.right;
        mPaint.setColor(getResources().getColor(mItems.get(mDrawIndex).getColor()));
        if (mDrawIndex + 1 < mItems.size()){
            mRightPaint.setColor(getResources().getColor(mItems.get(mDrawIndex + 1).getColor()));
        }
        invalidate();
    }
}
复制代码

这边为了维护一个item在navigation中滑动的效果,在ColorfulNavigation,维护了一个RectF用来绘制滑动中的item。RectF的right-left的值永远的等于该item的宽度,而left的值在起点处的item的left与目标item的left值的渐进移动中获得。item的宽度为ColorfulNavigation的总宽度除以item个数。

ok,接着为了维护在item交界处的两种颜色,这边通过下方的计算得到当前矩阵的左边界所在的位置,然后计算出当前矩阵所处在的边界位置,该边界的右边由于矩阵:mRightRectF绘制。:

mDrawIndex =  (int) mRectF.left / mItemWidth;
复制代码

如果要优化的话,应该将mRectF的右边界设置为矩阵所处在的边界,以减少绘制压力。

该开源库已经上传到github上了;

github.com/csming1995/…

各种求star~~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值