Android开发Android开发经验谈Android开发

仿微信底部导航栏BottomNavigation渐变色

2018-06-15  本文已影响53人  HarveyLegend
ezgif.com-video-to-gif.gif

不说废话了,直接上代码:

自定义View
/**
 * <pre>
 *     author : Harvey
 *     time   : 2018/06/14
 *     desc   :navigation icon自定义view,可以通过设置透明度实现类似微信效果
 * </pre>
 */
public class NavigationIconView extends View {

    private Paint mPaint;
    private Paint textPaint;
    private Bitmap selectedBitmap;
    private Bitmap unselectedBitmap;
    private Rect textRect;
    private int unSelectColor;
    private int selectColor;
    private String tabText;
    private int alphaValue = 0;
    private boolean selected;
    private int mWidth;
    private int textWidth;
    private float iconPadding;//默认icon和文字间距10
    private ArgbEvaluator mColorEvaluator;
    private int textColor;

    public NavigationIconView(Context context) {
        super(context);
    }

    public NavigationIconView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public NavigationIconView(Context context, AttributeSet attrs, int defStyleAttr, Paint mPaint) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    public final void init(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.NavigationIconView);
        int selectImg = typedArray.getResourceId(R.styleable.NavigationIconView_tab_select_img, android.R.drawable.ic_menu_add);
        int unSelectImg = typedArray.getResourceId(R.styleable.NavigationIconView_tab_unSelect_img, android.R.drawable.ic_menu_add);
        selectColor = typedArray.getColor(R.styleable.NavigationIconView_tab_select_text_color, Color.BLACK);
        unSelectColor = typedArray.getColor(R.styleable.NavigationIconView_tab_unSelect_text_color, Color.BLACK);
        tabText = typedArray.getString(R.styleable.NavigationIconView_tab_text);
        float tabTextSize = typedArray.getDimension(R.styleable.NavigationIconView_tab_textSize, 14f);
        iconPadding = typedArray.getDimension(R.styleable.NavigationIconView_img_padding, 18f);
        selected = typedArray.getBoolean(R.styleable.NavigationIconView_selected, false);
        typedArray.recycle();
        unselectedBitmap = createBitmap(unSelectImg);
        selectedBitmap = createBitmap(selectImg);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        textPaint = new Paint();
        textPaint.setTextSize(tabTextSize);
        textPaint.setAntiAlias(true);
        //获得绘制文本的宽和高
        textRect = new Rect();
        mPaint.getTextBounds(tabText, 0, tabText.length(), textRect);
        mColorEvaluator = new ArgbEvaluator();
        if (selected) {
            textColor = selectColor;
            alphaValue = 255;
        } else {
            textColor = unSelectColor;
            alphaValue = 0;
        }
        textWidth = getTextWidth(textPaint,tabText);
    }

    private Bitmap createBitmap(int resId) {
        return decodeResource(getResources(), resId);
    }

    private Bitmap decodeResource(Resources resources, int id) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        TypedValue value = new TypedValue();
        getResources().openRawResource(id, value);
        options.inTargetDensity = value.density;//float scale = targetDensity / (float)density;//缩放比例

        return BitmapFactory.decodeResource(resources, id, options);
    }

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        mWidth = Math.max(unselectedBitmap.getWidth(), textWidth);
        int mHeight = unselectedBitmap.getHeight() + textRect.height() + (int) iconPadding;

        if (getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT
                && getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT) {
            setMeasuredDimension(mWidth, mHeight);
        } else if (getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT) {
            setMeasuredDimension(mWidth, heightSize);
        } else if (getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT) {
            setMeasuredDimension(widthSize, mHeight);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        mPaint.setAlpha(255 - alphaValue);
        canvas.drawBitmap(unselectedBitmap, getWidth() / 2 - unselectedBitmap.getWidth() / 2, 0, mPaint); //开始在画板上画原图
        mPaint.setAlpha(alphaValue);
        canvas.drawBitmap(selectedBitmap, getWidth() / 2 - unselectedBitmap.getWidth() / 2, 0, mPaint);
        //绘制文字
        textPaint.setColor(textColor);
        canvas.drawText(tabText, getWidth() / 2 - textWidth / 2, unselectedBitmap.getHeight() + textRect.height() / 2 + (int) iconPadding, textPaint);
    }

    /**
     * 当滑动的时候来调用此方法渐变
     *
     * @param percent =1选中 =0不选中
     */
    public final void changePage(float percent, boolean isNext) {
        if (isNext) {
            textColor = (int) mColorEvaluator.evaluate(percent, unSelectColor, selectColor);//下一tab的颜色值
            alphaValue = (int) (255 * percent);
        } else {
            textColor = (int) mColorEvaluator.evaluate(percent, selectColor, unSelectColor);//当前tab的颜色值
            alphaValue = (int) (255 * (1 - percent));
        }
        invalidate();
    }

    private int getTextWidth(Paint paint, String str) {
        int iRet = 0;
        if (str != null && str.length() > 0) {
            int len = str.length();
            float[] widths = new float[len];
            paint.getTextWidths(str, widths);
            for (int j = 0; j < len; j++) {
                iRet += (int) Math.ceil(widths[j]);
            }
        }
        return iRet;
    }
}

