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); } }下面是绘制的效果图