Android刮刮卡自定义控件

效果图
刮刮卡自定义控件
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
/*** 描述:* 作者: shawn* 时间: 2024/5/2711:20*/
public class ScratchView extends View {/*** 绘制线条的画笔*/private Paint mOutterPaint = new Paint();/*** 遮层画笔*/private Paint mMaskPaint = new Paint();/*** 最下面画笔*/private Paint mBackPint = new Paint();/*** mCanvas绘制内容在其上*/private Bitmap mBitmap;/*** 记录用户绘制的Path*/private Path mPath = new Path();/*** 内存中创建的Canvas*/private Canvas mCanvas;private boolean isComplete;private Rect mTextBound = new Rect();private String mText = "¥500,0000";private int mLastX;private int mLastY;private int measuredWidth;private int measuredHeight;public GuaGuaKaView(Context context) {this(context, null);}public GuaGuaKaView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public GuaGuaKaView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init();}private void init() {mPath = new Path();setUpOutPaint();setUpBackPaint();}/*** 初始化canvas的绘制用的画笔*/private void setUpBackPaint() {mBackPint.setStyle(Paint.Style.FILL);mBackPint.setTextScaleX(2f);mBackPint.setColor(Color.DKGRAY);mBackPint.setTextSize(32);mBackPint.getTextBounds(mText, 0, mText.length(), mTextBound);}@Overrideprotected void onDraw(Canvas canvas) {if (!isComplete) {drawPath();canvas.drawBitmap(mBitmap, 0, 0, null);} else {this.setVisibility(GONE);}}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);measuredWidth = getMeasuredWidth();//宽高和父view的相同measuredHeight = getMeasuredHeight();// 初始化bitmapmBitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888);mCanvas = new Canvas(mBitmap);mMaskPaint.setColor(Color.parseColor("#000000"));//遮层透明mMaskPaint.setStyle(Paint.Style.FILL);mCanvas.drawRoundRect(new RectF(0, 0, measuredWidth, measuredHeight), 0, 0, mMaskPaint);
//        mCanvas.drawBitmap(BitmapFactory.decodeResource(getResources(),
//                R.drawable.bg_withdraw_history), null, new RectF(0, 0, measuredWidth, measuredHeight), null);//遮层}/*** 设置画笔的一些参数*/private void setUpOutPaint() {// 设置画笔
//         mOutterPaint.setAlpha(0);mOutterPaint.setColor(Color.parseColor("#c0c0c0"));mOutterPaint.setAntiAlias(true);mOutterPaint.setDither(true);mOutterPaint.setStyle(Paint.Style.STROKE);mOutterPaint.setStrokeJoin(Paint.Join.ROUND); // 圆角mOutterPaint.setStrokeCap(Paint.Cap.ROUND); // 圆角// 设置画笔宽度mOutterPaint.setStrokeWidth(50);}/*** 绘制线条*/private void drawPath() {mOutterPaint.setStyle(Paint.Style.STROKE);mOutterPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));//取俩者的交集mCanvas.drawPath(mPath, mOutterPaint);}@Overridepublic boolean onTouchEvent(MotionEvent event) {int action = event.getAction();int x = (int) event.getX();int y = (int) event.getY();switch (action) {case MotionEvent.ACTION_DOWN:mLastX = x;mLastY = y;mPath.moveTo(mLastX, mLastY);break;case MotionEvent.ACTION_MOVE:int dx = Math.abs(x - mLastX);int dy = Math.abs(y - mLastY);if (dx > 3 || dy > 3)mPath.lineTo(x, y);mLastX = x;mLastY = y;new Thread(mRunnable).start();break;case MotionEvent.ACTION_UP:new Thread(mRunnable).start();break;}invalidate();return true;}/*** 统计擦除区域任务*/private Runnable mRunnable = new Runnable() {private int[] mPixels;@Overridepublic void run() {int w = getWidth();int h = getHeight();float wipeArea = 0;float totalArea = w * h;Bitmap bitmap = mBitmap;mPixels = new int[w * h];/*** 拿到所有的像素信息*/bitmap.getPixels(mPixels, 0, w, 0, 0, w, h);/*** 遍历统计擦除的区域*/for (int i = 0; i < w; i++) {for (int j = 0; j < h; j++) {int index = i + j * w;if (mPixels[index] == 0) {wipeArea++;}}}/*** 根据所占百分比,进行一些操作*/if (wipeArea > 0 && totalArea > 0) {int percent = (int) (wipeArea * 100 / totalArea);Log.e("TAG", "清除区域 = " + percent);if (percent > 75) {isComplete = true;postInvalidate();}}}};/*** 将布局转换成bitmap* @param addViewContent* @return*/private Bitmap getViewBitmap(View addViewContent) {addViewContent.setDrawingCacheEnabled(true);addViewContent.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));addViewContent.layout(0, 0,addViewContent.getMeasuredWidth(),addViewContent.getMeasuredHeight());addViewContent.buildDrawingCache();Bitmap cacheBitmap = addViewContent.getDrawingCache();Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);return bitmap;}
}
 如何使用?
