Подтвердить что ты не робот

OnEditorActionListener, вызываемый дважды с одним и тем же событием на клавиатуре SenseUI

На одном телефоне, на котором я тестирую (HTC Incredible, Android 2.2, Software 3.21.605.1), я испытываю следующее поведение.

Обработчик события onEditorAction вызывается дважды (сразу же), когда нажата клавиша Enter на клавиатуре интерфейса Sense.

KeyEvent.getEventTime() является тем же самым для обоих случаев, когда вызывается событие, что приводит меня к этому обходу:

protected void onCreate(Bundle savedInstanceState) {
    [...]

    EditText text = (EditText)findViewById(R.id.txtBox);
    text.setOnEditorActionListener(new OnEditorActionListener() {
        private long lastCalled = -1;

        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
            if ( event.getEventTime() == lastCalled ) {
                return false;
            } else {
                lastCalled = event.getEventTime();
                handleNextButton(v);
                return true;
            }
        }
    });

    [...]
}

Текст EditText определяется как:

<EditText 
    android:layout_width="150sp" 
    android:layout_height="wrap_content"
    android:id="@+id/txtBox" 
    android:imeOptions="actionNext"
    android:capitalize="characters" 
    android:singleLine="true"
    android:inputType="textVisiblePassword|textCapCharacters|textNoSuggestions"
    android:autoText="false" 
    android:editable="true" 
    android:maxLength="6"
/>

На всех других устройствах, на которых я тестировал, кнопка действия правильно помечена как "Далее", и событие вызывается только один раз при нажатии этой кнопки.

Является ли это ошибкой в ​​Sense UI клавиатуре, или я делаю что-то неправильно?

Спасибо за любую помощь.


Обновлено - благодаря полученным ответам, я определился со следующим как мои проверки. Это отлично работает на обоих телефонах, которые я имею для тестирования (Sense UI и Cyanogenmod CM7)

            if (event != null && event.getAction() != KeyEvent.ACTION_DOWN) {
                return false;
            }

            if ( actionId != EditorInfo.IME_ACTION_NEXT && actionId != EditorInfo.IME_NULL ) {
                return false;
            }
4b9b3361

Ответ 1

Как сказал Митч, вы должны проверить действие события:

public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
    if (event == null || event.getAction() != KeyEvent.ACTION_DOWN)
        return false;

    // do your stuff

    return true;
}

Этот фрагмент работает как на Sense UI, так и на эмуляторе.

Ответ 2

(EditText) passwordView = (EditText) findViewById(R.id.password);
passwordView.setImeOptions(EditorInfo.IME_ACTION_DONE);
    passwordView.setOnEditorActionListener(new OnEditorActionListener()
        {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event)
            {
                String input;
                if(actionId == EditorInfo.IME_ACTION_DONE)
                {
                   input= v.getText().toString();
                    Toast toast= Toast.makeText(LogIn.this,input,
                            Toast.LENGTH_LONG);
                    toast.setGravity(Gravity.CENTER, 0, 0);
                    toast.show();
                    return true;
                }
                return false;
            }
        });

Ответ 3

Я думаю, что если вы вернете true, это значит, что вы интересуетесь остальными событиями, пока не достигнете IME_ACTION_DONE. Поэтому, если вы вернете false, это означает, что вас не интересуют события, и тогда у других представлений будет возможность справиться с этим. Поскольку у вас только 1 вид, я предлагаю вам просто игнорировать проверку actionId и просто возвращать false каждый раз.

etMovieName = (EditText) view.findViewById(R.id.et_movie_name);
etMovieName.setOnEditorActionListener(new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView tv, int actionId, KeyEvent event) {
        System.out.println("actionId= "+ actionId);
        performSearch();
        return false;
    }
});

Другая ситуация заключается в том, что если у вас есть перекрывающиеся представления или вид собора, то вы можете использовать actionId для передачи информации. В этой ситуации возвращение true позволит вам передать информацию другому виду. Если вы действительно заинтересованы в событии /actionId (например, если у вас есть другой вид сестры), вы можете сделать это:

etMovieName = (EditText) view.findViewById(R.id.et_movie_name);

etMovieName.setImeOptions(EditorInfo.IME_ACTION_DONE);
etMovieName.setSingleLine();

etMovieName.setOnEditorActionListener(new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView tv, int actionId, KeyEvent event) {
        System.out.println("actionId= "+ actionId);
        return performSearch();      }
});

Обратите внимание, что значение actionId изменилось на 6 после добавления:

etMovieName.setImeOptions(EditorInfo.IME_ACTION_DONE);
etMovieName.setSingleLine();

Ответ 4

В дополнение к ответу @Gubbel, я думаю, что прослушивание ACTION_UP вместо ACTION_DOWN лучше, потому что пользователь может фактически нажать пальцем на клавишу ввода (ACTION_DOWN), но затем колебаться и удерживать его в других местах.

Обычно мы хотим запустить событие только тогда, когда пользователь отпустит палец от клавиши ввода.

Так что код будет таким:

        @Override
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
            boolean handled = false;
            if (event.getAction() == KeyEvent.ACTION_DOWN) return true;
            if ((actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_NULL)
                    && event.getAction() == KeyEvent.ACTION_UP) {
                //Do your stuff here
                handled = true;
            }
            return handled;
        }

Ответ 5

вместо отправки ime-действия и null в качестве события, он отправляет событие касания, поэтому, если вы не получите правильное действие, вы можете проверить событие для action_up или action_down

Ответ 6

Возвращает true; после обработки урского случая, и его больше не будут называть

public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {

                if (actionId == EditorInfo.IME_NULL)
                {
                    Log.i("here","Add product ");
                    return true;  //this does the trick
                }
                return false;
            }