web-dev-qa-db-ja.com

カスタムビュー... onTouchEventをオーバーライドしますが、performClickはオーバーライドしません

私が開発しているカスタムAndroidビューでこの質問を(質問のタイトルから)受け取ります。

なぜ警告されますか?その背後にあるロジックは何ですか?つまり、なぜそれが良いのですか?
performClickをオーバーライドするときにonTouchEventもオーバーライドする練習

47
peter.petrov

目的は何ですか?

他のいくつかの回答では、警告を消す方法を見ることができますが、システムが最初にperformClick()をオーバーライドする理由を理解することが重要です。

世界には数百万人の盲人がいます。たぶん、あなたは通常それらについてあまり考えませんが、そうすべきです。彼らもAndroidを使用しています。 "どうやって?"あなたが尋ねるかもしれません。 1つの重要な方法は、 TalkBack アプリを使用することです。オーディオフィードバックを提供するスクリーンリーダーです。 [設定]> [アクセシビリティ]> [TalkBack]に移動して、携帯電話で有効にできます。チュートリアルをご覧ください。本当に面白いです。次に、目を閉じてアプリを使用してみてください。おそらく、アプリはせいぜい非常に迷惑であり、最悪の場合は完全に壊れていることに気付くでしょう。それはあなたにとっては失敗であり、視覚障害のある人による迅速なアンインストールです。

アプリをアクセシブルにするための概要については、Googleの優れたビデオをご覧ください。

performClick()をオーバーライドする方法

performClick()のオーバーライドが実際にどのように機能するかを確認するために、カスタムビューの例を見てみましょう。簡単なミサイル発射アプリを作成します。カスタムビューは、それを起動するボタンになります。

enter image description here

TalkBackを有効にすると音質は向上しますが、アニメーションGIFでは音声が許可されないため、自分で試してみる必要があります。

コード

activity_main.xml

_<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <net.example.customviewaccessibility.CustomView
        Android:layout_width="200dp"
        Android:layout_height="200dp"
        Android:contentDescription="Activate missile launch"
        Android:layout_centerInParent="true"
        />

</RelativeLayout>
_

contentDescriptionを設定していることに注意してください。これにより、ユーザーが気づいたときにTalkBackがカスタムビューを読み取ることができます。

CustomView.Java

_public class CustomView extends View {

    private final static int NORMAL_COLOR = Color.BLUE;
    private final static int PRESSED_COLOR = Color.RED;

    public CustomView(Context context) {
        super(context);
        init();
    }

    public CustomView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setBackgroundColor(NORMAL_COLOR);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                setBackgroundColor(PRESSED_COLOR);
                return true;

            case MotionEvent.ACTION_UP:
                setBackgroundColor(NORMAL_COLOR);

                // For this particular app we want the main work to happen
                // on ACTION_UP rather than ACTION_DOWN. So this is where
                // we will call performClick(). 
                performClick();
                return true;
        }
        return false;
    }

    // Because we call this from onTouchEvent, this code will be executed for both
    // normal touch events and for when the system calls this using Accessibility 
    @Override
    public boolean performClick() {
        super.performClick();

        launchMissile();

        return true;
    }

    private void launchMissile() {
        Toast.makeText(getContext(), "Missile launched", Toast.LENGTH_SHORT).show();
    }
}
_

ノート

  • documentation は、追加のタッチアップイベントを除外するために使用されるように見えるmDownTouch変数も使用しますが、アプリで十分に説明されていないか、厳密に必要ではないため、私はそれを残しましたでる。実際のミサイルランチャーアプリを作成する場合は、これをさらに検討することをお勧めします。
  • ミサイルを発射する主要なメソッド(launchMissile())は、performClick()から呼び出されます。 onTouchEventにもある場合は、2回呼び出さないように注意してください。カスタムビューの詳細に応じて、ビジネスロジックメソッドをいつどのように呼び出すかを正確に決定する必要があります。
  • performClick()をオーバーライドせず、警告を取り除くためだけに何もしないでください。世界の数百万人の盲人を無視したい場合は、警告を抑制することができます。少なくともそのように、あなたは自分の無情さについて正直です。

    _@SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) { ... }
    _

さらなる研究

59
Suragch

この警告は、performClickをオーバーライドするよう指示しています

@Override
 public boolean performClick() {
  // Calls the super implementation, which generates an AccessibilityEvent
        // and calls the onClick() listener on the view, if any
        super.performClick();

        // Handle the action for the custom click here

        return true;
 }

しかし、強制ではありません。私はカスタムのknobViewを作成しており、この警告に直面しているところでは非常にうまく機能しています。

16
Xar E Ahmer

onTouchEventは、警告の詳細にある「その他...」リンクをクリックすることで説明されているように、一部のアクセシビリティサービスによって呼び出されません。

目的のアクションに対してperformClickをオーバーライドするか、少なくともonTouchEventと一緒にオーバーライドすることをお勧めします。

コードがタッチイベントにより適している場合は、次のようなものを使用できます。

@Override
public boolean performClick() {
    if (actionNotAlreadyExecuted) {
        MotionEvent myEvent = MotionEvent.obtain(long downTime, long eventTime, int action, float x, float y, int metaState);
        onTouch(myView, myEvent);
    }
    return true; // register it has been handled
}

コードを介したタッチイベントへのアクセスの詳細については、 プログラムによるontouchイベントのトリガー

2
Abandoned Cart