Android项目刮刮奖详解(三)
前言
上一期我们已经实现了一个简易的刮刮卡功能,这一期我们来将其完善一下
目标
- 将刮刮奖的宽高改为合适高度
- 将刮刮奖位置居中
- 将信息层的图片换成文字(重点)
实现
将刮刮奖的宽高改为合适高度和将刮刮奖位置居中
这里其实很简单,我们直接到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>
将信息层的图片换成文字
之前我们信息层绘制的是中奖图片,如果没有图片怎么办?当然是直接拿文字来代替啦,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;
}
}
Android项目刮刮奖详解(三)的更多相关文章
- Android 之窗口小部件详解(三) 部分转载
原文地址:http://blog.csdn.net/iefreer/article/details/4626274. (一) 应用程序窗口小部件App Widgets 应用程序窗口小部件(Widget ...
- Android项目刮刮奖详解(二)
Android项目刮刮奖详解(一) 前言 上期我们简单地实现了一个画板的功能,用户可以在上面乱写乱画,其实,刮刮奖也是如此,用户刮奖的时候也是乱写乱画的. 刮刮奖原理 一共有两层画布,底层画布存放中奖 ...
- Android项目刮刮奖详解(四)
Android项目刮刮奖详解(三) 前言 上一期我们已经是完成了刮刮卡的基本功能,本期就是给我们的项目增加个功能以及美化一番 目标 增加功能 用户刮卡刮到一定程度的时候,清除遮盖层 在遮盖层放张图片, ...
- Android项目刮刮奖详解扩展篇——开源刮刮奖View的制作
Android项目刮刮奖详解(四) 前言 我们已经成功实现了刮刮奖的功能了,本期是扩展篇,我们把这个View直接定义成开源控件,发布到JitPack上,以后有需要也可以直接使用,关于自定义控件的知识, ...
- Android高效率编码-第三方SDK详解系列(三)——JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送
Android高效率编码-第三方SDK详解系列(三)--JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送 很久没有更新第三方SDK这个系列了,所以更新一下这几天工作中使用到的推送, ...
- Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
- Android高效率编码-第三方SDK详解系列(二)——Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能
Android高效率编码-第三方SDK详解系列(二)--Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能 我的本意是第二篇写Mob的shareSD ...
- Android高效率编码-第三方SDK详解系列(一)——百度地图,绘制,覆盖物,导航,定位,细腻分解!
Android高效率编码-第三方SDK详解系列(一)--百度地图,绘制,覆盖物,导航,定位,细腻分解! 这是一个系列,但是我也不确定具体会更新多少期,最近很忙,主要还是效率的问题,所以一些有效的东西还 ...
- Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
随机推荐
- Katalon Studio之请求响应中文乱码解决方法
最近在用Katalon做接口测试过程中发现请求响应消息中返回的中文均为乱码,这是因为我们使用的系统环境在初始安装时选择的中文简体,导致windows系统默认编码格式为GBK,但是KS的编码格式是UTF ...
- SpringMVC的配置和使用
SpringMVC的配置和使用 什么是SpringMVC? SpringMVC是Spring家族的一员,Spring是将现在开发中流行的组件进行组合而成的一个框架!它用在基于MVC的表现层开发,类似于 ...
- 权限系统设计-day01
数据库表的设计: 关键流程思考: 权限在SSH系统中应该表现为什么东西? 小胖这个用户登陆:1,检查用户名和密码;2,检查通过; 1),得到小胖这个用户的对应的所有的角色:R1 2),根据所有的角 ...
- Dubbo工作原理,集群容错,负载均衡
Remoting:网络通信框架,实现了sync-over-async和request-response消息机制. RPC:一个远程过程调用的抽象,支持负载均衡.容灾和集群功能. Registry:服务 ...
- [Java]LeetCode284. 顶端迭代器 | Peeking Iterator
Given an Iterator class interface with methods: next() and hasNext(), design and implement a Peeking ...
- [Swift]LeetCode798. 得分最高的最小轮调 | Smallest Rotation with Highest Score
Given an array A, we may rotate it by a non-negative integer K so that the array becomes A[K], A[K+1 ...
- Python——day14 三目运算、推导式、递归、匿名、内置函数
一.三目(元)运算符 定义:就是 if...else...语法糖前提:简化if...else...结构,且两个分支有且只有一条语句注:三元运算符的结果不一定要与条件直接性关系 cmd = input ...
- hdfs创建删除文件和文件夹
在 hadoop 中,基于 Linux 命令可以给 hdfs 创建文件和文件夹,或者删除文件和文件夹 创建文件的命令为: hadoop fs -touch /file.txt 创建文件夹的命令为: h ...
- angularJS学习(二)
1.实现列表 思路: accessCtrl.js let AccessCtrl = function($scope, AlertService, DialogService, BigDataServi ...
- Leetcode 137. 只出现一次的数字 II - 题解
Leetcode 137. 只出现一次的数字 II - 题解 137. Single Number II 在线提交: https://leetcode.com/problems/single-numb ...