AppCompatEditText.getpParent() внутри TextInputLayout возвращает FrameLayout
Я создаю простой AppCompatEditText, добавляю OnFocusChangeListener и помещаю его в простой TextInputLayout.
Когда AppCompatEditText теряет фокус, его содержимое должно проверяться методом isValidParam.
Это работало до вчерашнего дня, когда я использовал rev.23.0.3 Но теперь, когда я использовал rev.24.0.2, выдает ошибку, как показано ниже в 1-й строке метода isValidParam.
java.lang.ClassCastException: android.widget.FrameLayout не может быть приведен к android.support.design.widget.TextInputLayout
Я проверил в режиме отладки. AppCompatEditText.getpParent() действительно возвращает Framelayout вместо TextInputLayout.
LinearLayout llParams = new LinearLayout(context);
llParams.setOrientation(LinearLayout.VERTICAL);
// Create label for param
final TextInputLayout tilParam = new TextInputLayout(context);
// Add label into layout
llParams.addView(tilParam);
// Create Editor for param
final AppCompatEditText etParam = new AppCompatEditText(context);
edParam.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus)
if (isValidParam(etParam)) {
do some thing;
} else {
do other thing;
}
}
});
tilParam.addView(etParam);
// validation method
boolean isValidParam(AppCompatEditText editText) {
TextInputLayout til = (TextInputLayout) editText.getParent();
String text = editText.getText().toString().trim();
if (!text.equls("some criteria") {
till.setError("Error text")
return false;
}
return true;
}
5 ответов
Обновить:
Используйте виджет TextInputEditText
вместо EditText
внутри TextInputLayout.
старый ответ
TextInputLayout textInputLayout = (TextInputLayout) editText.getParent().getParent();
Это кажется быстрым решением. Далеко от идеала.
Вы можете проверить, находится ли EditText внутри TextInputLayout, используя следующий метод:
public static <ParentClass> ParentClass getFirstParent(View view, Class<ParentClass> parentClass) {
if (view.getParent() instanceof View) {
if (parentClass.isInstance(view.getParent())) {
return (ParentClass) view.getParent();
} else {
return getFirstParent((View) view.getParent(), parentClass);
}
} else {
return null;
}
}
Пример использования:
TextInputLayout textInputLayout = getFirstParent(editText, TextInputLayout.class)
Просто выдержки из официальных документов Android:
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/form_username"/>
</android.support.design.widget.TextInputLayout>
Примечание. Фактическая иерархия представления, представленная в TextInputLayout, НЕ гарантируется в соответствии с иерархией представления, записанной в XML. В результате вызовы getParent() для дочерних элементов TextInputLayout, таких как TextInputEditText, могут не возвращать сам TextInputLayout, а скорее промежуточное представление. Если вам нужен прямой доступ к View, установите android:id и используйте findViewById(int).
Поэтому, чтобы решить проблему, вы должны обратиться к findViewById
вместо getParent
из-за дополнительной раскладки между ними, представленной в версии 24.
Вы можете проверить код TextInputLayout
v24.xx
Теперь это работает с FrameLayout
,
@Override
public void addView(View child, int index, final ViewGroup.LayoutParams params) {
if (child instanceof EditText) {
mInputFrame.addView(child, new FrameLayout.LayoutParams(params));
//...
} else {
// Carry on adding the View...
super.addView(child, index, params);
}
}
где mInputFrame
это FrameLayout
,
Это причина вашей проблемы (родитель FrameLayout
).
Просто передайте tilParam
в качестве параметра, вместо использования getParent()
если вам нужно использовать это.
TextInputLayout имеет метод getEditText(). Это может быть альтернативный способ решения вашей проблемы. Вместо того, чтобы начинать с самого EditText и получать родительский TextInputLayout, вы можете начать с TextInputLayout и просто получить дочернее представление EditText. Для представлений, сгенерированных xml, следующий код является примером:
TextInputLayout someInputLayout = findViewById(R.id.some_input_layout);
EditText someEditText = someInputLayout.getEditText();
String text = someEditText.getText().toString();
Это могло бы быть более желательным решением, поскольку оно не требует каких-либо внешних методов, хотя это не решит вашу проблему, если по какой-то причине требуется, чтобы вы начинали с EditText. Я знаю, что на это давным-давно был дан ответ, но я использовал решение @sylwano, пока не обнаружил, что для моей конкретной проблемы было лучше сделать то, что указано выше.