欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android项目刮刮奖详解(三)

程序员文章站 2023-12-05 18:54:22
"Android项目刮刮奖详解(二)" 前言 上一期我们已经实现了一个简易的刮刮卡功能,这一期我们来将其完善一下 目标 + 将刮刮奖的宽高改为合适高度 + 将刮刮奖位置居中 + 将信息层的图片换成文字(重点) 实现 1. 将刮刮奖的宽高改为合适高度和将刮刮奖位置居中 这里其实很简单,我们直接到lay ......

android项目刮刮奖详解(二)

前言

上一期我们已经实现了一个简易的刮刮卡功能,这一期我们来将其完善一下

目标

  • 将刮刮奖的宽高改为合适高度
  • 将刮刮奖位置居中
  • 将信息层的图片换成文字(重点)

    实现

  1. 将刮刮奖的宽高改为合适高度和将刮刮奖位置居中

    这里其实很简单,我们直接到layout布局之中将大小修改一下即可,同时,在布局中利用gravity修改位置

     <?xml version="1.0" encoding="utf-8"?>
     <linearlayout
         xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:app="http://schemas.android.com/apk/res-auto"
         xmlns:tools="http://schemas.android.com/tools"
         android:orientation="vertical"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:gravity="center"
         tools:context="com.wan.guajiang.mainactivity">
    
     <com.wan.guajiang.guaguaka
          android:layout_width="300dp"
          android:layout_height="100dp"/>
    
     </linearlayout>
  2. 将信息层的图片换成文字

之前我们信息层绘制的是中奖图片,如果没有图片怎么办?当然是直接拿文字来代替啦,canvas不仅可以画图片,还可以画文字,写文字

首先,我们来了解一下canvas的drawtext方法参数

drawtext(string text, float x, floaty, paint paint);

text即使要写的文字内容,x,y是写的位置,需要注意的是,这里的x,y坐标并不是文字的左上角,而是一个与左下角比较接近的位置。大概在这里:如图
Android项目刮刮奖详解(三)
最后一个参数就是画笔了,这个画笔设置与之前相似,待会再补充一下

我们想要把文字写在信息层的正中间,x,y的坐标该怎么写呢?由上图可以知道,canvas使用drawtext方法,xy的坐标其实是位于文字的左下角的,下图便是图解

Android项目刮刮奖详解(三)

相信这张图还是很好理解的,我们继续,开始写代码

  • 首先,我们需要个文字内容

      string message = "恭喜中奖,3万元!";
  • 定义我们的画笔paint,对其进行相关设置

    这里得提一下,我们需要一个rect矩形来得到文字内容的背景大小,也就是上图中的红色矩形,paint画笔中提供了一个方法gettextbounds,我们可以通过此方法来获得文字内容的背景大小
    messagepaint.gettextbounds(string text,float start,float end,rect rect);

    上述代码的意思是,截取text文字中的从start到end的长度,将截取的长度和文字的高度形成一个矩形,rect矩形接收这个矩形

      rect mbackground = new rect();//用来接收gettextbounds返回的矩形      
      paint messagepaint = new paint();
      messagepaint.setcolor(color.red);
      messagepaint.setantialias(true);
      messagepaint.setstyle(paint.style.stroke);
      messagepaint.gettextbounds(message,0,message.length(),mbackground);
      messagepaint.settextsize(30);
  • 计算x,y坐标,canvas使用drawtext写出文字
    我们有两种方法来获得之前黑色矩形的长和宽,一种是使用getmeasured,另一种使用mbitmap.get方法来获得长和宽

      canvas.drawtext(message,getmeasuredwidth()/2-mbackground.width()/2,getmeasuredheight()/2+mbackground.height()/2,messagepaint);

    或者:

      canvas.drawtext(message,mbitmap.getwidth()/2-mbackground.width()/2,mbitmap.getheight()/2+mbackground.height()/2,messagepaint);

    测试图

Android项目刮刮奖详解(三)

完整代码

public class guajiangview extends view {

