安卓开发_慕课网_百度地图_刮刮涂层效果

简介: 学习内容来自“慕课网” 很多电商APP中都有刮刮卡活动,刮开涂层,获取刮刮卡内部信息 原理图: 刮刮卡效果:通过画笔画笔来实现,黄色涂层,蓝色涂层,刮动则将两涂层共有的部分去掉,   就是DstOut对应的 效果 MainActivity.

学习内容来自“慕课网”

很多电商APP中都有刮刮卡活动,刮开涂层,获取刮刮卡内部信息

原理图:

刮刮卡效果:通过画笔画笔来实现,黄色涂层,蓝色涂层,刮动则将两涂层共有的部分去掉,   就是DstOut对应的 效果

MainActivity.java

 1 package com.example.gauguaka;
 2 
 3 import android.os.Bundle;
 4 import android.app.Activity;
 5 import android.view.Menu;
 6 
 7 public class MainActivity extends Activity {
 8 
 9     @Override
10     protected void onCreate(Bundle savedInstanceState) {
11         super.onCreate(savedInstanceState);
12         setContentView(R.layout.activity_main);
13     }
14 
15     
16 }

 

新建一个包guaguaka.java 在包中新建类Guaguaka.java 

 

  1 package guaguaka.view;
  2 
  3 import com.example.gauguaka.R;
  4 
  5 import android.content.Context;
  6 import android.graphics.Bitmap;
  7 import android.graphics.Bitmap.Config;
  8 import android.graphics.BitmapFactory;
  9 import android.graphics.Canvas;
 10 import android.graphics.Color;
 11 import android.graphics.Paint;
 12 import android.graphics.Paint.Style;
 13 import android.graphics.Path;
 14 import android.graphics.PorterDuff.Mode;
 15 import android.graphics.PorterDuffXfermode;
 16 import android.graphics.Rect;
 17 import android.graphics.RectF;
 18 import android.util.AttributeSet;
 19 import android.util.Log;
 20 import android.view.MotionEvent;
 21 import android.view.View;
 22 
 23 public class Guaguaka extends View{
 24     //画笔
 25     private Paint moutterpaint;
 26     //记录绘制路径
 27     private Path mpath;
 28     //画布
 29     private Canvas mcanvas;
 30     //图片
 31     private Bitmap mbitmap;
 32     //绘制坐标值
 33     private int mlastx;
 34     private int mlasty;
 35     /*----------------------*/
 36     private Bitmap bitmap;
 37     private Bitmap moutterbitmap;
 38     // 判断遮盖层区域是否消除达到阈值
 39     private volatile boolean mComplete = false;
 40     
 41     
 42     
 43     public Guaguaka(Context context) {
 44         // TODO Auto-generated constructor stub
 45         this(context,null);
 46     }
 47     public Guaguaka(Context context, AttributeSet attrs) {
 48         this(context, attrs,0);
 49         // TODO Auto-generated constructor stub
 50     }
 51     public Guaguaka(Context context, AttributeSet attrs,int defStyle) {
 52         super(context, attrs ,defStyle);
 53         // TODO Auto-generated constructor stub
 54         init();
 55     }
 56     //获得控件的宽度和高度
 57     @Override
 58     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 59         // TODO Auto-generated method stub
 60         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 61         
 62         int width = getMeasuredWidth();
 63         int height = getMeasuredHeight();
 64         // 初始化我们的bitmap
 65         mbitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
 66         mcanvas = new Canvas(mbitmap);
 67         // 设置绘制path画笔的一些属性
 68         setupOutPaint();
 69         //setUpBackPaint();
 70         //mcanvas.drawColor(Color.parseColor("#c0c0c0"));
 71         //设置刮刮卡框架为圆角
 72         mcanvas.drawRoundRect(new RectF(0, 0, width, height), 30, 30,moutterpaint);
 73         //显示刮刮卡未刮开是的图案
 74         mcanvas.drawBitmap(moutterbitmap, null, new Rect(0, 0, width, height),null);
 75         
 76         
 77     }
 78     //初始化操作
 79     private void init() {
 80         // TODO Auto-generated method stub
 81         moutterpaint = new Paint();
 82         mpath = new Path();
 83         //刮开后的图片(chaji_1是一个茶壶的图片)
 84         bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.chaji_1);    
 85         //刮刮卡未刮时候的图案(fg_guaguaka 是一个刮刮卡字样的图片)
 86         moutterbitmap = BitmapFactory.decodeResource(getResources(),R.drawable.fg_guaguaka);
 87         }
 88     /**
 89      * 设置绘制path画笔的一些属性
 90      */
 91     private void setupOutPaint()
 92     {
 93         //画笔颜色 --红色
 94         moutterpaint.setColor(Color.parseColor("#c0c0c0"));
 95         //锯齿
 96         moutterpaint.setAntiAlias(true);
 97         moutterpaint.setDither(true);
 98         //线条圆角
 99         moutterpaint.setStrokeJoin(Paint.Join.ROUND);
100         moutterpaint.setStrokeCap(Paint.Cap.ROUND);
101         moutterpaint.setStyle(Style.FILL);
102         //画笔宽度
103         moutterpaint.setStrokeWidth(20);
104     }
105     /**
106      * 设置我们绘制获奖信息的画笔属性
107      */
108     
109     //绘制事件
110     @Override
111     public boolean onTouchEvent(MotionEvent event)
112     {
113         int action = event.getAction();
114 
115         int x = (int) event.getX();
116         int y = (int) event.getY();
117 
118         switch (action)
119         {
120         case MotionEvent.ACTION_DOWN://按下
121 
122             mlastx = x;
123             mlasty = y;
124             mpath.moveTo(mlastx, mlasty);
125             break;
126         case MotionEvent.ACTION_MOVE://移动
127 
128             int dx = Math.abs(x - mlastx);
129             int dy = Math.abs(y - mlasty);
130 
131             if (dx > 3 || dy > 3)
132             {
133                 mpath.lineTo(x, y);
134             }
135             //更新坐标
136             mlastx = x;
137             mlasty = y;
138 
139             break;
140         case MotionEvent.ACTION_UP://抬起
141             new Thread(mRunnable).start();// 统计擦除区域任务
142             break;
143         }
144         
145             invalidate();
146         return true;
147 
148     }
149     @Override
150     protected void onDraw(Canvas canvas)
151     {
152             canvas.drawBitmap(bitmap, 0 , 0, null);
153             //注意任务结束,会把一个mComplete设置为true;当为true时,直接展现刮奖区
154             if (!mComplete)
155             {
156             drawPath();
157             canvas.drawBitmap(mbitmap, 0, 0, null);
158             }
159         }
160 
161     private void drawPath()
162     {
163         moutterpaint.setStyle(Style.STROKE);
164         moutterpaint.setXfermode(new PorterDuffXfermode(Mode.DST_OUT));
165         mcanvas.drawPath(mpath, moutterpaint);
166     }
167     /**
168      * 统计擦除区域任务
169      */
170     private Runnable mRunnable = new Runnable()
171     {
172         private int[] mPixels;
173 
174         @Override
175         public void run()
176         {
177 
178             int w = getWidth();
179             int h = getHeight();
180 
181             float wipeArea = 0;
182             float totalArea = w * h;
183 
184             Bitmap bitmap = mbitmap;
185 
186             mPixels = new int[w * h];
187 
188             /**
189              * 拿到所有的像素信息
190              */
191             bitmap.getPixels(mPixels, 0, w, 0, 0, w, h);
192 
193             /**
194              * 遍历统计擦除的区域
195              */
196             for (int i = 0; i < w; i++)
197             {
198                 for (int j = 0; j < h; j++)
199                 {
200                     int index = i + j * w;
201                     if (mPixels[index] == 0)
202                     {
203                         wipeArea++;
204                     }
205                 }
206             }
207             
208             /**
209              * 根据所占百分比,进行一些操作
210              */
211             if (wipeArea > 0 && totalArea > 0)
212             {
213                 int percent = (int) (wipeArea * 100 / totalArea);
214                 Log.e("TAG", percent + "");
215 
216                 if (percent > 70)
217                 {
218                     mComplete = true;
219                     postInvalidate();
220                 }
221             }
222         }
223 
224     };
225 }
Guaguaka.java

 

