onKeyDown() проблема

Я хотел бы создать приложение для захвата фото/видео.

Я создал класс CaptureView, расширяющий класс SurfaceView, и поместил его в основную форму.

Активность основной формы имеет метод onCreateOptionsMenu(), который создает меню. Меню работало нормально, но потом я попытался реализовать метод onKeyDown:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {

    if(event.getAction() == KeyEvent.ACTION_DOWN) {
        switch(keyCode) {
        case KeyEvent.KEYCODE_CAMERA:
            videoPreview.TakePicture();
            return true;
        }
    }

    return super.onKeyDown(keyCode, event);
}

Меню больше не появляется, и метод не перехватывает событие onKeyDown.

Кто-нибудь знает, что может быть причиной этой проблемы?


person Niko Gamulin    schedule 10.06.2009    source источник
comment
Если вы закомментируете оператор if, меню по-прежнему не отображается?   -  person CiscoIPPhone    schedule 10.06.2009
comment
Я попытался закомментировать оператор if, но, как и ожидалось, ничего не изменилось.   -  person Niko Gamulin    schedule 10.06.2009
comment
Я только что узнал, что было какое-то исключение, не связанное с приведенным выше кодом, останавливающим выполнение.   -  person Niko Gamulin    schedule 11.06.2009


Ответы (8)


Я обнаружил, что возвращал true для всех событий, хотя должен был возвращать его только для кода, который использовал. Я переместил return true в область действия оператора if и вернул false в противном случае. Это вернуло мое меню!

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    super.onKeyDown(keyCode, event);
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        dba.close();
        Intent result = new Intent("Complete");
        setResult(Activity.RESULT_OK, result);
        finish();
        return true;
    }
    return false;
}
person Community    schedule 13.09.2009
comment
Извините, что всегда возвращается значение false, которое использовалось для работы в более старых SDK, но это приведет к проблемам: при компиляции с ICS этот подход отключит клавишу возврата. конечно, в вашем конкретном случае это работает, поскольку вы точно потребляете событие клавиши возврата, но в целом это не будет работать так, как ожидалось. - person Thierry; 12.11.2011
comment
-1. Лучший ответ включает в себя «return super.onKeyDown(keyCode, event);», вместо того, чтобы всегда возвращать false, когда вы не обрабатываете ключ, как было опубликовано rrabio. - person leetNightshade; 09.01.2013
comment
Метод onKeyDown() вообще не вызывается при нажатии кнопки аппаратного поиска, вместо этого запускается поведение поиска по умолчанию. Но нажатие кнопки «Назад» или «Меню» запускает этот метод. Как я могу прослушать нажатие кнопки поиска оборудования Android? - person Karthick; 07.06.2013

У меня была аналогичная проблема, и я решил ее, добавив

this.requestFocus();
this.setFocusableInTouchMode(true);

в конструкторе моего подкласса SurfaceView.

person Ciryon    schedule 30.11.2009
comment
спасибо, это сработало для меня. Я использовал viewflipper для перемещения между представлениями и хотел переопределить кнопку «Назад», чтобы установить представление в качестве текущего представления. Добавление веб-просмотра в VF перестало запускать KeyDown. Установка requestFocus и setFocusableInTouchMode на VF решила эту проблему. Спасибо еще раз - person Veeru; 05.07.2011

я решил удалить оператор if, например:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    switch(keyCode)
    {
        case KeyEvent.KEYCODE_CAMERA:
            videoPreview.TakePicture();
            return true;
    }
    return super.onKeyDown(keyCode, event);
}
person rrabio    schedule 15.06.2010
comment
да хороший момент. всегда возвращал false в конце, раньше у меня работало, но при компиляции с новым ICS SDK клавиша возврата больше не работает, так как событие, похоже, теперь потребляется в super.onKeyDown - person Thierry; 12.11.2011

Я не знаю, почему иногда это не работает, хотя для одного из моих приложений этот keyDown() работает нормально, и снова, когда я использую его для нового приложения, он не работает.

Но у меня есть решение, которое всегда работает:

@Override
public boolean dispatchKeyEvent (KeyEvent event) {
    if (event.getAction()==KeyEvent.ACTION_DOWN && event.getKeyCode()==KeyEvent.KEYCODE_BACK) {
        Toast.makeText(this, "Back button pressed", Toast.LENGTH_LONG).show();
        return true;
    }
    return false;
}
person enam    schedule 15.06.2012

Я решил это, добавив в конструктор этот код:

setFocusable(true);
requestFocus();

спасибо, Ciryon

Также каждый раз, когда я использую setContentView(myView);, я должен вызывать myView.requestFocus();. Если есть лучшее решение, пожалуйста, скажите мне.

person alaster    schedule 14.02.2012

Что ж, при просмотре документации API единственное, что выделяется, это то, что должен быть установлен атрибут android:clickable, а также включено представление для работы метода onKeyDown(...).

person Dean    schedule 10.06.2009

ты можешь попробовать это

this.setFocusable(true);
person zhujian    schedule 23.03.2010

Ваша активность может потреблять ключевое событие. Переопределите onKeyDown в действии и установите там точку останова.

Кроме того: когда вы говорите, что «поместили его в основную форму», вы используете макет XML или делаете это в своем коде?

person haseman    schedule 10.06.2009