简体   繁体   中英

Android: EditText in CustomView not behaving as expected when touched

I have a CustomView which contains a LinearLayout that holds an EditText & another custom view element. However, when I run my app and touch the EditText it does not behave as expected (doesn't appear to receive focus & the soft keyboard doesn't open). I've tried setting duplicateParentState="true" on both the EditText & the LinearLayout. I also attached an onTouchEventListener to the EditText that calls a simple toast & the toast did show up.

Here's the code for my 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>

Min SDK Version is set at 14, target is set at 20. Any help would be greatly appreciated!

EDIT:

I got this logcat message today while testing long presses on my FormFields.

W/TextView﹕ TextView does not support text selection. Action mode cancelled.

I double checked my code and the EditText element is only ever cast as an EditText. If the EditText is being cast to a TextView that would explain my original issues but now I'm confused as to why or how it was cast as a TextView.

It looks like you are extending LinearLayout but never using it in your layout. From what you've posted, you aren't using the FormField at all and the only custom View I see is the ValidationIcon view. So hooking the touch events into EditText and ValidationIcon aren't occurring because you aren't using FormField in your layout.xml.

Rather than extending LinearLayout, why not just use the predefined methods and attributes to handle the behaviour you are trying to achieve. For example, displaying keyboard, requesting focus, and displaying hint:

<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" />

The keyboard should display when the edit text receives focus, if not you could programmatically do this by requesting focus and handling the IME manager call. For example, from the 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'

  • 在此处输入图片说明

use this code for custom Edittext with title


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()
        }
    
    
    }


main/../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" />


thanks you

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM