advice
advice

Reputation: 5988

Android - Custom View - Extending EditText with Views on Top

I'm trying to figure out a good solution on how to extend EditText to allow me to have other Views layered on top. I am trying to make a custom View that is an EditText that has a TextView on top to display the number of characters, and an ImageView on top for a clear button.

Currently, I have it working with extending FrameLayout, but that doesn't give me the control/flexibility that I am looking for. Such as I can't use ButterKnife's @OnTextChanged as it expects a TextView, and I don't have direct access to any XML attributes of the EditText unless I pass them through.

Thanks for your time.

ClearableEditText.java

public class ClearableEditText extends FrameLayout {

    public ClearableEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    protected void init() {
        View inflate = inflate(getContext(), R.layout.clearable_edit_text, this);
        ButterKnife.bind(this, inflate);
        ...
    }

    ...
}

R.layout.clearable_edit_text.xml

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

    <EditText
        android:id="@+id/clearable_edit"
        style="@style/edit_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10" />

    <ImageView
        android:id="@+id/clearable_clear"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:layout_marginRight="10dp"
        android:layout_marginTop="5dp"
        android:src="@drawable/button_clear"
        android:visibility="invisible"
        tools:visibility="visible" />


    <TextView
        android:id="@+id/clearable_count"
        style="@style/edit_text_number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|right"
        tools:text="1200" />
</FrameLayout>

Upvotes: 1

Views: 4762

Answers (1)

Anonymous
Anonymous

Reputation: 4900

I find it simpler in these situations to use an empty layout in the xml which I later fill on runtime with whatever elements I want. example:

<?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:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView ..... />
    <Button........./>
    .
    .
    .
    <LinearLayout 
        android:id="@+id/container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>


</LinearLayout>

and in the activity

LayoutInflater inflater = getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout container = (LinearLayout)findViewById(R.id.container);
MyComplexView myComplexView = new MyComplexView(inflater, container);

where MyComplexView:

    public static class MyComplexView{

        LinearLayout container;
        LayoutInflater inflater;
        TextView textView ;
        ImageView img;
        EditText editText;

        public MyComplexView(LinearLayout container,LayoutInflater inflater ){
            this.container = container;
            this.inflater = inflater;
            View v = (View) inflater.inflate(R.layout.mylayout, null);
            container.addView(v);
            textView = (TextView)v.findViewById(R.id.textview);
            img = (ImageView)v.findViewById(R.id.imgaviev);
            editText = (EditText)v.findViewById(R.id.edittext);
            // assign whatever text change listeners or on click listeners you want
        }

        public void makeEditTextMultiline(boolean flag){
            if(flag){    
                edittext.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_FLAG_MULTI_LINE); 
            }
            else{
                edittext.setSingleLine(true);
            }
        }
        public String getEditTextText(){
            return editText.getText().toString();
        }

    }

After that you can create all sorts of methods in the MyComplexView class to manipulate the object.

I think it's easier this way than extending the View class.

Upvotes: 1

Related Questions