开源库FlycoRoundView解析

**FlycoRoundView
一个扩展原生控件支持圆角矩形框背景的库,可以减少相关shape资源文件使用
支持TextView,FrameLayout,LinearLayout,RelativeLayout,更多使用也可以自己扩展**

1.使用方法


实现以上的效果只需要如下,几个简单的自定义属性,

  <com.flyco.roundview.RoundTextView
            android:id="@+id/rtv_3"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:ellipsize="end"
            android:gravity="center"
            android:paddingBottom="10dp"
            android:paddingLeft="18dp"
            android:paddingRight="18dp"
            android:paddingTop="10dp"
            android:singleLine="true"
            android:text="TextView Radius 10dpTextView Radius 10dp"
            android:textColor="#383838"
            rv:rv_backgroundColor="#F6CE59"
            rv:rv_cornerRadius="10dp" />

自定义xml属性的意思

 <!-- 圆角矩形背景色 -->
    <attr name="rv_backgroundColor" format="color"/>
    <!-- 圆角矩形背景色press -->
    <attr name="rv_backgroundPressColor" format="color"/>
    <!-- 圆角弧度,单位dp-->
    <attr name="rv_cornerRadius" format="dimension"/>
    <!-- 圆角弧度,单位dp-->
    <attr name="rv_strokeWidth" format="dimension"/>
    <!-- 圆角边框颜色-->
    <attr name="rv_strokeColor" format="color"/>
    <!-- 圆角边框颜色press -->
    <attr name="rv_strokePressColor" format="color"/>
    <!-- 文字颜色press-->
    <attr name="rv_textPressColor" format="color"/>
    <!-- 圆角弧度是高度一半-->
    <attr name="rv_isRadiusHalfHeight" format="boolean"/>
    <!-- 圆角矩形宽高相等,取较宽高中大值-->
    <attr name="rv_isWidthHeightEqual" format="boolean"/>
    <!-- 圆角弧度,单位dp,TopLeft-->
    <attr name="rv_cornerRadius_TL" format="dimension"/>
    <!-- 圆角弧度,单位dp,TopRight-->
    <attr name="rv_cornerRadius_TR" format="dimension"/>
    <!-- 圆角弧度,单位dp,BottomLeft-->
    <attr name="rv_cornerRadius_BL" format="dimension"/>
    <!-- 圆角弧度,单位dp,BottomRight-->
    <attr name="rv_cornerRadius_BR" format="dimension"/>
    <!-- 是否有Ripple效果,api21+有效-->
    <attr name="rv_isRippleEnable" format="boolean"/>

代码解析

通过观察源码,主要有如下几个类

  • RoundFrameLayout
  • RoundLinearLayout
  • RoundRelativeLayout
  • RoundTextView
  • RoundViewDelegate


    其中所有的自定义View的代码大致全都是这样
 public RoundRelativeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        //主要逻辑在这里面初始化
        delegate = new RoundViewDelegate(this, context, attrs);
    }

    /** use delegate to set attr */
    public RoundViewDelegate getDelegate() {
        return delegate;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //判断是否设置为是宽高相同
        if (delegate.isWidthHeightEqual() && getWidth() > 0 && getHeight() > 0) {
            int max = Math.max(getWidth(), getHeight());
            int measureSpec = MeasureSpec.makeMeasureSpec(max, MeasureSpec.EXACTLY);
            super.onMeasure(measureSpec, measureSpec);
            return;
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        //判断是否圆角取高的一半
        if (delegate.isRadiusHalfHeight()) {
            delegate.setCornerRadius(getHeight() / 2);
        }else {
            delegate.setBgSelector();
        }
    }

主要代码集中在RoundViewDelegate里面,进去看看
取出xml中的属性 ,如果对自定义xml属性不熟悉–>戳这里Android 深入理解Android中的自定义属性

 //取出xml中的属性
 private void obtainAttributes(Context context, AttributeSet attrs) {
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RoundTextView);
        backgroundColor = ta.getColor(R.styleable.RoundTextView_rv_backgroundColor, Color.TRANSPARENT);
 //~~~省略代码
        isRippleEnable = ta.getBoolean(R.styleable.RoundTextView_rv_isRippleEnable, true);
        ta.recycle();
    }

