Android Canvas总结

Canvas总结

Canvas类保存“draw”调用。 要绘制一些东西,你需要4个基本组件:Bitmap来保存像素,Canvas来承载绘图调用(写入位图),绘图基元(例如Rect,Path,text,Bitmap),以及Paint来描述绘图的颜色和样式。

一、构造方法

  • Canvas():无参数构造方法
  • Canvas(Bitmap bitmap):有一个指定的Bitmap参数的构造方法
  • Canvas(GL gl):有一个指定的GL上下文的构造方法

二、获取Canvas对象

  • 通过重写View.onDraw方法
  • 自己创建一个Canvas对象
  • 调用SurfaceHolder.lockCanvas(),返回一个Canvas 在 surfaceView 或 TextureView中使用

三、常用的成员方法

  • clipPath(Path path,Region.Op op):根据指定的Path路径裁剪Canvas。
      Path path:指定的路径;
      Region.Op op:裁剪的运算规则。

  • clipRect(float left,float top,float right,float bottom,Region.Op op):根据指定的Rect裁剪Canvas。
      float left:左边偏移量;
      float top:上边偏移量;
      float right:右边偏移量;
      float bottom:下边偏移量;
      Region.Op op:裁剪的运算规则。

  • clipRect(Rect rect,Region.Op op):根据指定的Rect裁剪Canvas。
      Rect rect:矩阵,包含了左、上、右、下坐标;
      Region.Op op:裁剪的运算规则。

  • clipRegion(Region region,Region.Op op):根据指定的Region裁剪Canvas。
      Region region:由数个Rect组成的对象;
      Region.Op op:裁剪的运算规则。

      clip方法都是针对Canvas裁剪而非Canvas中的内容,每次clip方法都相当于新建了一层画布并裁剪。
      上述3个clip方法中都会涉及到Region.Op枚举类。
      下面对这个枚举类做一个解释:
        为了方便说明,把第一次clipRect的绘制范围设为A,第二次clipRect设定的范围设为B。
        Op.DIFFERENCE:旧画布减去新旧两块画布的交集,即只显示A -(A∩B);
        Op.REVERSE_DIFFERENCE:新画布减去新旧两块画布的交集,即显示B-(A∩B)+A;
        Op.INTERSECT,新的画布和当前画布的共同区域,即显示A+(A∩B);
        Op.REPLACE,不论A和B的集合状况,B的范围将全部进行显示,如果和A有交集,则将覆盖A的交集范围,如果A和B不相交,那各自都会完全显示;
        Op.UNION,即A和B的并集范围,即两者所包括的范围的绘制内容都会被显示;
        Op.XOR,新旧两块画布的并集减去两块画布的交集,即(A∪B)-(A∩B);

    /**
     * 测试clip方法
     */
    // 简单测试clip方法
    Rect rect = new Rect(0, 0, 600, 600); // 绘制了(0,0)->(600,600)的矩形
    paint.setColor(Color.BLACK);
    canvas.clipRect(0,0,300,300);// 裁剪出(0,0)->(300,300)的矩形
    canvas.drawRect(rect, paint);

    // 测试clip方法的运算规则
    Path path = new Path();
    path.addRect(0, 0, 200, 200, Path.Direction.CCW);
    paint.setColor(Color.RED);
    canvas.drawPath(path, paint); // 绘制(0,0)->(200,200)的红色矩阵
    // 测试Region.Op.DIFFERENCE的效果
    // 在上面画布绘制上基础上裁剪掉指定的区域,后面的绘制的在这块区域内显示上面绘制的内容
    ccanvas.clipRect(150, 150, 450, 450, Region.Op.DIFFERENCE);
    paint.setColor(Color.YELLOW);
    canvas.drawRect(50, 50, 350, 350, paint);// 绘制(50,50)->(350,350)的黄色矩阵

