Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android custom EditText view and NextFocusDown

In my register activity there are a few custom EditText views set in a vertical LinearLayout. Top to down.

Because I need some extra functionality for each EditText, I created a custom EditText class that provides that extra functionality. That class relies on some custom attributes that were added in attrs.xml and are retrieved in the class and then set to the inflated EditText.

Everything works fine except for one thing that I can't seem to solve. I can't seem to get NextFocusDown to work on my custom EditText views. When using standard EditText views, it works fine. When I switch to my custom EditText, it ignores it. All other attributes function normally except this one.

What am I missing? Has anyone managed to use that attribute in a custom edit text view ?

Thank you!

EDIT:

This is part of the custom EditText class:

public class CustomEditText extends RelativeLayout {

private LayoutInflater mInflater = null;
private EditText mEditText;
private TextView mHintQuestionMark;
private TextView mHintText;
private Button mButtonClear;

private boolean isExpandView = false;
private boolean clearButtonEnabled = false;
private boolean hintEnabled = false;


public CustomEditText(Context context) {
    super(context);
    initViews();
}

public CustomEditText(Context context, AttributeSet attrs) {
    super(context, attrs);
    initViews();
    getCustomAttributes(context, attrs);
}

public CustomEditText(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    initViews();
    getCustomAttributes(context, attrs);
}

private void initViews() {
    mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    mInflater.inflate(R.layout.custom_edit_text, this, true);
    mHintText = (TextView) findViewById(R.id.theHint);
    mEditText = (EditText) findViewById(R.id.theEditText);

    mEditText.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {

            if (clearButtonEnabled){
                if (charSequence.length() > 0){
                    mButtonClear.setVisibility(VISIBLE);
                } else {
                    mButtonClear.setVisibility(INVISIBLE);
                }
            }
        }

        @Override
        public void afterTextChanged(Editable editable) {

        }
    });

    mHintQuestionMark = (TextView) findViewById(R.id.hintQuestionMark);
    mHintQuestionMark.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (isExpandView) {
                collapseHeight(mHintText);
            } else {

                // Expand the HINT view downwards
                expandHeight(mHintText);
            }
        }
    });

    mButtonClear = (Button) findViewById(R.id.buttonClear);
    mButtonClear.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            mEditText.setText("");
        }
    });
}

private void getCustomAttributes(Context ctx, AttributeSet attrs){
    TypedArray typedArray = ctx.getTheme().obtainStyledAttributes(attrs, R.styleable.edittext_attrs, 0, 0);
    int firstNameId = 0;
    int lastNameId = 0;

    try{
        mEditText.setInputType(typedArray.getInt(R.styleable.edittext_attrs_android_inputType, EditorInfo.TYPE_TEXT_VARIATION_NORMAL));
        mEditText.setHint(typedArray.getString(R.styleable.edittext_attrs_android_hint));
        mEditText.setNextFocusDownId(typedArray.getInt(R.styleable.edittext_attrs_android_nextFocusDown, -1));
        clearButtonEnabled = typedArray.getBoolean(R.styleable.edittext_attrs_add_clear_button, false);
        hintEnabled = typedArray.getBoolean(R.styleable.edittext_attrs_add_hint_icon, false);
    } finally {
        typedArray.recycle();
    }

    if (hintEnabled){
        mHintQuestionMark.setVisibility(VISIBLE);
    } else {
        mHintQuestionMark.setVisibility(GONE);

    }
}

This is the custom edit text xml I'm inflating in that class:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">

<LinearLayout
    android:id="@+id/editTextGroup"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <RelativeLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1">

        <EditText
            android:id="@+id/theEditText"
            android:layout_width="match_parent"
            android:layout_height="52dp"
            android:layout_weight="1"
            android:background="@drawable/edit_text_rectangle"
            android:maxLength="53"
            android:padding="12dp"
            android:visibility="visible" />

        <Button
            android:id="@+id/buttonClear"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:background="@drawable/remove_text_x"
            android:layout_marginLeft="5dp"
            android:visibility="gone" />

    </RelativeLayout>

    <TextView
        android:id="@+id/hintQuestionMark"
        android:layout_width="36dp"
        android:layout_height="52dp"
        android:text="\?"
        android:textColor="#eeeeee"
        android:textSize="30sp"
        android:gravity="center"
        android:layout_gravity="right"
        android:background="#288abf"
        android:visibility="gone" />

</LinearLayout>

<TextView
    android:id="@+id/theHint"
    android:layout_width="match_parent"
    android:layout_height="120dp"
    android:padding="8dp"
    android:text="@string/txtEmailHintText"
    android:textColor="#eeeeee"
    android:textSize="15sp"
    android:gravity="left"
    android:background="#288abf"
    android:layout_alignLeft="@+id/editTextGroup"
    android:layout_below="@+id/editTextGroup"
    android:visibility="gone" />

</RelativeLayout>

This is the attrs.xml file I use to get the values in the custom edittext class:

<?xml version="1.0" encoding="utf-8"?>
<resources>

<declare-styleable name="edittext_attrs">

    <attr name="android:inputType" />
    <attr name="android:hint" />
    <attr name="android:nextFocusDown" />
    <attr name="add_clear_button" format="boolean" />
    <attr name="add_hint_icon" format="boolean" />

</declare-styleable>
</resources>

And this is a tiny part of the layout xml I use for the register activity with its two views that should use the NextFocusDown:

 <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="16dp">

        <com.name.view.customViews.CustomEditText
            android:id="@+id/registerTxtFirstName"
            android:layout_width="133dp"
            android:layout_height="52dp"
            android:nextFocusDown="@+id/registerTxtLastName"
            android:layout_alignParentLeft="true"
            android:inputType="textPersonName"
            custom:add_clear_button="true"
            android:hint="@string/first"
            android:visibility="visible" />

        <com.name.view.customViews.CustomEditText
            android:id="@+id/registerTxtLastName"
            android:layout_width="133dp"
            android:layout_height="52dp"
            android:layout_alignParentRight="true"
            custom:add_clear_button="true"
            android:hint="@string/last"
            android:inputType="textPersonName"
            android:visibility="visible" />


    </RelativeLayout>

I hope there's enough information here to see what the problem is.

Thanks!

like image 382
Alon Minski Avatar asked Nov 02 '22 05:11

Alon Minski


2 Answers

Old post but I'm submitting this answer in case anyone else runs into the same problem.

In my case, I found using setOnClickListener() on the CustomEditText in question causes the android:nextFocusDown="" xml property to not function properly.

For example:

myxml.xml

<com.view.MyCustomEditText
    android:id="@+id/username"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="16dp"
    android:hint="@string/email_username"
    android:inputType="textEmailAddress"
    android:nextFocusDown="@+id/password"/>

<EditText
    android:id="@+id/password"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:hint="@string/password_hint"
    android:inputType="textPassword"
    android:imeOptions="actionDone"/>

MainActivity.java:

mUserEditText = (EditText) findViewById(R.id.username);
mPasswordEditText = (EditText) findViewById(R.id.password);
// Instead of using this
mEditText.setOnClickListener(this)
// Use
mEditText.setOnTouchListener(this)
like image 153
jds17 Avatar answered Nov 11 '22 09:11

jds17


You can copy imeOptions attribute from system attrs.xml file to your custom view attributes

<?xml version="1.0" encoding="UTF-8"?>
<resources>
    <declare-styleable name="CustomEditText">
        <attr name="imeOptions">
            <flag name="normal" value="0x00000000" />
            <flag name="actionUnspecified" value="0x00000000" />
            <flag name="actionNone" value="0x00000001" />
            <flag name="actionGo" value="0x00000002" />
            <flag name="actionSearch" value="0x00000003" />
            <flag name="actionSend" value="0x00000004" />
            <flag name="actionNext" value="0x00000005" />
            <flag name="actionDone" value="0x00000006" />
            <flag name="actionPrevious" value="0x00000007" />
            <flag name="flagNoPersonalizedLearning" value="0x1000000" />
            <flag name="flagNoFullscreen" value="0x2000000" />
            <flag name="flagNavigatePrevious" value="0x4000000" />
            <flag name="flagNavigateNext" value="0x8000000" />
            <flag name="flagNoExtractUi" value="0x10000000" />
            <flag name="flagNoAccessoryAction" value="0x20000000" />
            <flag name="flagNoEnterAction" value="0x40000000" />
            <flag name="flagForceAscii" value="0x80000000" />
        </attr>
    </declare-styleable>
</resources>

Then when you use your custom EditText use imeOptions attribute with your 'custom'(or name it whatever you like) namespace

<RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="16dp">

        <com.name.view.customViews.CustomEditText
            android:id="@+id/registerTxtFirstName"
            android:layout_width="133dp"
            android:layout_height="52dp"
            android:nextFocusDown="@+id/registerTxtLastName"
            android:layout_alignParentLeft="true"
            android:inputType="textPersonName"
            custom:add_clear_button="true"
            custom:imeOptions="actionNext"
            android:hint="@string/first"
            android:visibility="visible" />

        <com.name.view.customViews.CustomEditText
            android:id="@+id/registerTxtLastName"
            android:layout_width="133dp"
            android:layout_height="52dp"
            android:layout_alignParentRight="true"
            custom:add_clear_button="true"
            custom:imeOptions="actionDone"
            android:hint="@string/last"
            android:inputType="textPersonName"
            android:visibility="visible" />
    </RelativeLayout>

And the last step is parse this attribute in your custom EditText and set it to the system one.

TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CustomEditText);
int imeOptions = array.getInt(R.styleable.CustomEditText_imeOptions, EditorInfo.IME_NULL);
systemEditText.setImeOptions(imeOptions);
array.recycle();
like image 29
voronnenok Avatar answered Nov 11 '22 11:11

voronnenok