Android不规则点击区域详解
Android不规则点击区域详解
摘要
今天要和大家分享的是Android不规则点击区域,准确说是在视觉上不规则的图像点击响应区域分发。
其实这个问题比较简单,对于很多人来说根本不值得做为一篇博文写出来,但在我的群里确实有童鞋不了解如何实现并且很想知道完整的流程是什么样的,故完成demo作为参考。
以下篇幅记录个人分析流程。
我们的需求。

我们需要实现chrome这样的不同颜色区域点击响应不同的事件。Chrome中分别点击红色、黄色、绿色、蓝色进行不同的事件响应。
经过我们对android组件的了解,组件都是矩形的(即使看上去不是矩形),所以点击区域也是一个矩形。
实现原理。
就原理上讨论的话我认为有两种方式比较简单,一种是利用数学线性规划,另一种是通过像素颜色判断。当然两种都有使用的范围和优缺点,今天就只针对像素颜色判断进行讲解。
我们把chrome的颜色做成4张图(也就是4个图层),每张图都只有一种颜色(准确说是一定范围的颜色),并且每张图的大小都是一样的,颜色的位置相对效果图是一致的,其他用透明像素,这样做是为了方便贴图。然后点击的时候判断点击的颜色是否是透明就可以了,如果是透明那么不处理点击事件,如果不是透明那么需要处理事件。
实践切图。
切图的最终效果如下:(四周的灰色是图的范围,实际并没有颜色是透明的)

程序判断透明。
为了方便管理,所以直接把判断部分写在组件内部,也就是自定义组件。程序比较简单,直接上代码。
package com.vane.ui.widget;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout;
public class MenuViewItem extends FrameLayout {
private int width = -1;
private int height = -1;
private Bitmap bitmap;
public MenuViewItem(Context context) {
super( context);
}
public MenuViewItem(Context context, AttributeSet attrs, int defStyle) {
super( context, attrs, defStyle);
}
public MenuViewItem(Context context, AttributeSet attrs) {
super( context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
if(action != MotionEvent.ACTION_DOWN) {
return super.onTouchEvent( event);
}
int x = (int)event.getX();
int y = (int)event.getY();
if(width == -1 || height == -1) {
Drawable drawable = ((StateListDrawable)getBackground()).getCurrent();
bitmap = ((BitmapDrawable)drawable).getBitmap();
width = getWidth();
height = getHeight();
}
if(null == bitmap || x < 0 || y < 0 || x >= width || y >= height) {
return false;
}
int pixel = bitmap.getPixel( x, y);
if(Color.TRANSPARENT == pixel) {
return false;
}
return super.onTouchEvent( event);
}
}
Drawable drawable = ((StateListDrawable)getBackground()).getCurrent(); 因为我用的背景是selector,如果你用的不是selector那么可以把这段代码你实际设置的背景的drawable类型。这里唯一需要说明的是onTouchEvent方法,返回true表示组件需要拦截touch事件,返回false表示不拦截那么事件会继续分发到viewgroup中的其他child去。程序中有段
如何使用。
使用也很简单,直接贴出activity_main.l布局文件。
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<com.vane.ui.widget.MenuViewItem
android:id="@+id/menu_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/chrome_1" />
<com.vane.ui.widget.MenuViewItem
android:id="@+id/menu_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/chrome_2" />
<com.vane.ui.widget.MenuViewItem
android:id="@+id/menu_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/chrome_3" />
<com.vane.ui.widget.MenuViewItem
android:id="@+id/menu_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/chrome_4" />
</FrameLayout>
chrome_1.xml资源如下:布局里面的背景是selector,下面贴出一个的相应资源结构,其他的都是一样的。
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/chrome_1_s" android:state_pressed="true"/>
<item android:drawable="@drawable/chrome_1_n"/>
</selector>
这里面仅仅是按下和非按下状态的不同资源。
完整demo。
扯淡的代码就不说了,demo使用的资源都是上文中讲的,直接贴代码。
package com.vane.demo; import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast; public class MainActivity extends Activity implements OnClickListener { private Toast mToast; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState);
setContentView( R.layout.activity_main);
findViewById( R.id.menu_1).setOnClickListener( this);
findViewById( R.id.menu_2).setOnClickListener( this);
findViewById( R.id.menu_3).setOnClickListener( this);
findViewById( R.id.menu_4).setOnClickListener( this);
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate( R.menu.main, menu);
return true;
} @Override
public void onClick(View v) {
if(null != mToast) {
mToast.cancel();
}
switch(v.getId()) {
case R.id.menu_1:
mToast = Toast.makeText( this, "red", Toast.LENGTH_SHORT);
break;
case R.id.menu_2:
mToast = Toast.makeText( this, "yellow", Toast.LENGTH_SHORT);
break;
case R.id.menu_3:
mToast = Toast.makeText( this, "green", Toast.LENGTH_SHORT);
break;
case R.id.menu_4:
mToast = Toast.makeText( this, "blue", Toast.LENGTH_SHORT);
break;
}
mToast.show();
}
}
demo的实现效果。