这里写图片描述

    // 测试Region.Op.REVERSE_DIFFERENCE的效果
    // 和原来的画布结合成一个整块的画布,并将新画布中重合的部分给除掉
    canvas.clipRect(150, 150, 450, 450, Region.Op.REVERSE_DIFFERENCE);
    paint.setColor(Color.YELLOW);
    canvas.drawRect(50, 50, 350, 350, paint);// 绘制(50,50)->(350,350)的黄色矩阵

这里写图片描述

    // 测试Region.Op.INTERSECT的效果
    // 旧画布加上新的画布和当前画布的共同区域
    canvas.clipRect(150, 150, 450, 450, Region.Op.INTERSECT);
    paint.setColor(Color.YELLOW);
    canvas.drawRect(50, 50, 350, 350, paint);// 绘制(50,50)->(350,350)的黄色矩阵

这里写图片描述

    // 测试Region.Op.REPLACE的效果
    // 不论新旧两块canvas的相交情况,新canvas一定完全显示;相交的部分新的会覆盖掉旧的。如果两个canvas不相交,那各自都会完全显示。
    canvas.clipRect(150, 150, 450, 450, Region.Op.REPLACE);
    paint.setColor(Color.YELLOW);
    canvas.drawRect(50, 50, 350, 350, paint);// 绘制(50,50)->(350,350)的黄色矩阵

这里写图片描述

    // 测试Region.Op.UNION的效果
    // 新画布和原来的画布结合成一个整块的画布,后面绘制的图形都将在两个画布上进行显示。即:新旧两块画布的并集。
    canvas.clipRect(150, 150, 450, 450, Region.Op.UNION);
    paint.setColor(Color.YELLOW);
    canvas.drawRect(50, 50, 350, 350, paint);// 绘制(50,50)->(350,350)的黄色矩阵

这里写图片描述

    // 测试Region.Op.XOR的效果
    // 新旧两块画布的并集减去两块画布的交集。
    canvas.clipRect(150, 150, 450, 450, Region.Op.XOR);
    paint.setColor(Color.YELLOW);
    canvas.drawRect(50, 50, 350, 350, paint);// 绘制(50,50)->(350,350)的黄色矩阵

这里写图片描述

  • drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint):在指定的区域内绘制指定的扇形或弧形。
      RectF oval:指定的绘制区域
      float startAngle:扇形开始的角度(默认3点钟方向为零度角);
      float sweepAngle:扇形顺时针扫描的角度;
      boolean useCenter:是否使用中心,如果需要画完整的扇形,则为true,否则为false;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性
        /**
         * 测试drawArc方法
         */
        paint.setColor(Color.BLACK);
        paint.setAntiAlias(true);//消除锯齿,但是会减慢绘制速度
        paint.setStyle(Paint.Style.FILL);// 设置画笔的风格

        // 设置绘制区域
        RectF rect = new RectF(50, 50, 200, 200);
        // 先绘制黑色背景
        canvas.drawRect(rect, paint);
        // 绘制扇形
        paint.setColor(Color.RED);
        canvas.drawArc(rect, 0, 90, true, paint);// 设置使用中心

这里写图片描述

        // 绘制扇形
        paint.setColor(Color.RED);
        canvas.drawArc(rect, 0, 90, false, paint);// 设置不使用中心

这里写图片描述
  设置不使用中心时,可以看到中间的三角形区域消失了。

        // 绘制扇形
        paint.setStyle(Paint.Style.STROKE);// 设置画笔的风格
        paint.setStrokeWidth(5);// 设置画笔风格为STROKE时,必须设置StrokeWidth
        paint.setColor(Color.RED);
        canvas.drawArc(rect, 0, 90, true, paint);// 设置使用中心

这里写图片描述
  将画笔风格设置为STROKE,设置使用中心,则绘制出了一个空心的扇形。并且如果大家仔细看的话,发现空心扇形已经超出了黑色背景的边缘,所以大家使用STROKE时需要考虑到StrokeWidth的宽度对绘制图的影响。

        // 绘制扇形
        paint.setStyle(Paint.Style.STROKE);// 设置画笔的风格
        paint.setStrokeWidth(5);
        paint.setColor(Color.RED);
        canvas.drawArc(rect, 0, 90, false, paint);// 设置不使用中心

