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

简介: 学习内容来自“慕课网” 很多电商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     }

效果图:

相关文章
|
2月前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台策略
在移动应用开发的战场上,安卓和iOS两大阵营各据一方。随着技术的演进,跨平台开发框架成为开发者的新宠,旨在实现一次编码、多平台部署的梦想。本文将探讨跨平台开发的优势与挑战,并分享实用的开发技巧,帮助开发者在安卓和iOS的世界中游刃有余。
|
2月前
|
缓存 前端开发 Android开发
安卓开发中的自定义视图:从零到英雄
【10月更文挑战第42天】 在安卓的世界里,自定义视图是一块画布,让开发者能够绘制出独一无二的界面体验。本文将带你走进自定义视图的大门,通过深入浅出的方式,让你从零基础到能够独立设计并实现复杂的自定义组件。我们将探索自定义视图的核心概念、实现步骤,以及如何优化你的视图以提高性能和兼容性。准备好了吗?让我们开始这段创造性的旅程吧!
39 1
|
2月前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
1月前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
57 19
|
2月前
|
IDE Java 开发工具
移动应用与系统:探索Android开发之旅
在这篇文章中,我们将深入探讨Android开发的各个方面,从基础知识到高级技术。我们将通过代码示例和案例分析,帮助读者更好地理解和掌握Android开发。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和技巧。让我们一起开启Android开发的旅程吧!
|
1月前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
65 14
|
1月前
|
Java Linux 数据库
探索安卓开发:打造你的第一款应用
在数字时代的浪潮中,每个人都有机会成为创意的实现者。本文将带你走进安卓开发的奇妙世界,通过浅显易懂的语言和实际代码示例,引导你从零开始构建自己的第一款安卓应用。无论你是编程新手还是希望拓展技术的开发者,这篇文章都将为你打开一扇门,让你的创意和技术一起飞扬。
|
1月前
|
XML 存储 Java
探索安卓开发之旅:从新手到专家
在数字时代,掌握安卓应用开发技能是进入IT行业的关键。本文将引导读者从零基础开始,逐步深入安卓开发的世界,通过实际案例和代码示例,展示如何构建自己的第一个安卓应用。我们将探讨基本概念、开发工具设置、用户界面设计、数据处理以及发布应用的全过程。无论你是编程新手还是有一定基础的开发者,这篇文章都将为你提供宝贵的知识和技能,帮助你在安卓开发的道路上迈出坚实的步伐。
38 5
|
1月前
|
开发框架 Android开发 iOS开发
安卓与iOS开发中的跨平台策略:一次编码,多平台部署
在移动应用开发的广阔天地中,安卓和iOS两大阵营各占一方。随着技术的发展,跨平台开发框架应运而生,它们承诺着“一次编码,到处运行”的便捷。本文将深入探讨跨平台开发的现状、挑战以及未来趋势,同时通过代码示例揭示跨平台工具的实际运用。
122 3
|
1月前
|
XML 搜索推荐 前端开发
安卓开发中的自定义视图:打造个性化UI组件
在安卓应用开发中,自定义视图是一种强大的工具,它允许开发者创造独一无二的用户界面元素,从而提升应用的外观和用户体验。本文将通过一个简单的自定义视图示例,引导你了解如何在安卓项目中实现自定义组件,并探讨其背后的技术原理。我们将从基础的View类讲起,逐步深入到绘图、事件处理以及性能优化等方面。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和技巧。