Androidでタッチ領域をカスタマイズしたい
こういう状況を想定しています。
こういう風に、CustomViewでのタッチ判定領域をカスタマイズするときにどうすればいいのかを調べてみた結果をまとめておきます。
円状のボタンを作った時とか、独自の形をしたViewを作った時に、タッチ領域が四角のままというのをなんとかしたいという要望が出たので作りました。(需要は少なそう)
View#dispatchTouchEventを使用する
結果として、ViewクラスにあるdispatchTouchEventをOverrideすればいいらしい。
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/