这里写图片描述
  再设置不使用中心时,只绘制了一条曲线。

  • drawARGB(int a, int r, int g, int b) :将会以颜色ARBG填充整个控件的Canvas背景。
      int a:alpha,色彩透明度
      int r:red色彩空间
      int g:green色彩空间
      int b:blue色彩空间
        /**
         * 测试ARGB
         */
        canvas.clipRect(50, 50, 250, 250);
        canvas.drawARGB(200, 150, 60, 120);

这里写图片描述

  • drawBitmap(Bitmap bitmap, float left, float top, Paint paint) :绘制位图。
      Bitmap bitmap:位图对象;
      float left:位图在Canvas上偏移左边的位置;
      float top:位图在Canvas上偏移顶部的位置;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。

  • drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) :绘制位图。
      Bitmap bitmap:位图对象;
      Rect src:是对图片进行裁剪,若是空null则显示整个图片;
      Rect dst:位图在Canvas上显示的区域;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。

  • drawCircle(float cx, float cy, float radius, Paint paint):绘制圆形。
      float cx:圆心的x坐标;
      float cy:圆心的y坐标;
      float radius:圆的半径;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。

        /**
         * 测试drawCircle方法
         */
        paint.setColor(Color.GREEN);
        paint.setAntiAlias(true);//消除锯齿,但是会减慢绘制速度
        paint.setStyle(Paint.Style.FILL);// 设置画笔的风格
        // 绘制圆形
        canvas.drawCircle(100, 100, 50, paint);

这里写图片描述
  绘制了一个完整的圆形

        paint.setColor(Color.GREEN);
        paint.setAntiAlias(true);//消除锯齿,但是会减慢绘制速度
        paint.setStyle(Paint.Style.STROKE);// 设置画笔的风格
        paint.setStrokeWidth(5);
        // 绘制圆形
        canvas.drawCircle(100, 100, 50, paint);

这里写图片描述
  这里将画笔的风格设置为STROKE,即空心模式,则绘制了一个圆环。这里同样需要注意的是StrokeWidth的宽度对绘制图的影响。

  • drawColor(int color, PorterDuff.Mode mode):绘制颜色,但是要制定一个mode。
      int color:颜色值
      PorterDuff.Mode mode:绘制颜色的模式

  • drawLine(float startX, float startY, float stopX, float stopY, Paint paint):绘制直线。
      float startX:直线的起点x坐标;
      float startY:直线的起点y坐标;
      float stopX:直线的终点x坐标;
      float stopY:直线的终点y坐标;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。

        /**
         * 测试drawLine
         */
        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.STROKE);// 这里也可以设为FILL,效果是一样的
        paint.setStrokeWidth(10);
        canvas.drawLine(50, 50, 150, 250, paint);

这里写图片描述

  • drawLines(float[] pts, int offset, int count, Paint paint) :该方法用于在画布上绘制多条直线,通过指定直线的端点坐标数组来绘制。该方法可以绘制多条直线,同时也可以指定哪些线段绘制,而哪些线段不绘制。
      float[] pts:多条直线的端点坐标,每条直线占用4个数据;
      int offset:跳过的数据的个数;
      int count:最终实际参与绘制的数据个数;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。
        /**
         * 测试drawLines
         */
        paint.setColor(Color.BLUE);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(5);
        float[] pts = {20, 30, 100, 50, 50, 30, 90, 150, 45, 80, 120, 30};
        canvas.drawLines(pts, paint);

