美文网首页Android自定义ViewAndroid开发经验谈Android技术知识
Android 完全解决: shape绘制虚线, 系统兼容问题

Android 完全解决: shape绘制虚线, 系统兼容问题

作者: liys_android | 来源:发表于2020-04-10 23:55 被阅读0次
    dash.png

    一. 先看系统提供的方法

    水平虚线

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="line">
        <stroke
            android:width="1dp"    ---》  宽度
            android:color="@color/line"   ----》虚线颜色
            android:dashGap="4dp"    ----》虚线间隔宽度
            android:dashWidth="2dp"/>  ---》虚线的宽度
    </shape>
    
    <View
         ...
          android:background="@drawable/shape_dash_line"
          android:layerType="software" />
    

    1. 发现问题:

    (1). 不同的版本或系统容易出现各种问题, 例如: 小米电视5.1或6.0系统都正常, 但是用4.4系统的电视盒子, 直接闪退, 然后日志也没发现什么错误.

    (2). View的宽高要 比 虚线 实际宽高 要大, 不然无法显示, 影响布局精确度.
    例如: 虚线高度1dp, 把View的高=1dp, 虚线是不显示.

    (3). 每次改变虚线的属性(宽度, 间距, 大小, 方向) 都需要新建一个xml文件, 用起来也麻烦.

    2. 解决问题:

    (1). 百度, 谷歌 等搜索.
    能解决部分兼容问题, 但搜到的结果可能是不全面的, 不能从根本上解决.

    (2). 看系统源码解决问题, 哪个版本系统出问题, 就跑去看哪个版本系统源码.
    能从根本上解决(1)(2)两个问题, 但是不适合绝大多数人, 不是每个人都对源码有那么深入理解的. 而且无法解决第3个问题.

    (3). 自定义View, 用Paint绘制虚线.
    和系统版本完全无关, 不用考虑兼容问题, 所有的属性自由控制.

    对比上面3种方法, 最终我决定用第3种方法.

    二. 实现思路

    1.抽取属性

    (1) 方向---orientation 水平和竖直
    (2) 每段实线长度---line_space
    (3) 每段空白长度---blank_space
    (4) 每段实线颜色---line_color

    <!--文件 res/value/attr.xml-->
         <!--虚线-->
        <declare-styleable name="DashLineView">
            <attr name="line_space" format="dimension"/>
            <attr name="blank_space" format="dimension"/>
            <attr name="line_color" format="color"/>
            <attr name="orientation">
                <enum name="horizontal" value="0" />
                <enum name="vertical" value="1" />
            </attr>
        </declare-styleable>
    

    2. java代码具体实现

    1. 继承View
    2. 获取属性, 把属性设置到Paint
    3. 重写onDraw方法绘制.
    public class DashLineView extends View {
    
        private Context context;
        private Paint paint = new Paint();
        private int orientation = 0;
        private int lineColor;
        private int lineSpace;
        private int blankSpace;
        private Path path = new Path();
    
        public DashLineView(Context context) {
            this(context, null);
        }
    
        public DashLineView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public DashLineView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            this.context = context;
            initAttrs(attrs);
            init();
        }
    
        private void initAttrs(AttributeSet attrs){
            if(attrs==null){
                return;
            }
            TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DashLineView);
            orientation = typedArray.getInteger(R.styleable.DashLineView_orientation, 0);
            lineColor = typedArray.getInteger(R.styleable.DashLineView_line_color, Color.WHITE);
            lineSpace = typedArray.getDimensionPixelOffset(R.styleable.DashLineView_line_space, dp2px(5));
            blankSpace = typedArray.getDimensionPixelOffset(R.styleable.DashLineView_blank_space, dp2px(5));
        }
    
        private void init(){
            paint.setColor(lineColor);
            paint.setAntiAlias(true);
            paint.setStyle(Paint.Style.STROKE);
            //绘制长度为lineSpace的实线后再绘制长度为blankSpace的空白区域,0位间隔
            paint.setPathEffect(new DashPathEffect(new float[]{lineSpace, blankSpace}, 0));
    
            post(new Runnable() {
                @Override
                public void run() {
                    //设置画笔宽度
                    if(orientation==0) { //水平
                        paint.setStrokeWidth(getMeasuredHeight());
                    }else{
                        paint.setStrokeWidth(getMeasuredWidth());
                    }
                }
            });
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            path.moveTo(0, 0);
            if(orientation==0){ //水平
                path.lineTo(getWidth(), 0);
            }else{ //垂直
                path.lineTo(0, getHeight());
            }
            canvas.drawPath(path, paint);
        }
    
        /** dp转px */
        public int dp2px(float dpVal){
            return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dpVal, context.getResources().getDisplayMetrics());
        }
    }
    

    3.使用

    <包名.DashLineView
           ...
            app:line_space="2dp"
            app:blank_space="2dp"
            app:line_color="#000000"
            app:orientation="horizontal"/>
    

    总结: 只需自定义View一次, 以后所有项目都可以使用, 无需担心兼容问题.

    相关文章

      网友评论

        本文标题:Android 完全解决: shape绘制虚线, 系统兼容问题

        本文链接:https://www.haomeiwen.com/subject/nzlnphtx.html