资讯专栏INFORMATION COLUMN

Android项目刮刮奖详解(三)

avwu / 1757人阅读

摘要:项目刮刮奖详解二前言上一期我们已经实现了一个简易的刮刮卡功能,这一期我们来将其完善一下目标将刮刮奖的宽高改为合适高度将刮刮奖位置居中将信息层的图片换成文字重点实现将刮刮奖的宽高改为合适高度和将刮刮奖位置居中这里其实很简单,我们直接到布局之中

Android项目刮刮奖详解(二)

前言

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

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

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

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

     
     
    
     
    
     
  2. 将信息层的图片换成文字

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

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

drawText(String text, float x, floaty, Paint paint);

text即使要写的文字内容,x,y是写的位置,需要注意的是,这里的x,y坐标并不是文字的左上角,而是一个与左下角比较接近的位置。大概在这里:如图

最后一个参数就是画笔了,这个画笔设置与之前相似,待会再补充一下

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

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

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

      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);
    测试图

完整代码
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;

    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/2811.html

相关文章

  • Android项目刮刮详解扩展篇——开源刮刮View的制作

    摘要:项目刮刮奖详解四前言我们已经成功实现了刮刮奖的功能了,本期是扩展篇,我们把这个直接定义成开源控件,发布到上,以后有需要也可以直接使用,关于自定义控件的知识,不了解的同学可以看这下面我之前写的这两篇自定义控件开发发布第三方库到上实现定义属性文Android项目刮刮奖详解(四) 前言 我们已经成功实现了刮刮奖的功能了,本期是扩展篇,我们把这个View直接定义成开源控件,发布到JitPack上,以...

    Tychio 评论0 收藏0
  • Android项目刮刮详解(四)

    Android项目刮刮奖详解(三) 前言 上一期我们已经是完成了刮刮卡的基本功能,本期就是给我们的项目增加个功能以及美化一番 目标 增加功能 用户刮卡刮到一定程度的时候,清除遮盖层 在遮盖层放张图片,增加用户体验 增加一个刮完奖回调监听 实现 1.自动消除效果 我们首先来了解一下bitmap的getPixels方法 getPixels(@ColorInt int[] pixels, int ...

    SegmentFault 评论0 收藏0
  • Android项目刮刮详解(二)

    摘要:项目刮刮奖详解一前言上期我们简单地实现了一个画板的功能,用户可以在上面乱写乱画,其实,刮刮奖也是如此,用户刮奖的时候也是乱写乱画的。Android项目刮刮奖详解(一) 前言 上期我们简单地实现了一个画板的功能,用户可以在上面乱写乱画,其实,刮刮奖也是如此,用户刮奖的时候也是乱写乱画的。 刮刮奖原理 一共有两层画布,底层画布存放中奖信息的图片,上层画布则是一个遮盖层,我们将底层画布成为信息层,...

    2450184176 评论0 收藏0
  • Android项目刮刮详解(一)

    摘要:前言最近正在学鸿洋大大的刮刮奖,感觉学有所得,便是来写篇详解尽管网上有很多了,不过毕竟是自己写的,自己以后方便复习,正文开始目标实现画板功能思路我们需要自定义来实现画板功能,之后再将其稍微改造即可。前言 最近正在学鸿洋大大的刮刮奖,感觉学有所得,便是来写篇详解(尽管网上有很多了,不过毕竟是自己写的,自己以后方便复习),正文开始 目标 实现画板功能 思路 我们需要自定义View来实现画板功能,...

    isLishude 评论0 收藏0
  • 基于canvas的刮刮

    摘要:一种类似刮刮奖的洗车游戏。我的思路如下在一中随机放入一些信息如谢谢惠顾,中奖了,然后用画布遮盖此。通过刮掉画布上的颜色层,下面的信息就显示出来了。其中前两个参数分别为获取像素区域的左上角坐标。后两个参数为像素区域的高和宽。 公司要上活动。一种类似刮刮奖的洗车游戏。网上查找了一些代码和思路,自己也来模仿一个。我的思路如下: 在一div中随机放入一些信息(如:谢谢惠顾,中奖了),然后用c...

    LuDongWei 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<