Android:CustomView 中的 EditText 在被触摸时没有按预期表现
Android: EditText in CustomView not behaving as expected when touched
我有一个 CustomView,其中包含一个包含 EditText 和另一个自定义视图元素的 LinearLayout。但是,当我 运行 我的应用程序并触摸 EditText 时,它的行为不像预期的那样(似乎没有接收到焦点并且软键盘没有打开)。我已经尝试在 EditText 和 LinearLayout 上设置 duplicateParentState="true"。我还在 EditText 上附加了一个 onTouchEventListener,它调用了一个简单的 toast 并且 toast 确实出现了。
这是我的 CustomView 的代码。
form_field.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_marginBottom="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/grey_rounded_borders">
<EditText
android:id="@+id/edit_text"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:inputType="text"
android:padding="10dp"
android:textColor="#2d6169"
android:textSize="18sp"
android:background="@color/transparent" />
<RelativeLayout
android:layout_marginStart="5dp"
android:layout_marginEnd="10dp"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<com.example.app.ValidationIcon
android:id="@+id/validation_icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
</RelativeLayout>
</LinearLayout>
FormField.java
package com.example.app;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.InputType;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import java.util.ArrayList;
public class FormField extends LinearLayout {
private EditText editText;
private ValidationIcon validationIcon;
private Integer fieldInputType;
private String fieldInputHint;
public FormField(Context context)
{
super(context);
}
public FormField(Context context, AttributeSet attributeSet)
{
super(context, attributeSet);
TypedArray attrs = context.obtainStyledAttributes(attributeSet, R.styleable.FormField, 0, 0);
fieldInputType = attrs.getInt(
R.styleable.FormField_fieldInputType,
InputType.TYPE_TEXT_VARIATION_NORMAL
);
fieldInputHint = attrs.getString(
R.styleable.FormField_fieldInputHint
);
attrs.recycle();
inflate(getContext(), R.layout.form_field, this);
this.setFocusable(true);
this.setFocusableInTouchMode(true);
editText = (EditText)findViewById(R.id.edit_text);
editText.setInputType(fieldInputType);
editText.setHint(fieldInputHint);
editText.setFocusableInTouchMode(true);
validationIcon = (ValidationIcon)findViewById(R.id.validation_icon);
validationIcon.setValid(true);
ArrayList<View> touchables = new ArrayList<View>();
touchables.add(this);
touchables.add(editText);
addTouchables(touchables);
}
public FormField(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
}
registration_layout.xml
<RelativeLayout android:id="@+id/container"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp">
<RelativeLayout android:id="@+id/account_details"
android:layout_marginBottom="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.app.FormField
android:id="@+id/name_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:fieldInputHint="@string/name_field_hint" />
<com.example.app.FormField
android:id="@+id/email_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:fieldInputHint="@string/email_field_hint" />
<com.example.app.FormField
android:id="@+id/password_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:fieldInputHint="@string/password_field_hint" />
<com.example.app.FormField
android:id="@+id/re_password_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:fieldInputHint="@string/re_password_field_hint" />
</RelativeLayout>
</RelativeLayout>
最低 SDK 版本设置为 14,目标设置为 20。如有任何帮助,我们将不胜感激!
编辑:
我今天在我的 FormFields 上测试长按时收到这条 logcat 消息。
W/TextView﹕ TextView does not support text selection. Action mode cancelled.
我仔细检查了我的代码,发现 EditText 元素仅被转换为 EditText。如果将 EditText 转换为 TextView,这可以解释我原来的问题,但现在我很困惑为什么或如何将它转换为 TextView。
看起来您正在扩展 LinearLayout 但从未在您的布局中使用它。根据您发布的内容,您根本没有使用 FormField,我看到的唯一自定义视图是 ValidationIcon 视图。因此,将触摸事件挂接到 EditText 和 ValidationIcon 不会发生,因为您没有在 layout.xml 中使用 FormField。
与其扩展 LinearLayout,不如使用预定义的方法和属性来处理您试图实现的行为。例如显示键盘、请求焦点、显示提示:
<EditText
android:id="@+id/edit_text"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
**android:inputType="text"**
**android:hint="@styleable/FormField_fieldInputHint"**
android:padding="10dp"
android:textColor="#2d6169"
android:textSize="18sp"
android:background="@color/transparent" />
当编辑文本获得焦点时应该显示键盘,否则您可以通过请求焦点和处理 IME 管理器调用以编程方式执行此操作。例如,来自 Activity/Fragment:
//call this from onViewCreated to grab focus and begin the flow
editText.requestFocus();
//set focus listener to handle keyboard display
editText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
InputMethodManager imm = (InputMethodManager)getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(myEditText.getWindowToken(), 0);
} else {
InputMethodManager imm = (InputMethodManager)getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.showSoftInputFromWindow(myEditText.getWindowToken(), 0);
}
});
确保没有设置 inputType:'none'
或 '0X000000'
将此代码用于带有标题的自定义 Edittext
custom_view.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:foregroundGravity="right"
app:layout_anchorGravity="right">
<LinearLayout
android:orientation="vertical"
android:id="@+id/search_closed_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center|right"
android:background="@color/white"
android:foregroundGravity="center"
android:gravity="right">
<TextView
android:id="@+id/txt_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|left"
android:layout_marginStart="16dp"
android:layout_marginTop="14dp"
android:fontFamily="@font/intel"
android:foregroundGravity="center"
android:text="textview"
android:textColor="@color/title_color"
android:textSize="14dp"
android:textStyle="bold" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/lay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:clickable="true"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/edt_text"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@drawable/edit_txtbg"
android:fontFamily="@font/intel"
android:gravity="center|start"
android:paddingStart="24dp"
android:textColor="@color/text_color"
android:textColorHint="@color/txt_hint"
android:textSize="@dimen/text_nev"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/img_add_patient"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</FrameLayout>
CustomEditText.kt
package com.mdppractice.custom
import android.content.Context
import android.text.InputType
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.EditText
import android.widget.FrameLayout
import android.widget.TextView
import com.mdppractice.R
class CustomEditText(
context: Context,
attrs: AttributeSet,
) : FrameLayout(context, attrs) {
private var txt_title: TextView
private var edt_text: EditText
init {
LayoutInflater.from(context)
.inflate(R.layout.custom_view, this, true)
txt_title = findViewById(R.id.txt_title)
edt_text = findViewById(R.id.edt_text)
val a = context.obtainStyledAttributes(attrs, R.styleable.CustomEditText)
txt_title.text = a.getString(R.styleable.CustomEditText_title)
edt_text.hint = a.getString(R.styleable.CustomEditText_hint)
when(a.getString(R.styleable.CustomEditText_inputType)) {
"number" -> edt_text.inputType = InputType.TYPE_CLASS_PHONE
"textCapSentences" -> edt_text.inputType = InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
"text" -> edt_text.inputType = InputType.TYPE_CLASS_TEXT
}
a.recycle()
}
fun setmInputType(type: Int) {
edt_text.setRawInputType(InputType.TYPE_CLASS_TEXT)
setmInputType(type)
}
fun setTitle(title: Int) {
txt_title.setText(title)
}
fun set_Text(title: Int) {
edt_text.setText(title)
}
fun getTitle(): String {
return txt_title.text.toString()
}
fun get_Text(): String {
return edt_text.text.toString()
}
}
主/../attr.xml
<declare-styleable name="CustomEditText">
<attr name="title" format="string"/>
<attr name="onCenter" format="boolean"/>
<attr name="hint" format="string"/>
<attr name="maxLength" format="integer"/>
<attr name="inputType" format="string"/>
</declare-styleable>
@drawable/edit_txtbg
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/listview_background_shape">
<stroke android:width="1dp" android:color="@color/button_bg_border" />
<padding android:left="0dp"
android:top="0dp"
android:right="0dp"
android:bottom="0dp" />
<corners android:radius="6dp"/>
<solid android:color="@color/button_bg" />
</shape>
-
use in layout
<com.mdppractice.custom.CustomEditText
android:id="@+id/edt_custom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="Patient ID/Phone"
android:autofillHints="@string/verified"
android:foregroundGravity="center"
android:hint="Please enter name"
app:inputType="textCapSentences"
android:textColor="@color/title_color"
android:textSize="14dp"
android:textStyle="bold" />
谢谢
我有一个 CustomView,其中包含一个包含 EditText 和另一个自定义视图元素的 LinearLayout。但是,当我 运行 我的应用程序并触摸 EditText 时,它的行为不像预期的那样(似乎没有接收到焦点并且软键盘没有打开)。我已经尝试在 EditText 和 LinearLayout 上设置 duplicateParentState="true"。我还在 EditText 上附加了一个 onTouchEventListener,它调用了一个简单的 toast 并且 toast 确实出现了。
这是我的 CustomView 的代码。
form_field.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_marginBottom="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/grey_rounded_borders">
<EditText
android:id="@+id/edit_text"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:inputType="text"
android:padding="10dp"
android:textColor="#2d6169"
android:textSize="18sp"
android:background="@color/transparent" />
<RelativeLayout
android:layout_marginStart="5dp"
android:layout_marginEnd="10dp"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<com.example.app.ValidationIcon
android:id="@+id/validation_icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
</RelativeLayout>
</LinearLayout>
FormField.java
package com.example.app;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.InputType;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import java.util.ArrayList;
public class FormField extends LinearLayout {
private EditText editText;
private ValidationIcon validationIcon;
private Integer fieldInputType;
private String fieldInputHint;
public FormField(Context context)
{
super(context);
}
public FormField(Context context, AttributeSet attributeSet)
{
super(context, attributeSet);
TypedArray attrs = context.obtainStyledAttributes(attributeSet, R.styleable.FormField, 0, 0);
fieldInputType = attrs.getInt(
R.styleable.FormField_fieldInputType,
InputType.TYPE_TEXT_VARIATION_NORMAL
);
fieldInputHint = attrs.getString(
R.styleable.FormField_fieldInputHint
);
attrs.recycle();
inflate(getContext(), R.layout.form_field, this);
this.setFocusable(true);
this.setFocusableInTouchMode(true);
editText = (EditText)findViewById(R.id.edit_text);
editText.setInputType(fieldInputType);
editText.setHint(fieldInputHint);
editText.setFocusableInTouchMode(true);
validationIcon = (ValidationIcon)findViewById(R.id.validation_icon);
validationIcon.setValid(true);
ArrayList<View> touchables = new ArrayList<View>();
touchables.add(this);
touchables.add(editText);
addTouchables(touchables);
}
public FormField(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
}
registration_layout.xml
<RelativeLayout android:id="@+id/container"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp">
<RelativeLayout android:id="@+id/account_details"
android:layout_marginBottom="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.app.FormField
android:id="@+id/name_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:fieldInputHint="@string/name_field_hint" />
<com.example.app.FormField
android:id="@+id/email_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:fieldInputHint="@string/email_field_hint" />
<com.example.app.FormField
android:id="@+id/password_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:fieldInputHint="@string/password_field_hint" />
<com.example.app.FormField
android:id="@+id/re_password_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:fieldInputHint="@string/re_password_field_hint" />
</RelativeLayout>
</RelativeLayout>
最低 SDK 版本设置为 14,目标设置为 20。如有任何帮助,我们将不胜感激!
编辑:
我今天在我的 FormFields 上测试长按时收到这条 logcat 消息。
W/TextView﹕ TextView does not support text selection. Action mode cancelled.
我仔细检查了我的代码,发现 EditText 元素仅被转换为 EditText。如果将 EditText 转换为 TextView,这可以解释我原来的问题,但现在我很困惑为什么或如何将它转换为 TextView。
看起来您正在扩展 LinearLayout 但从未在您的布局中使用它。根据您发布的内容,您根本没有使用 FormField,我看到的唯一自定义视图是 ValidationIcon 视图。因此,将触摸事件挂接到 EditText 和 ValidationIcon 不会发生,因为您没有在 layout.xml 中使用 FormField。
与其扩展 LinearLayout,不如使用预定义的方法和属性来处理您试图实现的行为。例如显示键盘、请求焦点、显示提示:
<EditText
android:id="@+id/edit_text"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
**android:inputType="text"**
**android:hint="@styleable/FormField_fieldInputHint"**
android:padding="10dp"
android:textColor="#2d6169"
android:textSize="18sp"
android:background="@color/transparent" />
当编辑文本获得焦点时应该显示键盘,否则您可以通过请求焦点和处理 IME 管理器调用以编程方式执行此操作。例如,来自 Activity/Fragment:
//call this from onViewCreated to grab focus and begin the flow
editText.requestFocus();
//set focus listener to handle keyboard display
editText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
InputMethodManager imm = (InputMethodManager)getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(myEditText.getWindowToken(), 0);
} else {
InputMethodManager imm = (InputMethodManager)getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.showSoftInputFromWindow(myEditText.getWindowToken(), 0);
}
});
确保没有设置 inputType:'none'
或 '0X000000'
将此代码用于带有标题的自定义 Edittext
custom_view.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:foregroundGravity="right"
app:layout_anchorGravity="right">
<LinearLayout
android:orientation="vertical"
android:id="@+id/search_closed_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center|right"
android:background="@color/white"
android:foregroundGravity="center"
android:gravity="right">
<TextView
android:id="@+id/txt_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|left"
android:layout_marginStart="16dp"
android:layout_marginTop="14dp"
android:fontFamily="@font/intel"
android:foregroundGravity="center"
android:text="textview"
android:textColor="@color/title_color"
android:textSize="14dp"
android:textStyle="bold" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/lay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:clickable="true"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/edt_text"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@drawable/edit_txtbg"
android:fontFamily="@font/intel"
android:gravity="center|start"
android:paddingStart="24dp"
android:textColor="@color/text_color"
android:textColorHint="@color/txt_hint"
android:textSize="@dimen/text_nev"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/img_add_patient"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</FrameLayout>
CustomEditText.kt
package com.mdppractice.custom
import android.content.Context
import android.text.InputType
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.EditText
import android.widget.FrameLayout
import android.widget.TextView
import com.mdppractice.R
class CustomEditText(
context: Context,
attrs: AttributeSet,
) : FrameLayout(context, attrs) {
private var txt_title: TextView
private var edt_text: EditText
init {
LayoutInflater.from(context)
.inflate(R.layout.custom_view, this, true)
txt_title = findViewById(R.id.txt_title)
edt_text = findViewById(R.id.edt_text)
val a = context.obtainStyledAttributes(attrs, R.styleable.CustomEditText)
txt_title.text = a.getString(R.styleable.CustomEditText_title)
edt_text.hint = a.getString(R.styleable.CustomEditText_hint)
when(a.getString(R.styleable.CustomEditText_inputType)) {
"number" -> edt_text.inputType = InputType.TYPE_CLASS_PHONE
"textCapSentences" -> edt_text.inputType = InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
"text" -> edt_text.inputType = InputType.TYPE_CLASS_TEXT
}
a.recycle()
}
fun setmInputType(type: Int) {
edt_text.setRawInputType(InputType.TYPE_CLASS_TEXT)
setmInputType(type)
}
fun setTitle(title: Int) {
txt_title.setText(title)
}
fun set_Text(title: Int) {
edt_text.setText(title)
}
fun getTitle(): String {
return txt_title.text.toString()
}
fun get_Text(): String {
return edt_text.text.toString()
}
}
主/../attr.xml
<declare-styleable name="CustomEditText">
<attr name="title" format="string"/>
<attr name="onCenter" format="boolean"/>
<attr name="hint" format="string"/>
<attr name="maxLength" format="integer"/>
<attr name="inputType" format="string"/>
</declare-styleable>
@drawable/edit_txtbg
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/listview_background_shape">
<stroke android:width="1dp" android:color="@color/button_bg_border" />
<padding android:left="0dp"
android:top="0dp"
android:right="0dp"
android:bottom="0dp" />
<corners android:radius="6dp"/>
<solid android:color="@color/button_bg" />
</shape>
-
use in layout
<com.mdppractice.custom.CustomEditText android:id="@+id/edt_custom" android:layout_width="match_parent" android:layout_height="wrap_content" app:title="Patient ID/Phone" android:autofillHints="@string/verified" android:foregroundGravity="center" android:hint="Please enter name" app:inputType="textCapSentences" android:textColor="@color/title_color" android:textSize="14dp" android:textStyle="bold" />
谢谢