Edited at

AndroidのCustomViewでタッチ領域を円にする

More than 3 years have passed since last update.


Androidでタッチ領域をカスタマイズしたい

こういう状況を想定しています。

custom view detect

こういう風に、CustomViewでのタッチ判定領域をカスタマイズするときにどうすればいいのかを調べてみた結果をまとめておきます。

円状のボタンを作った時とか、独自の形をしたViewを作った時に、タッチ領域が四角のままというのをなんとかしたいという要望が出たので作りました。(需要は少なそう)


View#dispatchTouchEventを使用する

結果として、ViewクラスにあるdispatchTouchEventをOverrideすればいいらしい。


CircleDetectView.java

public class CircleDetectView extends View {

//... 中略

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
float touchX = event.getX(), touchY = event.getY();
float r = getWidth() / 2;

// 中心からタッチ点までの距離(の2乗)を計算
// float lenght = (float)Math.pow(touchX - r, 2) + (float)Math.pow(touchY - r, 2);
// 追記(2015/2/26):
// 距離を測る Math.hypot という大層便利なメソッドがありました。
double length = Math.hypot(touchX - r, touchY - r);

// (中心からタッチ点までの距離)^2 <= (円の半径)^2
if (length <= r * r) {
// 円の内部
// (superを呼び出すことによってonTouchやonClickを呼び出すようにする)
return super.dispatchTouchEvent(event);
} else {
// 円の外部(falseにすると、onTouchやonClickなどが呼ばれない)
return false;
}
}
}


dispatchTouchEventがタッチイベントの起点として使われてるようなので、こいつを少しいじってやれば解決するようです。

今回は円の内側をタッチ領域としたいので、タッチした点から円の中心(今回はViewの中心)までの距離が半径よりも小さくなれば円の内側をタッチしたことが表せますね。


展望

領域判定の部分をinterfaceにして、領域を自分でカスタマイズ出来るようになったらちょっとおもしろそう。

星形の判定とか、同じ円でも中心をずらして半円のタッチ領域とか、いろいろ可能性はありそうですね。


参考サイト様

Android のタッチイベントを理解する(その1)

http://blog.lciel.jp/blog/2013/12/03/android-touch-event/