Почему установка imeActionId с предопределенным ресурсом идентификатора создает ошибку?

У Кирилла Моттье есть отличная статья по настройке клавиши send/done/return на мягкой клавиатуре Android. При тестировании кода я (и несколько других комментариев) заметил, что установка imeActionId с новым идентификатором в XML (например, @+ id/...) возвращает 0 в OnEditorActionListener, когда ключ попадает в пользователь, а не уникальный идентификатор. Однако, если вы установили идентификатор в файле ids.xml и установили imeActionId на это (например, w/@id/...), это приведет к ошибке внедрения макета.

Единственный способ, с помощью которого я смог успешно установить imeActionId в уникальный идентификатор, - это установить его программно на Java. Итак, каково правильное использование атрибута XML imeActionId?

Вот Gist со всем моим кодом: https://gist.github.com/gsysko/d46adbe27d409bde0299

Спасибо за рассмотрение этого вопроса.

Ответ 1

Причина в том, что imeActionId является небольшим неправильным в этом случае. Javadoc для imeActionId говорит:

Поставьте значение для параметра EditorInfo.actionId, используемого при подключении метода ввода к текстовому виду.

Он ищет, чтобы вы назначили значение. Идентификатор ресурса предназначен для идентификации ресурсов в вашем приложении и не имеет гарантированного значения. В некоторых случаях вы можете делать сравнения на основе идентификаторов ресурсов, таких как View.getId(), но нехорошо смешивать идентификатор ресурса с постоянными значениями, которые использует EditorInfo. Android может попытаться помешать вам это сделать, когда он анализирует ваши XML файлы, бросая исключения, как вы видели, но не так много проверок, которые он может выполнять во время выполнения, если вы установите его программно.

Вместо этого вы можете определить целочисленное значение в своих ресурсах, например:

<!--res/values/integers.xml-->
<resources>
<item type="integer" name="customImeActionId" format="integer">100</item>
</resources>

и используйте его как

android:imeActionId="@integer/customImeActionId"

В вашем коде вы можете получить его

int imeActionId = getResources().getInteger(R.integer.customImeActionId);

edit: ОК, это вызвало мой интерес, так что, глядя дальше в исходный код Android, TextView анализирует атрибут вроде:

mEditor.mInputContentType.imeActionId = a.getInt(attr, mEditor.mInputContentType.imeActionId);

Он будет использовать mEditor.mInputContentType.imeActionId как значение по умолчанию, которое в этом случае равно 0, если он не может найти значение int attr, что объясняет, почему оно возвращает 0, если вы используете вновь созданный идентификатор, Я не нашел причины ошибки инфляции.