Life is Really Short, Have Your Life!!

ござ先輩の主に技術的なメモ

AndroidのOnKeyListenerは2度呼ばれる

今週からAndroidのネイティブアプリを作ってます。Android歴は3日目です。

XMLベースで画面を作るのは滅茶苦茶WPFに似ているので全く違和感なく入れました。イベントハンドラの実装も簡単だし。Activityという単位で画面構成がされること、そいつ自体がスタック構造になっており、デフォルトではActivityを呼ぶ度に新しいインスタンスが作られる。ゾンビActivityがじゃんじゃん生成されることに気をつけたい。

GUIアプリってUI回りでメモリリークしない為にどうするんだっけってのが実装の肝だと感じます。

で、テキストフィールド(EditText)のEnterのキーイベントを拾おうと思ってこんなコード書きました。

final EditText textView = (EditText)view.findViewById(R.id.textView1);
textView.setOnKeyListener(new View.OnKeyListener() {
    @Override
    public boolean onKey(View view, int i, KeyEvent keyEvent) {
        if(i == KeyEvent.KEYCODE_ENTER){
            System.out.println("text is "+ textView.getText());
            return true;
        }
        return false;
    }
});

このコードを実行すると、System.out.printlnが2回も呼ばれてしまいます。その理由は俺たちのStackOverflowに書いてありました。

OnKey is fire twice: the first time for key down, and the second time for key up, so you have to filter

android - Why is onKey() called twice? - Stack Overflow

Windows系だとKeyDown、KeyPress、KeyUpと細かくイベントがわかれているんですけど、なんかAndroidはOnKeyで全部まとめちゃった仕様なんだって。なので、1度しか発生させたくない場合は、以下の様にフィルターをはさもう。

final EditText textView = (EditText)view.findViewById(R.id.textView1);
textView.setOnKeyListener(new View.OnKeyListener() {
    @Override
    public boolean onKey(View view, int i, KeyEvent keyEvent) {
       //ここ
        if (event.getAction()!=KeyEvent.ACTION_DOWN) return false;
        if(i == KeyEvent.KEYCODE_ENTER){
            System.out.println("text is "+ textView.getText());
            return true;
        }
        return false;
    }
});