<RelativeLayout>
<!-- 显示层 -->
<ImageViewandroid:id="@+id/iv_holder"android:layout_width="0dp"android:layout_height="100dp"android:layout_marginStart="14dp"android:layout_marginTop="60dp"android:layout_marginEnd="14dp"android:scaleType="fitXY"android:src="@drawable/bg_drama_top"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" />
<!-- 刮奖层 -->
<ScratchViewapp:layout_constraintTop_toTopOf="@id/iv_holder"app:layout_constraintBottom_toBottomOf="@id/iv_holder"app:layout_constraintStart_toStartOf="@id/iv_holder"app:layout_constraintEnd_toEndOf="@id/iv_holder"android:layout_width="0dp"android:layout_height="0dp"/>
</RelativeLayout>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/333966.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux--进程间通信(1)(匿名管道)

目录 1.了解进程通信 1.1进程为什么要通信 1.2 进程如何通信 1.3进程间通信的方式 2.管道 2.1管道的初步理解 2.2站在文件描述符的角度-进一步理解管道 2.3 管道的系统调用接口&#xff08;匿名管道&#xff09; 2.3.1介绍接口函数&#xff1a; 2.3.2编写一个管道的代…

AI Agent教育行业落地案例

【AI赋能教育】揭秘Duolingo背后的AI Agent&#xff0c;让学习更高效、更有趣&#xff01; ©作者|Blaze 来源|神州问学 引言 随着科技的迅猛发展&#xff0c;人工智能技术已经逐步渗透到我们生活的各个方面。而随着AI技术的广泛应用&#xff0c;教育培训正引领着一场新的…

微软语音使用小计

简介 使用微软语音可以实现语音转文字和文字转语音。测试了下&#xff0c;使用还是挺方便的。 使用微软语音有两种方式。一种是使用命令行的形式&#xff0c;另一种是调用SDK的方式。 适合使用语音 CLI 的情况&#xff1a; 想在极少设置且无需编写代码的情况下试验语音服务…

Vulnhub靶机 whowantsobeking :1 打靶 渗透详细过程(萌新)

Vulnhub靶机搭建配置 先搭建vulnhub靶机&#xff1a;https://www.vulnhub.com/entry/who-wants-to-be-king-1,610/ 下载镜像之后whowantsobeking.ova后&#xff0c;用VMware Workstation Pro打开依次点击文件-打开&#xff0c;选择我们刚才下载的ova文件打开&#xff0c;修改…

JavaWeb开发 2.Web开发 Web前端开发 ①介绍

内心一旦平静&#xff0c;外界便鸦雀无声 —— 24.5.27 一、初识Web前端 网页有哪些部分组成? 文字、图片、音频、视频、超链接 ...网页&#xff0c;背后的本质是什么? 前端代码前端的代码是如何转换成用户眼中的网页的? 通过浏览器转化(解析和渲染)成用户看…

表空间[MAIN]处于脱机状态

达梦数据库还原后&#xff0c;访问数据库报错&#xff1a;表空间[MAIN]处于脱机状态 解决方法&#xff1a; 1&#xff1a;检查备份文件 DMRMAN 中使用 CHECK 命令对备份集进行校验&#xff0c;校验备份集是否存在及合法。 ##语法&#xff1a;CHECK BACKUPSET <备份集目录…

小识MFC,一套设计优雅与不优雅并存的类库----小话MFC(2)

Q1&#xff1a; CPoint继承于POINT&#xff0c;这样有什么好处&#xff1f; A&#xff1a; 继承的一个最基本的好处当然就是减少代码量。CPoint和POINT内部数据一样&#xff0c;只是一个提供了更多的方法来操作对象。 typedef struct tagPOINT {LONG x;LONG y; } POINT, *P…

小程序大能量:盲盒平台搭建与营销策略

