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 的背景. ...
随机推荐
- 微信测试号开发入门配置问题java
这个测试号配置弄了好几天了,入了无数坑,终于解决了...辛苦我了,手动安慰一下自己.. 为了萌新们以后不要再浪费时间绕半天做无用功.看看楼楼的艰苦历程吧. 此教程针对没有云服务器,没有自己的域名的.没 ...
- 29 ArcMap许可服务器点击授权后无法进入下一步
系统描述:Windows server 2008 R2 ArcMap版本:10.6 系统要求各项都满足,包括补丁包都有,没有杀毒软件,ArcMap软件能安装上,但是到授权那步出问题 系统要求http ...
- Swift 编程杂谈
1.Swift 3.0 使用Cocopods 导入第三方报错 之前一直用Object-C 编写代码 用Cocopods导入第三方没出过什么问题(PS:2017最新cocoaPods安装教程) 今天用 ...
- Python入门(白银篇)
一.变量.元组的赋值和循环删除 (1)多个变量同时赋值 #多个变量赋值a,b,c,d=1,2,3,4x=y=m=n=520print(a,b,c,d,x,y,m,n) (2)不引入第三方变量下,交换a ...
- CESSNA: Resilient Edge-Computing
CESSNA: 弹性边缘计算 本文为SIGCOMM 2018 Workshop (Mobile Edge Communications, MECOMM)论文. 笔者翻译了该论文.由于时间仓促,且笔者英 ...
- 用R处理一组数据的三种方式
USArrests是R附带的一个数据集,现在我们需要创建一个factor向量urbancat,如果UrbanPop列的某个值在中位数之上,就把urbancat对应位置的值设为1,否则设为0. 这种数据 ...
- 基于Java的ArrayList和LinkedList的实现与总结
一.定义MyList接口,包含列表常见方法: import java.util.Iterator; /** * 线性表(列表)的接口定义 */ public interface MyList<T ...
- FFmpeg开发实战(三):FFmpeg 打印音视频Meta信息
在之前使用FFmpeg命令行的时候,我们经常看到FFmpeg命令行在输出音视频文件的会打印一下文件的Meta信息,类似如图: 那么我们如何通过代码的方式输出这些Meta信息呢? FFmpeg提供了一个 ...
- [Swift]LeetCode155. 最小栈 | Min Stack
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. pu ...
- Spring Boot: Yaml配置文件 以及 @ConfigurationProperties属性获取
Yaml配置文件 概述 Spring Boot在支持application.properties配置文件的同时,也支持application.yaml配置文件. 配置文件中的属性,可以通过: 通过@V ...