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不规则点击区域详解的更多相关文章

  1. Android 之窗口小部件详解--App Widget

    Android 之窗口小部件详解--App Widget  版本号 说明 作者 日期  1.0  添加App Widge介绍和示例  Sky Wang 2013/06/27        1 App ...

  2. Android中的windowSoftInputMode属性详解

    这篇文章主要介绍了Android中的windowSoftInputMode属性详解,本文对windowSoftInputMode的9个属性做了详细总结,需要的朋友可以参考下     在前面的一篇文章中 ...

  3. Android 之窗口小部件详解(三)  部分转载

    原文地址:http://blog.csdn.net/iefreer/article/details/4626274. (一) 应用程序窗口小部件App Widgets 应用程序窗口小部件(Widget ...

  4. Android 的事件传递机制,详解

    Android 的事件传递机制,详解 前两天和一个朋友聊天的时候.然后说到事件传递机制.然后让我说的时候,忽然发现说的不是非常清楚,事实上Android 的事件传递机制也是知道一些,可是感觉自己知道的 ...

  5. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

  6. Android Design Support Library使用详解

    Android Design Support Library使用详解 Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的And ...

  7. 《Android群英传》读书笔记 (5) 第十一章 搭建云端服务器 + 第十二章 Android 5.X新特性详解 + 第十三章 Android实例提高

    第十一章 搭建云端服务器 该章主要介绍了移动后端服务的概念以及Bmob的使用,比较简单,所以略过不总结. 第十三章 Android实例提高 该章主要介绍了拼图游戏和2048的小项目实例,主要是代码,所 ...

  8. Android中Canvas绘图基础详解(附源码下载) (转)

    Android中Canvas绘图基础详解(附源码下载) 原文链接  http://blog.csdn.net/iispring/article/details/49770651   AndroidCa ...

  9. Android高效率编码-第三方SDK详解系列(三)——JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送

    Android高效率编码-第三方SDK详解系列(三)--JPush推送牵扯出来的江湖恩怨,XMPP实现推送,自定义客户端推送 很久没有更新第三方SDK这个系列了,所以更新一下这几天工作中使用到的推送, ...

随机推荐

  1. ubuntu安装redis

    1.下载安装root@21ebdf03a086:/# apt-cache search redisroot@21ebdf03a086:/# apt-get install redis-server a ...

  2. Spring MVC + jpa框架搭建,及全面分析

    一,hibernate与jpa的关系 首先明确一点jpa是什么?以前我就搞不清楚jpa和hibernate的关系. 1,JPA(Java Persistence API)是Sun官方提出的Java持久 ...

  3. 我的fckeditor实践

    一开始我不懂这个ConnectorServlet是何用处,后来发现是专门用于文件上传的,因为fckeditor默认是不支持这个功能的. ConnectorServlet: /* * FCKeditor ...

  4. jQuery演示10种不同的切换图片列表动画效果以及tab动画演示 2

    很常用的一款特效纯CSS完成tab实现5种不同切换对应内容效果 实例预览 下载地址 实例代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ...

  5. 如何启动/停止/重启MySQL

    启动.停止.重启 MySQL 是每个拥有独立主机的站长必须要撑握的操作,下面为大家简单介绍一下操作方法: 一.启动方式 1.使用 service 启动:service mysqld start 2.使 ...

  6. MySQL笔记汇总

    [目录] MySQL笔记汇总 一.mysql简介 数据简介 结构化查询语言 二.mysql命令行操作 三.数据库(表)更改 表相关 字段相关 索引相关 表引擎操作 四.数据库类型 数字型 字符串型 日 ...

  7. PHP中VC6、VC9、TS、NTS版本的区别与用法详解

    Thread safe(线程安全)是运行在Apache上以模块的PHP上,如果你以CGI的模式运行PHP,请选择非线程安全模式(non-thread safe). 1. VC6与VC9的区别: VC6 ...

  8. 【UML】类图的几种关系总结

    在UML类图中,常见的有以下几种关系:泛化(Generalization),  实现(Realization),关联(Association),聚合(Aggregation),组合(Compositi ...

  9. IT 需要知道的一些专业名词和解释 (长期更新)

    c2c: 就是我卖东西你来买  (comsumer to comsumer个人对个人) b2c: 就是我开公司卖东西你来买 (business to comsumer 公司对个人) o2o: 就是我开 ...

  10. 三、oracle 体系结构

    1.oracle内存由SGA+PGA所构成 2.oracle数据库体系结构数据库的体系结构是指数据库的组成.工作过程与原理,以及数据在数据库中的组织与管理机制. oracle工作原理: 1).在数据库 ...