一、引言 在移动互联网的浪潮下&#xff0c;小程序以其轻量级、即用即走的特点&#xff0c;成为了商家与消费者沟通的新桥梁。盲盒经济作为近年来兴起的消费趋势&#xff0c;结合小程序平台&#xff0c;不仅为用户带来了全新的购物体验&#xff0c;也为商家带来了更多的商业机…

【管理咨询宝藏115】某大型电力集团5年战略发展报告终稿

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏115】某大型电力集团5年战略发展报告终稿 【格式】PDF版本 【关键词】战略规划、大型国企、战略报告 【核心观点】 - 战略领导人敏锐的直觉和城…

【乐吾乐3D可视化组态编辑器】模型类型与属性

编辑器地址&#xff1a;3D可视化组态 - 乐吾乐Le5le 本章主要为您介绍模型的属性功能。 一个模型至少会包含一个节点&#xff08;Node&#xff09;&#xff0c;从节点类型上可以分为转换节点&#xff08;TransformNode&#xff09;、网格&#xff08;Mesh&#xff09;、实例网…

5.27作业

定义自己的命名空间my_sapce&#xff0c;在my_sapce中定义string类型的变量s1&#xff0c;再定义一个函数完成对字符串的逆置。 #include <iostream> #include <string.h>using namespace std; namespace my_space {string s1;void RevString(string &s1); } v…

OrangePi AIpro 开箱初体验及语音识别样例

OrangePi AIpro 开箱初体验及语音识别样例 一、 前言 首先非常感谢官方大大给予这次机会&#xff0c;让我有幸参加此次活动。 OrangePi AIpro联合华为精心打造&#xff0c;采用昇腾AI技术路线&#xff0c;具体为4核64位处理器AI处理器&#xff0c;集成图形处理器&#xff0c;…

【JavaScript】P3 JavaScipt 注释方法、结束符、输入输出

小结&#xff1a; Js 注释&#xff1a; 单行注释&#xff1a;//多行注释&#xff1a;/* */ Js 结束符&#xff1a; 分号; 可以加也可以不加 Js 输入输出&#xff1a; 输入&#xff1a;prompt()输出&#xff1a;document.write() 在页面中打印&#xff0c;console.log() 在控制…

浅谈金融行业数据安全分类分级

数据安全管理是一项从上而下的、多方配合开展的工作。在进行数据安全管理组织架构建设时&#xff0c;需要从上而下建设&#xff1b;从而全面推动数据安全管理工作的执行和落地&#xff1b;以保证数据安全的合法合规、并长效推动业务的发展和稳定运行。 金融行业机构应设立数据…

【Sql Server】随机查询一条表记录,并重重温回顾下存储过程的封装和使用

大家好&#xff0c;我是全栈小5&#xff0c;欢迎来到《小5讲堂》。 这是《Sql Server》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 前言随机查询语…

自定义CSS属性(@property)解决自定义CSS变量无法实现过渡效果的问题

且看下面的代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>demot</title&g…

Python批量docx或doc文档转换pdf

说明&#xff1a; 1、因为项目需要&#xff0c;需要手动将十几个word文档转换成pdf文档 2、python请安装3.9.0以上&#xff0c;否则一些依赖库无法正常用 #! /usr/bin/python3 # -*- coding: utf-8 -*-import os import comtypes.client# 批量将docx文件转换pdf文件 def docx_t…

第十二周 5.21面向对象的三大特性(封装、继承、多态)(二)

三、多态 1.理解: (1)多态:父类型的引用存储不同子类型的对象 父类类名 引用名 new 子类类名(); 引用 对象 父类型 子类型 …

Java面试八股之AQS对资源的共享方式

AQS对资源的共享方式 AQS设计了一套灵活的机制&#xff0c;不仅支持独占&#xff08;Exclusive&#xff09;锁模式&#xff0c;也支持共享&#xff08;Shared&#xff09;锁模式&#xff0c;使得资源可以被一个或者多个线程以不同的方式访问。这两种模式通过控制一个内部的vol…

B站pink老师HTML5基础(一)

文章目录 一、网页1.什么是网页2.什么是HTML二、常用浏览器 三、Web标准四、HTML标签1.HTML基本结构标签 五、快捷键六、常用标签1.标题标签2.段落和换行标签3.文本格式化标签4.div标签和span标签5.图像标签6.图像路径7.超链接标签8.特殊字符 一、网页 1.什么是网页 2.什么是H…