这里写图片描述
  可以一次画出多条直线,4个参数的方法大家可以自己测试一下。

  • drawOval(RectF oval, Paint paint) :绘制一个区域的内切圆或椭圆。
      RectF oval:内切圆或椭圆所在的区域;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。
        /**
         * 测试drawOval方法
         */
        paint.setColor(Color.RED);
        paint.setAntiAlias(true);//消除锯齿,但是会减慢绘制速度
        paint.setStyle(Paint.Style.FILL);// 设置画笔的风格

        // 设置绘制区域
        RectF rect = new RectF(50, 50, 200, 100);

        canvas.drawOval(rect,paint);

这里写图片描述

        paint.setStyle(Paint.Style.STROKE);// 设置画笔的风格
        paint.setStrokeWidth(5);

        // 设置绘制区域
        RectF rect = new RectF(50, 50, 200, 100);

        canvas.drawOval(rect,paint);

这里写图片描述
  不多说,大家都懂的。

  • drawPaint(Paint paint):绘制背景,效果类似于drawColor。
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。

  • drawPath(Path path, Paint paint) :绘制指定的路径。
      Path path:指定的路径;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。

        /**
         * 测试drawPath,绘制出一个三角形
         */
        paint.setColor(Color.RED);
        paint.setAntiAlias(true);//消除锯齿,但是会减慢绘制速度
        paint.setStyle(Paint.Style.FILL);// 设置画笔的风格
        Path path = new Path();
        path.moveTo(50,50);
        path.lineTo(100,50);
        path.lineTo(75,100);
        path.close();
        canvas.drawPath(path,paint);

这里写图片描述
  在这里绘制出什么样的图形完全取决去你的path是什么样的。

  • drawPoint(float x, float y, Paint paint):绘制点,需要在paint中定义画笔宽度(setStrokeWidth)、以及形状(setStrokeCap)。
      float x:绘制的点的x坐标;
      float y:绘制的点的y坐标;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。
        /**
         * 测试drawPoint,绘制出一个点
         */
        paint.setColor(Color.RED);
        paint.setAntiAlias(true);//消除锯齿,但是会减慢绘制速度
        paint.setStyle(Paint.Style.STROKE);// 设置画笔的风格
        paint.setStrokeWidth(20);

        paint.setStrokeCap(Paint.Cap.ROUND);// 设置画笔的形状
        canvas.drawPoint(50,50,paint);

        paint.setColor(Color.GREEN);
        paint.setStrokeCap(Paint.Cap.BUTT);// 设置画笔的形状
        canvas.drawPoint(80,50,paint);

        paint.setColor(Color.BLUE);
        paint.setStrokeCap(Paint.Cap.SQUARE);// 设置画笔的形状
        canvas.drawPoint(120,50,paint);

这里写图片描述

  • drawPoints(float[] pts, int offset, int count, Paint paint):绘制多个点,需要在paint中定义画笔宽度(setStrokeWidth)、以及形状(setStrokeCap)。
      float[] pts:多条点的坐标,每条点占用2个数据;
      int offset:跳过的数据的个数;
      int count:最终实际参与绘制的数据个数;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。

  • drawPosText(char[] text, int index, int count, float[] pos, Paint paint) :按照指定点的坐标绘制文本。(方法已过时)
      char[] text:需要绘制的文本数组
      int index:需要绘制的第一个字符位置;
      int count:实际参与绘制的数据个数;
      float[] pos:被绘制文本的坐标,每个字占用2个数据;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。

  • drawPosText(String text, float[] pos, Paint paint):按照指定点的坐标绘制文本。(方法已过时)
      String text:需要绘制的文本字符串
      float[] pos:被绘制文本的坐标,每个字占用2个数据;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。

        /**
         * 测试drawPosText
         */
        paint.setColor(Color.RED);
        paint.setAntiAlias(true);//消除锯齿,但是会减慢绘制速度
        paint.setStyle(Paint.Style.STROKE);// 设置画笔的风格
        paint.setStrokeWidth(2);
        paint.setTextSize(50);

        String text = "Test";
        float[] pos = {50, 50, 100, 100, 150, 50, 200, 100};
        canvas.drawPosText(text, pos, paint);