将布局文件修改:

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     >
 6 
 7  <guaguaka.view.Guaguaka
 8         android:id="@+id/id_guaguaka"
 9         android:layout_width="300dp"
10         android:layout_height="100dp"
11         android:layout_centerInParent="true"
12         />
13 </RelativeLayout>
activity_main.xml

效果图:

接下来就行效果的优化。

当刮开涂层达到总面积的多少的时候,将全部图案显示出来

首先定义一个布尔值

1 // 判断遮盖层区域是否消除达到阈值
2     private volatile boolean mComplete = false;

添加计算刮开区域面积的线程

 1 private Runnable mRunnable = new Runnable()
 2     {
 3         private int[] mPixels;
 4 
 5         @Override
 6         public void run()
 7         {
 8 
 9             int w = getWidth();
10             int h = getHeight();
11 
12             float wipeArea = 0;
13             float totalArea = w * h;
14 
15             Bitmap bitmap = mbitmap;
16 
17             mPixels = new int[w * h];
18 
19             /**
20              * 拿到所有的像素信息
21              */
22             bitmap.getPixels(mPixels, 0, w, 0, 0, w, h);
23 
24             /**
25              * 遍历统计擦除的区域
26              */
27             for (int i = 0; i < w; i++)
28             {
29                 for (int j = 0; j < h; j++)
30                 {
31                     int index = i + j * w;
32                     if (mPixels[index] == 0)
33                     {
34                         wipeArea++;
35                     }
36                 }
37             }
38             
39             /**
40              * 根据所占百分比,进行一些操作
41              */
42             if (wipeArea > 0 && totalArea > 0)
43             {
44                 int percent = (int) (wipeArea * 100 / totalArea);
45                 Log.e("TAG", percent + "");
46 
47                 if (percent > 70) //如果刮开面积达到70% 则将mComplete布尔值设为true 将全部图案显示出来
48                 {
49                     mComplete = true;
50                     postInvalidate();
51                 }
52             }
53         }
54 
55     };

 