此处要说明一下,不知为何

textRect = new Rect();
mPaint.getTextBounds(tabText, 0, tabText.length(), textRect);

这种方式得到的文字宽度不对。。。只好换了方法。请路过的大神指导一下~

attr文件定义
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="NavigationIconView">
        <attr name="tab_select_img" format="reference" />
        <attr name="tab_unSelect_img" format="reference" />
        <attr name="tab_select_text_color" format="color" />
        <attr name="tab_unSelect_text_color" format="color" />
        <attr name="tab_text" format="string" />
        <attr name="tab_textSize" format="dimension" />
        <attr name="selected" format="boolean" />
        <attr name="img_padding" format="dimension" />
    </declare-styleable>
</resources>

布局文件
<?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="match_parent"
    android:orientation="vertical">

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <LinearLayout
        android:id="@+id/navigation_lay"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ffffff"
        android:orientation="horizontal"
        android:paddingBottom="6dp"
        android:paddingTop="6dp">

        <com.harvey.deomo.ui.NavigationIconView
            android:id="@+id/requirement_iv"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="1"
            app:img_padding="@dimen/dp10"
            app:selected="true"
            app:tab_select_img="@drawable/tab_requirement_select"
            app:tab_select_text_color="@color/title_color"
            app:tab_text="需求反馈"
            app:tab_textSize="@dimen/sp_12"
            app:tab_unSelect_img="@drawable/tab_requirement_unselect"
            app:tab_unSelect_text_color="@color/light_gray" />


        <com.harvey.deomo.ui.NavigationIconView
            android:id="@+id/equip_state_iv"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="1"
            app:img_padding="@dimen/dp10"
            app:tab_select_img="@drawable/tab_state_select"
            app:tab_select_text_color="@color/title_color"
            app:tab_text="设备状态"
            app:tab_textSize="@dimen/sp_12"
            app:tab_unSelect_img="@drawable/tab_state_unselect"
            app:tab_unSelect_text_color="@color/light_gray" />

        <com.harvey.deomo.ui.NavigationIconView
            android:id="@+id/equip_manage_iv"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="1"
            app:img_padding="@dimen/dp10"
            app:tab_select_img="@drawable/tab_equip_manage_selected"
            app:tab_select_text_color="@color/title_color"
            app:tab_text="设备管理"
            app:tab_textSize="@dimen/sp_12"
            app:tab_unSelect_img="@drawable/tab_equip_manage_unselected"
            app:tab_unSelect_text_color="@color/light_gray" />
    </LinearLayout>

</LinearLayout>

Activity部分代码:
public void initView() {
        mFragments.add(requirementFragment);
        mFragments.add(equipmentStateFragment);
        mFragments.add(equipmentManageFragment);
        FragmentAdapter adapter = new FragmentAdapter(getSupportFragmentManager(), mFragments);// 初始化adapter
        viewPager.setAdapter(adapter); // 设置adapter
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                // 当前总的偏移量
                float currentPositionOffsetSum = position + positionOffset;
                // 上次滑动的总偏移量大于此次滑动的总偏移量,页面从右向左进入(手指从右向左滑动)
                boolean rightToLeft = mLastPositionOffsetSum <= currentPositionOffsetSum;
                if (currentPositionOffsetSum == mLastPositionOffsetSum) return;
                int enterPosition;
                int leavePosition;
                float percent;
                if (rightToLeft) {  // 从右向左滑
                    enterPosition = (positionOffset == 0.0f) ? position : position + 1;
                    leavePosition = enterPosition - 1;
                    percent = (positionOffset == 0.0f) ? 1.0f : positionOffset;
                } else {            // 从左向右滑
                    enterPosition = position;
                    leavePosition = position + 1;
                    percent = 1 - positionOffset;
                }
                switchTab(enterPosition, leavePosition, percent);

                mLastPositionOffsetSum = currentPositionOffsetSum;
            }

            @Override
            public void onPageSelected(int position) {

            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });

    }

    private void switchTab(int enterPosition, int leavePosition, float percent) {
        switch (leavePosition) {
            case 0:
                requirementIv.changePage(percent, false);
                equipStateIv.changePage(percent, true);
                equipManageIv.changePage(1, false);
                break;
            case 1:
                switch (enterPosition) {
                    case 0:
                        equipStateIv.changePage(percent,false);
                        requirementIv.changePage(percent,true);
                        equipManageIv.changePage(1,false);
                        break;
                    case 2:
                        equipStateIv.changePage(percent,false);
                        equipManageIv.changePage(percent,true);
                        requirementIv.changePage(1,false);
                        break;
                }
                break;
            case 2:
                equipManageIv.changePage(percent,false);
                equipStateIv.changePage(percent,true);
                requirementIv.changePage(1,false);
                break;
        }
    }

Acitivty中判断viewpager滑动与上一篇文章用到同样的方法。https://www.jianshu.com/p/354c3a89eccc

完。

上一篇 下一篇

猜你喜欢

热点阅读