开源库FlycoRoundView解析

来源:互联网 发布:成都数据恢复 编辑:程序博客网 时间:2024/05/30 22:49

**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);

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

0 0
原创粉丝点击