    /**
     * 绘制线条的paint,即用户手指绘制path
     */
    private paint moutterpaint = new paint();
    /**
     * 记录用户绘制的path
     */
    private path mpath = new path();
    /**
     * 内存中创建的canvas
     */
    private canvas mcanvas;
    /**
     * mcanvas绘制内容在其上
     */
    private bitmap mbitmap;

    private int mlastx;
    private int mlasty;

    private string message;//中奖信息
    private rect mbackground;//文字背景矩形大小
    private paint messagepaint = new paint();//文字画笔
    private boolean isclear = false;
    public guajiangview(context context) {
        super(context);

    }



    public guajiangview(context context, @nullable attributeset attrs) {
        super(context, attrs);
    }

    public guajiangview(context context, @nullable attributeset attrs, int defstyleattr) {
        super(context, attrs, defstyleattr);
    }

    public guajiangview(context context, @nullable attributeset attrs, int defstyleattr, int defstyleres) {
        super(context, attrs, defstyleattr, defstyleres);
    }

    @override
    protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
        super.onmeasure(widthmeasurespec, heightmeasurespec);
        log.d(tag, "onmeasure: 测量");
        int width = getmeasuredwidth();
        int height = getmeasuredheight();


        // 初始化bitmap
        mbitmap = bitmap.createbitmap(width, height, bitmap.config.argb_8888);//以获得的宽高创建一个32位的bitmap
        mcanvas = new canvas(mbitmap);//以bitmap创建了一个画布
        mcanvas.drawcolor(color.green);//设置画布的颜色为绿色

        mbackground = new rect();
        message = "恭喜中奖,3万元!";
        messagepaint.setcolor(color.red);
        messagepaint.setantialias(true);
        messagepaint.setstyle(paint.style.stroke);
        messagepaint.gettextbounds(message,0,message.length(),mbackground);
        messagepaint.settextsize(30);


        // 设置画笔
        moutterpaint.setcolor(color.blue);
        moutterpaint.setantialias(true);//使用抗锯齿功能,会消耗较大资源,绘制图形速度会变慢
        moutterpaint.setdither(true);//图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰
        moutterpaint.setstyle(paint.style.stroke);
        moutterpaint.setstrokejoin(paint.join.round);//圆角,平滑
        moutterpaint.setstrokecap(paint.cap.round); //圆角
        moutterpaint.setstrokewidth(20); // 设置画笔宽度

        messagepaint.setcolor(color.red);

    }

    @override
    protected void ondraw(canvas canvas) {
        log.d(tag, "ondraw: 画");


        canvas.drawtext(message,mbitmap.getwidth()/2-mbackground.width()/2,getmeasuredheight()/2+mbackground.height()/2,messagepaint);
        drawpath();
        canvas.drawbitmap(mbitmap, 0,0, null);

    }

    private void drawpath() {
        log.d(tag, "drawpath: ");

        moutterpaint.setxfermode(new porterduffxfermode(porterduff.mode.dst_out));
        mcanvas.drawpath(mpath, moutterpaint);
    }

    @override
    public boolean ontouchevent(motionevent event) {
        //当手指按到屏幕上的时候,path路径之中就使用moveto方法,移动到手指当前位置,invalidate刷新view,回调ondraw方法,(还没有画出来)
        //之后,手指移动,action是处于action_move的状态,path路径使用lineto方法(画直线),
        // 同时,将x,y坐标进行了更新,invalidate刷新view,回调ondraw方法,canvas通过drawpath使用画笔将path画了出来,之后如果用户没有抬起手指,则继续循环action_move中的步骤

        int action = event.getaction();
        int x = (int) event.getx();//获得x坐标
        int y = (int) event.gety();//获得y坐标
        switch (action){
            case motionevent.action_down:
                mlastx = x;
                mlasty = y;
                mpath.moveto(mlastx, mlasty);//之后回调ondraw方法canvas将path
                break;
            case motionevent.action_move:
                mpath.lineto(x, y);//之后回调ondraw方法时canvas画直线到(x,y)该点
                mlastx = x;//更新x坐标
                mlasty = y;//更新y坐标
                break;
            default:break;
        }
        invalidate();//刷新view,回调ondraw方法
        log.d(tag, "ontouchevent: invalidate");
        return true;

    }
}