左图是正常截图,右图是点击在红色区域上的截图。
总结。
不规则点击区域的本质是图像像素判断是否是指定颜色(本例中是透明),然后进行touch事件的分发处理。当然如何你不了解touch分发的话可能就不那么容易理解为什么会这么做。
如果文中有任何疑问或者不妥之处欢迎留言交流。在此也留下QQ群311536202,欢迎交流。
Android不规则点击区域详解的更多相关文章
- Android 之窗口小部件详解--App Widget
Android 之窗口小部件详解--App Widget 版本号 说明 作者 日期 1.0 添加App Widge介绍和示例 Sky Wang 2013/06/27 1 App ...
- Android中的windowSoftInputMode属性详解
这篇文章主要介绍了Android中的windowSoftInputMode属性详解,本文对windowSoftInputMode的9个属性做了详细总结,需要的朋友可以参考下 在前面的一篇文章中 ...
- Android 之窗口小部件详解(三) 部分转载
原文地址:http://blog.csdn.net/iefreer/article/details/4626274. (一) 应用程序窗口小部件App Widgets 应用程序窗口小部件(Widget ...
- Android 的事件传递机制,详解
Android 的事件传递机制,详解 前两天和一个朋友聊天的时候.然后说到事件传递机制.然后让我说的时候,忽然发现说的不是非常清楚,事实上Android 的事件传递机制也是知道一些,可是感觉自己知道的 ...
- Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
- Android Design Support Library使用详解
Android Design Support Library使用详解 Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的And ...
- 《Android群英传》读书笔记 (5) 第十一章 搭建云端服务器 + 第十二章 Android 5.X新特性详解 + 第十三章 Android实例提高
第十一章 搭建云端服务器 该章主要介绍了移动后端服务的概念以及Bmob的使用,比较简单,所以略过不总结. 第十三章 Android实例提高 该章主要介绍了拼图游戏和2048的小项目实例,主要是代码,所 ...
- Android中Canvas绘图基础详解(附源码下载) (转)
Android中Canvas绘图基础详解(附源码下载) 原文链接 http://blog.csdn.net/iispring/article/details/49770651 AndroidCa ...
- Android高效率编码-第三方SDK详解系列(三)——JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送
Android高效率编码-第三方SDK详解系列(三)--JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送 很久没有更新第三方SDK这个系列了,所以更新一下这几天工作中使用到的推送, ...
随机推荐
- Nagios学习笔记三:配置Nagios
1.Nagios的主配置文件 Nagios的主配置文件为nagios.cfg,其语法非常简洁,通常#开头的行为注释行,而参数的设置格式为<parameter>=<value>: ...
- java利用16进制来辨别png格式的图片
很多人知道利用.png的字符串结尾可以判断前端传入的图片是否为png格式,但是这只是潜意识的判断!那么如何利用png读写的特殊内容来深意识地判断图片格式呢?最近在做东西的时候遇到了点问题,在加载图片的 ...
- 好消息!Html5游戏和动画的福音
今年基本都淡出了cocos2d-js的开发,更多集中在普通H5应用上,还有自己的Fanvas组件(http://code.tencent.com/),做canvas动画. 不过,最近回头一看WebGL ...
- Leetcode 119 Pascal's Triangle II 数论递推
杨辉三角,这次要输出第rowIndex行 用滚动数组t进行递推 t[(i+1)%2][j] = t[i%2][j] + t[i%2][j - 1]; class Solution { public: ...
- Leetcode 101 Symmetric Tree 二叉树
判断一棵树是否自对称 可以回忆我们做过的Leetcode 100 Same Tree 二叉树和Leetcode 226 Invert Binary Tree 二叉树 先可以将左子树进行Invert B ...
- 已知2个一维数组:a[]={3,4,5,6,7},b[]={1,2,3,4,5,6,7};把数组a与数组b 对应的元素乘积再赋值给数组b,如:b[2]=a[2]*b[2];最后输出数组b的元素。
package hanqi; import java.util.Scanner; public class Test7 { public static void main(String[] args) ...
- 阅读开发高手的代码 分享二则.NET开发框架的技巧
最近阅读了一套ERP开发框架的源代码,对开发框架的理解又深入一层,也为其将知识点运用的如此灵活而自叹不如. 郎咸平教授说,国际金融炒家对国际金融知识的理解与运用程序,是不可想像的.1997年的亚洲金融 ...
- MyEclipse xml 手动添加 dtd
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "- ...
- 三、oracle 体系结构
1.oracle内存由SGA+PGA所构成 2.oracle数据库体系结构数据库的体系结构是指数据库的组成.工作过程与原理,以及数据在数据库中的组织与管理机制. oracle工作原理: 1).在数据库 ...
- AsyncTask实现断点续传
之前公司里面项目的下载模块都是使用xUtils提供的,最近看了下xUtils的源码,它里面也是使用AsyncTask来执行异步任务的,它的下载也包含了断点续传的功能.这里我自己也使用AsyncTask ...