Android中图形的绘制-----自定义View(利用canvas和Path相结合)

Android中绘图的方式有多种,在一些App中与可能会用到,小弟利用闲暇时间在网上找了一点资料进行研究,谨在此汇总一下,希望对用需要的同仁有所帮助。说到自定义控件相信大家都不陌生,这边文章主要介绍的就是利用自定义控件进行绘制。其中主要在onDraw()方法中进行操作。主要用到的有控件Paint(画笔)和Path这两种。下面直接多行代码了,代码中都有注释,不再多做解释:

1.主函数中不用做任何操作,只要在主函数的布局中调用即可:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.wls.pathdraw.MainActivity">

    <view.MyView2
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <view.MyView
        android:id="@+id/view_line"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</RelativeLayout>
2.下面是自定义MyView中的代码。展示的是一种折线图:

public class MyView extends View {
    //原点位置的坐标
    private int xPoint = 260;
    private int yPoint = 760;
    //刻度长度
    private int xScal = 8;//8个单位构成一个刻度
    private int yScal = 40;
    //x轴与y轴坐标轴的长度
    private int xLength = 380;
    private int yLength = 240;
    //横坐标最多可绘制的点
    private int MaxDataSize = xLength/xScal;
    //存放纵坐标所绘制的点
    private List<Integer> yList = new ArrayList<>();
    //y轴刻度上显示字的集合
    private String [] yLable = new String[yLength/yScal];

    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
           if(msg.what == 0){
               MyView.this.invalidate();//刷新view
           }
        }
    };
    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        for(int i = 0; i < yLable.length; i++){
            yLable[i] = (i+1) + "M/s";
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){//在线程中不断往集合中添加数据
                    try {
                        Thread.sleep(1000);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    //判断集合长度是否大于最大绘制长度
                    if(yList.size() > MaxDataSize){
                        yList.remove(0);
                    }
                    //生成1-6的随机数
                    yList.add(new Random().nextInt(5) + 1);
                    mHandler.sendEmptyMessage(0);//发送空消息通知刷新
                }

            }
        }).start();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setAntiAlias(true);
        //画y轴
        canvas.drawLine(xPoint,yPoint - yLength,xPoint,yPoint,mPaint);
        //y轴箭头
        canvas.drawLine(xPoint,yPoint - yLength,xPoint - 3,yPoint - yLength + 6,mPaint);
        canvas.drawLine(xPoint,yPoint - yLength,xPoint + 3,yPoint - yLength + 6,mPaint);
        //绘制刻度和文字
        for(int i = 0; i * yScal < yLength; i++){
            canvas.drawLine(xPoint,yPoint - i * yScal,xPoint + 5,yPoint - i * yScal,mPaint);

            canvas.drawText(yLable[i],xPoint - 50, yPoint - i * yScal,mPaint);
        }
        //画X轴
        canvas.drawLine(xPoint,yPoint,xPoint + xLength,yPoint,mPaint);
        //如果集合中有数据,依次取出进行绘制
       /* if(yList.size() > 1){
            for(int i = 1; i < yList.size(); i ++){
                canvas.drawLine(xPoint + (i - 1) * xScal,yPoint - yList.get(i - 1) * yScal,xPoint + i * xScal,yPoint - yList.get(i) * yScal,mPaint);
            }
        }*/
        //这里也可以使用canvas.drawPath()绘制(无填充)
       /* if(yList.size() > 1){
            Path mPath = new Path();
            mPath.moveTo(xPoint,yPoint - yList.get(0) * yScal);//起点
            for(int i = 1; i < yList.size(); i ++){
                mPath.lineTo(xPoint + i * xScal,yPoint - yList.get(i) * yScal);
            }
            canvas.drawPath(mPath,mPaint);
        }*/
        /*//这里实现填充(无边界)
        mPaint.setStyle(Paint.Style.FILL);//实现填充
        if(yList.size() > 1){
            Path mPath = new Path();
            mPath.moveTo(xPoint,yPoint - yList.get(0) * yScal);//起点
            for(int i = 1; i < yList.size(); i ++){
                mPath.lineTo(xPoint + i * xScal,yPoint - yList.get(i) * yScal);
            }
            mPath.lineTo(xPoint + (yList.size() - 1) * xScal,yPoint);
            canvas.drawPath(mPath,mPaint);
        }*/
        mPaint.setStrokeWidth(5f);//红色边界的填充
        Paint paint = new Paint();
        paint.setColor(Color.BLUE);
        paint.setStyle(Paint.Style.FILL);
        paint.setAntiAlias(true);
        if(yList.size() > 1){
            Path mPath = new Path();
            Path path = new Path();
            mPath.moveTo(xPoint,yPoint - yList.get(0) * yScal);//起点
            path.moveTo(xPoint,yPoint);
            for(int i = 0; i < yList.size(); i ++){
                mPath.lineTo(xPoint + i * xScal,yPoint - yList.get(i) * yScal);
                path.lineTo(xPoint + i * xScal,yPoint - yList.get(i) * yScal);
            }
            path.lineTo(xPoint + (yList.size() - 1) * xScal,yPoint);
            canvas.drawPath(mPath,mPaint);
            canvas.drawPath(path,paint);
        }
    }
}
这里介绍了绘制折线时的两种方法:canvas.drawLine()和canvas.drawPath()。里面对图形的展示有三种形式,无填充色的,有填充色的和有红色边线的三种展现形式,均可以实现。下面的效果图中,只会展示有边界线的。

