Android不規則點擊區域詳解

Android不規則點擊區域詳解

摘要

今天要和你們分享的是Android不規則點擊區域,準確說是在視覺上不規則的圖像點擊響應區域分發。android

其實這個問題比較簡單,對於不少人來講根本不值得作爲一篇博文寫出來,但在個人羣裏確實有童鞋不瞭解如何實現而且很想知道完整的流程是什麼樣的,故完成demo做爲參考。chrome

如下篇幅記錄我的分析流程。app

 

咱們的需求。

 

咱們須要實現chrome這樣的不一樣顏色區域點擊響應不一樣的事件。Chrome中分別點擊紅色、黃色、綠色、藍色進行不一樣的事件響應。ide

通過咱們對android組件的瞭解,組件都是矩形的(即便看上去不是矩形),因此點擊區域也是一個矩形。佈局

 

實現原理。

就原理上討論的話我認爲有兩種方式比較簡單,一種是利用數學線性規劃,另外一種是經過像素顏色判斷。固然兩種都有使用的範圍和優缺點,今天就只針對像素顏色判斷進行講解。ui

咱們把chrome的顏色作成4張圖(也就是4個圖層),每張圖都只有一種顏色(準確說是必定範圍的顏色),而且每張圖的大小都是同樣的,顏色的位置相對效果圖是一致的,其餘用透明像素,這樣作是爲了方便貼圖。而後點擊的時候判斷點擊的顏色是不是透明就能夠了,若是是透明那麼不處理點擊事件,若是不是透明那麼須要處理事件。this

 

實踐切圖。

切圖的最終效果以下:(四周的灰色是圖的範圍,實際並無顏色是透明的)spa

 

 

程序判斷透明。

爲了方便管理,因此直接把判斷部分寫在組件內部,也就是自定義組件。程序比較簡單,直接上代碼。code

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去。程序中有段xml

 

如何使用。

使用也很簡單,直接貼出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,歡迎交流。

相關文章
相關標籤/搜索