这里写图片描述
  现在是空心的字,如果想实现实心的,改变Style。

  • drawRect(float left, float top, float right, float bottom, Paint paint):绘制矩形。
      float left:左边偏移量;
      float top:上边偏移量;
      float right:右边偏移量;
      float bottom:下边偏移量;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。

  • drawRect(Rect r, Paint paint):绘制矩形。
      Rect r:矩形在Canvas上显示的区域;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。

  • drawRGB(int r, int g, int b):绘制Canvas背景色。
      int r:red色彩空间
      int g:green色彩空间
      int b:blue色彩空间

  • drawRoundRect(RectF rect, float rx, float ry, Paint paint):绘制圆角矩形。
      RectF rect:指定的绘制区域
      float rx:x方向的圆角弧度;
      float ry:y方向的圆角弧度;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。

        /**
         * 测试drawRoundRect
         */
        paint.setColor(Color.RED);
        paint.setAntiAlias(true);//消除锯齿,但是会减慢绘制速度
        paint.setStyle(Paint.Style.FILL);// 设置画笔的风格

        RectF rectF = new RectF(50, 50, 200, 200);// 绘制区域
        canvas.drawRoundRect(rectF,10,40,paint);

这里写图片描述
  可能看的不是很清楚,但是还是能看到x方向的弧度与y方向的弧度大小是不一样的,x方向比较尖锐。

  • drawText(char[] text, int index, int count, float x, float y, Paint paint):绘制文本。
      char[] text:需要绘制的文本数组
      int index:需要绘制的第一个字符位置;
      int count:实际参与绘制的字符个数;
      float x:绘制的点的x坐标;
      float y:绘制的点的y坐标,默认是文本的baseLine的y坐标,而不是上沿的y坐标;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。

  • drawText(String text, float x, float y, Paint paint):绘制文本。
      String text:需要绘制的文本字符串
      float x:绘制的点的x坐标;
      float y:绘制的点的y坐标,默认是文本的baseLine的y坐标,而不是上沿的y坐标;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。

  • drawText(String text, int start, int end, float x, float y, Paint paint):绘制文本。
      String text:需要绘制的文本字符串
      int start:开始的字符位置(包含)
      int end:结束的字符位置(不含)
      float x:绘制的点的x坐标;
      float y:绘制的点的y坐标,默认是文本的baseLine的y坐标,而不是上沿的y坐标;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。

        /**
         * 测试drawText
         */
        String text = "12345678";
        Rect bound = new Rect();
        // 获取到text的区域范围,从而可以获取到text的宽高
        paint.getTextBounds(text, 0, text.length(), bound);
        paint.setTextSize(30);
        paint.setColor(Color.RED);
        canvas.drawText(text, 50, 50 + bound.height(), paint);// y指的是text的baseLine的偏移量

这里写图片描述

  • drawTextOnPath(char[] text, int index, int count, Path path, float hOffset, float vOffset, Paint paint):依据路径排版文本。
      char[] text:需要绘制的文本数组
      int index:需要绘制的第一个字符位置;
      int count:实际参与绘制的字符个数;
      Path path:指定的路径;
      float hOffset:水平方向的偏移量;
      float vOffset:垂直方向的偏移量;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。

  • drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint):依据路径排版文本。
      String text:需要绘制的文本字符串
      Path path:指定的路径;
      float hOffset:水平方向的偏移量;
      float vOffset:垂直方向的偏移量;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。

        /**
         * 测试drawTextOnPath
         */
        Path path = new Path();
        path.addRect(50, 50, 350, 350, Path.Direction.CW);// 添加一个矩形,并设置矩形的方向为顺时针方向
        paint.setColor(Color.GREEN);
        paint.setAntiAlias(true);//消除锯齿,但是会减慢绘制速度
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(3);
        canvas.drawPath(path,paint);// 先绘制出矩形,便于观察

        String text = "canvas.drawTextOnPath";
        paint.setTextSize(50);
        paint.setColor(Color.RED);

        canvas.drawTextOnPath(text,path,50,10,paint);