在各个自定义View中看到,在onLayout中会调用setBgSelector()方法,进去看看


    public void setBgSelector() {
        //StateListDrawable类对应<selector>这个xml标签
        StateListDrawable bg = new StateListDrawable();
        //如果是5.0以上的系统,可以设置水波纹的效果
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && isRippleEnable) {
            setDrawable(gd_background, backgroundColor, strokeColor);
            //对应<ripple>标签
            RippleDrawable rippleDrawable = new RippleDrawable(
                    getPressedColorSelector(backgroundColor, backgroundPressColor), gd_background, null);
            //设置为View背景
            view.setBackground(rippleDrawable);
        } else {
            //设置四个角的圆角弧度,背景颜色
            setDrawable(gd_background, backgroundColor, strokeColor);
            //前面加个‘-’,相当于xml中的 state_pressed属性为false的时候,
            bg.addState(new int[]{-android.R.attr.state_pressed}, gd_background);
            if (backgroundPressColor != Integer.MAX_VALUE || strokePressColor != Integer.MAX_VALUE) {
                //设置按下去的背景色
                setDrawable(gd_background_press, backgroundPressColor == Integer.MAX_VALUE ? backgroundColor : backgroundPressColor,
                        strokePressColor == Integer.MAX_VALUE ? strokeColor : strokePressColor);
                bg.addState(new int[]{android.R.attr.state_pressed}, gd_background_press);
            }
            //设置背景
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {//16
                view.setBackground(bg);
            } else {
                //noinspection deprecation
                view.setBackgroundDrawable(bg);
            }
        }
        //如果是TextView,设置字体的颜色,按下去的颜色
        if (view instanceof TextView) {
            if (textPressColor != Integer.MAX_VALUE) {
                ColorStateList textColors = ((TextView) view).getTextColors();
//              Log.d("AAA", textColors.getColorForState(new int[]{-android.R.attr.state_pressed}, -1) + "");
                ColorStateList colorStateList = new ColorStateList(
                        new int[][]{new int[]{-android.R.attr.state_pressed}, new int[]{android.R.attr.state_pressed}},
                        new int[]{textColors.getDefaultColor(), textPressColor});
                ((TextView) view).setTextColor(colorStateList);
            }
        }
    }

设置背景的方法全都在这里了~比较简单,基本就是把以前只能用xml写死的selector等等标签,用java代码变灵活了!

   private void setDrawable(GradientDrawable gd, int color, int strokeColor) {
        //设置Drawable的背景色
        gd.setColor(color);
        //四个角设置圆角
        if (cornerRadius_TL > 0 || cornerRadius_TR > 0 || cornerRadius_BR > 0 || cornerRadius_BL > 0) {
            /**The corners are ordered top-left, top-right, bottom-right, bottom-left*/
            radiusArr[0] = cornerRadius_TL;
            radiusArr[1] = cornerRadius_TL;
            radiusArr[2] = cornerRadius_TR;
            radiusArr[3] = cornerRadius_TR;
            radiusArr[4] = cornerRadius_BR;
            radiusArr[5] = cornerRadius_BR;
            radiusArr[6] = cornerRadius_BL;
            radiusArr[7] = cornerRadius_BL;
            gd.setCornerRadii(radiusArr);
        } else {
            //全都设置成cornerRadius
            gd.setCornerRadius(cornerRadius);
        }
        //设置边框
        gd.setStroke(strokeWidth, strokeColor);
    }

以下是Drawable Xml对应的的class类

GradientDrawable

<shape> 对应 GradientDrawable
//设置背景颜色
setColor(@ColorInt int argb)
//设置各个角的弧度
setCornerRadii(float[] radii)
//左上角  右上角  右下角  左下角 这里数组长度必须是8位 如下
gradientDrawable1.setCornerRadii(new float[]{0,0,8,8,16,16,32,32});
//设置四个角的弧度
setCornerRadius(float radius)
//设置边框 宽度,和颜色
setStroke(int width, @ColorInt int color)

StateListDrawable

<selector> 对应 StateListDrawable类
主要方法有以下
//对应xml的属性,当前状态下的显示背景
addState(new int[]{-android.R.attr.state_pressed}, gd_background);

这里可以同时设置多个状态比如
  stateListDrawable.addState(
  new int[]{-android.R.attr.state_pressed,
            -android.R.attr.state_checked,
            -android.R.attr.state_selected,gradientDrawable1);

主要用到的就是这两个类了~~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值