在ACTION_UP,即松开触屏的时候调用

1 case MotionEvent.ACTION_UP://抬起
2             new Thread(mRunnable).start();// 统计擦除区域任务
3             break;

 

任务结束,会把一个mComplete设置为true;当为true时,直接展现刮奖区

 1 @Override
 2     protected void onDraw(Canvas canvas)
 3     {
 4         drawBackText(canvas);
 5 
 6         if (!isComplete)
 7         {
 8             drawPath();
 9             canvas.drawBitmap(mBitmap, 0, 0, null);
10         }
11 
12     }

效果图:

相关文章
|
30天前
|
缓存 搜索推荐 Android开发
安卓开发中的自定义控件实践
【10月更文挑战第4天】在安卓开发的海洋中,自定义控件是那片璀璨的星辰。它不仅让应用界面设计变得丰富多彩,还提升了用户体验。本文将带你探索自定义控件的核心概念、实现过程以及优化技巧,让你的应用在众多竞争者中脱颖而出。
|
30天前
|
Java Android开发 Swift
安卓与iOS开发对比:平台选择对项目成功的影响
【10月更文挑战第4天】在移动应用开发的世界中,选择合适的平台是至关重要的。本文将深入探讨安卓和iOS两大主流平台的开发环境、用户基础、市场份额和开发成本等方面的差异,并分析这些差异如何影响项目的最终成果。通过比较这两个平台的优势与挑战,开发者可以更好地决定哪个平台更适合他们的项目需求。
98 1
|
6天前
|
编解码 Java Android开发
通义灵码:在安卓开发中提升工作效率的真实应用案例
本文介绍了通义灵码在安卓开发中的应用。作为一名97年的聋人开发者,我在2024年Google Gemma竞赛中获得了冠军,拿下了很多项目竞赛奖励,通义灵码成为我的得力助手。文章详细展示了如何安装通义灵码插件,并通过多个实例说明其在适配国际语言、多种分辨率、业务逻辑开发和编程语言转换等方面的应用,显著提高了开发效率和准确性。
|
5天前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
18 5
|
3天前
|
JSON Java Android开发
探索安卓开发之旅:打造你的第一个天气应用
【10月更文挑战第30天】在这个数字时代,掌握移动应用开发技能无疑是进入IT行业的敲门砖。本文将引导你开启安卓开发的奇妙之旅,通过构建一个简易的天气应用来实践你的编程技能。无论你是初学者还是有一定经验的开发者,这篇文章都将成为你宝贵的学习资源。我们将一步步地深入到安卓开发的世界中,从搭建开发环境到实现核心功能,每个环节都充满了发现和创造的乐趣。让我们开始吧,一起在代码的海洋中航行!
|
5天前
|
缓存 数据库 Android开发
安卓开发中的性能优化技巧
【10月更文挑战第29天】在移动应用的海洋中,性能是船只能否破浪前行的关键。本文将深入探讨安卓开发中的性能优化策略,从代码层面到系统层面,揭示如何让应用运行得更快、更流畅。我们将以实际案例和最佳实践为灯塔,引领开发者避开性能瓶颈的暗礁。
16 3
|
7天前
|
存储 IDE 开发工具
探索Android开发之旅:从新手到专家
【10月更文挑战第26天】在这篇文章中,我们将一起踏上一段激动人心的旅程,探索如何在Android平台上从零开始,最终成为一名熟练的开发者。通过简单易懂的语言和实际代码示例,本文将引导你了解Android开发的基础知识、关键概念以及如何实现一个基本的应用程序。无论你是编程新手还是希望扩展你的技术栈,这篇文章都将为你提供价值和启发。让我们开始吧!
|
1月前
|
Web App开发 安全 程序员
FFmpeg开发笔记(五十五)寒冬里的安卓程序员可进阶修炼的几种姿势
多年的互联网寒冬在今年尤为凛冽,坚守安卓开发愈发不易。面对是否转行或学习新技术的迷茫,安卓程序员可从三个方向进阶:1)钻研谷歌新技术,如Kotlin、Flutter、Jetpack等;2)拓展新功能应用,掌握Socket、OpenGL、WebRTC等专业领域技能;3)结合其他行业,如汽车、游戏、安全等,拓宽职业道路。这三个方向各有学习难度和保饭碗指数,助你在安卓开发领域持续成长。
58 1
FFmpeg开发笔记(五十五)寒冬里的安卓程序员可进阶修炼的几种姿势
|
13天前
|
Java API Android开发
安卓应用程序开发的新手指南:从零开始构建你的第一个应用
【10月更文挑战第20天】在这个数字技术不断进步的时代,掌握移动应用开发技能无疑打开了一扇通往创新世界的大门。对于初学者来说,了解并学习如何从无到有构建一个安卓应用是至关重要的第一步。本文将为你提供一份详尽的入门指南,帮助你理解安卓开发的基础知识,并通过实际示例引导你完成第一个简单的应用项目。无论你是编程新手还是希望扩展你的技能集,这份指南都将是你宝贵的资源。
42 5
|
12天前
|
设计模式 IDE Java
探索安卓开发:从新手到专家的旅程
【10月更文挑战第22天】 在数字时代的浪潮中,移动应用开发如同一座金矿,吸引着无数探险者。本文将作为你的指南针,指引你进入安卓开发的广阔天地。我们将一起揭开安卓平台的神秘面纱,从搭建开发环境到掌握核心概念,再到深入理解安卓架构。无论你是初涉编程的新手,还是渴望进阶的开发者,这段旅程都将为你带来宝贵的知识和经验的财富。让我们开始吧!