这里写图片描述
  现在是顺时针方向,如果设置Path.Direction.CCW就是逆时针方向。

  • getSaveCount():返回栈中保存的状态,值等于 save()调用次数-restore()调用次数

  • restore():回到上一个save调用之前的状态,如果restore调用的次数大于save方法,会出错。

  • restoreToCount(int saveCount):回到任何一个save()方法调用之前的状态。
      int saveCount:某一个save()方法调用的地方;

  • save():保存当前的matrix和clip到私有的栈中(Skia内部实现)。任何matrix变换和clip操作都会在调用restore的时候还原。

  • save(int saveFlags):传入一个标志,来表示当restore 的时候,哪些参数需要还原。该参数定义在Canvas中,参照下面。save()方法默认的是还原matrix和clip,但是可以使用这个方法指定哪些需要还原。并且只有指定matrix和clip才有效,其余的几个参数是用于saveLayer()和saveLayerAlpha()方法的。
      int saveFlags:指定需要还原哪些参数;
        MATRIX_SAVE_FLAG:需要还原Matrix;
        CLIP_SAVE_FLAG:需要还原Clip;
        HAS_ALPHA_LAYER_SAVE_FLAG:图层的 clip 标记;
        FULL_COLOR_LAYER_SAVE_FLAG:图层的 color 标记;
        CLIP_TO_LAYER_SAVE_FLAG:图层的 clip 标记,在saveLayer 和 saveLayerAlpha Android强烈建议必须加上他;
        ALL_SAVE_FLAG:还原所有,一般情况都是使用这个;

  • saveLayer(float left, float top, float right, float bottom, Paint paint, int saveFlags):保存当前图层到栈中。
      float left:左边偏移量;
      float top:上边偏移量;
      float right:右边偏移量;
      float bottom:下边偏移量;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。
      int saveFlags:指定需要还原哪些参数;

  • saveLayer(RectF bounds, Paint paint, int saveFlags):保存当前图层到栈中。
      RectF bounds:图层所在的区域;
      Paint paint:画笔,定义绘制的颜色、Style风格等属性。
      int saveFlags:指定需要还原哪些参数;

  • saveLayerAlpha(float left, float top, float right, float bottom, int alpha, int saveFlags):本身和save方法差不多,但是它单独分配了一个画布用于绘制图层。它定义了一个画布区域(可设置透明度),此方法之后的所有绘制都在此区域中绘制,直到调用canvas.restore()方法。
      float left:左边偏移量;
      float top:上边偏移量;
      float right:右边偏移量;
      float bottom:下边偏移量;
      int alpha:透明度;
      int saveFlags:指定需要还原哪些参数;

  • saveLayerAlpha(RectF bounds, int alpha, int saveFlags):本身和save方法差不多,但是它单独分配了一个画布用于绘制图层。它定义了一个画布区域(可设置透明度),此方法之后的所有绘制都在此区域中绘制,直到调用canvas.restore()方法。
      RectF bounds:图层所在的区域;
      int alpha:透明度;
      int saveFlags:指定需要还原哪些参数;

  • rotate(float degrees, float px, float py):绕x,y支点旋转Canvas,默认绕(0,0)点。
      float degrees:旋转角度;
      float px:支点的x坐标;
      float py:支点的y坐标;

  • scale(float sx, float sy, float px, float py):放大Canvas。
      float sx:x轴方向放大倍数;
      float sy:y轴方向放大倍数;
      float px:支点的x坐标;
      float py:支点的y坐标;

  • setBitmap(Bitmap bitmap):设置Canvas到指定的Bitmap位图中绘制。
      Bitmap bitmap:位图。

  • translate(float dx, float dy):Canvas平移到指定的点。
      float dx:平移到的点的x坐标;
      float dy:平移到的点的y坐标;

目前Canvas的总结就这样,后面我会持续更新Canvas各方法的应用场景与应用方法。对Paint、Path的总结即将开始,敬请期待。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值