2.自定义MyView2的代码,这里绘制了空心,实心,渐变色和字体四中样式。绘制的图形分别是圆形,正方形,长方形,椭圆,三角形和梯形,分为四列展示即四中样式。

public class MyView2 extends View {
    
    public MyView2(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);
        /**
         * 第一列,空心
         */
        Paint mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);//空心
        mPaint.setAntiAlias(true);//抗锯齿
        mPaint.setStrokeWidth(3f);

        canvas.drawCircle(40,40,30,mPaint);//圆形
        canvas.drawRect(10,90,70,150,mPaint);//正方形
        canvas.drawRect(10,170,70,200,mPaint);//长方形
        canvas.drawOval(new RectF(10,220,70,250),mPaint);//椭圆形

        Path path = new Path();//运用path绘制三角形
        path.moveTo(10,330);
        path.lineTo(70,330);
        path.lineTo(40,270);
        path.close();//封闭的图形
        canvas.drawPath(path,mPaint);

        Path mPath = new Path();//绘制梯形
        mPath.moveTo(10,410);
        mPath.lineTo(70,410);
        mPath.lineTo(55,350);
        mPath.lineTo(25,350);
        mPath.close();
        canvas.drawPath(mPath,mPaint);
        /**
         * 第二列,实心
         */
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.FILL);//实心
        mPaint.setAntiAlias(true);//抗锯齿
        mPaint.setStrokeWidth(3f);

        canvas.drawCircle(120,40,30,mPaint);//圆形
        canvas.drawRect(90,90,150,150,mPaint);//正方形
        canvas.drawRect(90,170,150,200,mPaint);//长方形
        canvas.drawOval(new RectF(90,220,150,250),mPaint);//椭圆形

        Path path2 = new Path();//运用path绘制三角形
        path2.moveTo(90,330);
        path2.lineTo(150,330);
        path2.lineTo(120,270);
        path2.close();//封闭的图形
        canvas.drawPath(path2,mPaint);

        Path mPath2 = new Path();//绘制梯形
        mPath2.moveTo(90,410);
        mPath2.lineTo(150,410);
        mPath2.lineTo(135,350);
        mPath2.lineTo(105,350);
        mPath2.close();
        canvas.drawPath(mPath2,mPaint);
        /**
         * 第三列,渐变色
         * LinearGradient shader = new LinearGradient(0, 0, endX, endY, new
         * int[]{startColor, midleColor, endColor},new float[]{0 , 0.5f,
         * 1.0f}, TileMode.MIRROR);
         * 参数一为渐变起初点坐标x位置,参数二为y轴位置,参数三和四分辨对应渐变终点
         * 其中参数new int[]{startColor, midleColor,endColor}是参与渐变效果的颜色集合,
         * 其中参数new float[]{0 , 0.5f, 1.0f}是定义每个颜色处于的渐变相对位置,
         * 这个参数可以为null,如果为null表示所有的颜色按顺序均匀的分布
         */
        Shader shader = new LinearGradient(0,0,100,100,
                new int[]{Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW},null, Shader.TileMode.REPEAT);
        // Shader.TileMode三种模式
        // REPEAT:沿着渐变方向循环重复
        // CLAMP:如果在预先定义的范围外画的话,就重复边界的颜色
        // MIRROR:与REPEAT一样都是循环重复,但这个会对称重复
        mPaint.setShader(shader);//用shader中定义的颜色来画
        canvas.drawCircle(200,40,30,mPaint);
        canvas.drawRect(170,90,230,150,mPaint);//正方形
        canvas.drawRect(170,170,230,200,mPaint);//长方形
        canvas.drawOval(new RectF(170,220,230,250),mPaint);//椭圆形

        Path path3 = new Path();//运用path绘制三角形
        path3.moveTo(170,330);
        path3.lineTo(230,330);
        path3.lineTo(200,270);
        path3.close();//封闭的图形
        canvas.drawPath(path3,mPaint);

        Path mPath3 = new Path();//绘制梯形
        mPath3.moveTo(170,410);
        mPath3.lineTo(230,410);
        mPath3.lineTo(215,350);
        mPath3.lineTo(185,350);
        mPath3.close();
        canvas.drawPath(mPath3,mPaint);
        /**
         * 第四列,绘制字体
         */
        mPaint.setTextSize(24);

        canvas.drawText("圆形", 240, 50, mPaint);

        canvas.drawText("正方形", 240, 120, mPaint);

        canvas.drawText("长方形", 240, 190, mPaint);

        canvas.drawText("椭圆形", 240, 250, mPaint);

        canvas.drawText("三角形", 240, 320, mPaint);

        canvas.drawText("梯形", 240, 390, mPaint);

    }

}
下面是绘制的效果图

    

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值