Help us understand the problem. What is going on with this article?

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

More than 5 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/

litmon
とある恵比寿のAndroidエンジニアです。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away