Skip to content

Instantly share code, notes, and snippets.

@rodrigohenriques
Last active February 12, 2023 07:44
Show Gist options
  • Star 56 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save rodrigohenriques/77398a81b5d01ac71c3b to your computer and use it in GitHub Desktop.
Save rodrigohenriques/77398a81b5d01ac71c3b to your computer and use it in GitHub Desktop.
Used to make your EditText a better option than Spinners
public class ClickToSelectEditText<T extends Listable> extends AppCompactEditText {
List<T> mItems;
String[] mListableItems;
CharSequence mHint;
OnItemSelectedListener<T> onItemSelectedListener;
public ClickToSelectEditText(Context context) {
super(context);
mHint = getHint();
}
public ClickToSelectEditText(Context context, AttributeSet attrs) {
super(context, attrs);
mHint = getHint();
}
public ClickToSelectEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mHint = getHint();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ClickToSelectEditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mHint = getHint();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
setFocusable(false);
setClickable(true);
}
public void setItems(List<T> items) {
this.mItems = items;
this.mListableItems = new String[items.size()];
int i = 0;
for (T item : mItems) {
mListableItems[i++] = item.getLabel();
}
configureOnClickListener();
}
private void configureOnClickListener() {
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());
builder.setTitle(mHint);
builder.setItems(mListableItems, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int selectedIndex) {
setText(mListableItems[selectedIndex]);
if (onItemSelectedListener != null) {
onItemSelectedListener.onItemSelectedListener(mItems.get(selectedIndex), selectedIndex);
}
}
});
builder.setPositiveButton(R.string.dialog_close_button, null);
builder.create().show();
}
});
}
public void setOnItemSelectedListener(OnItemSelectedListener<T> onItemSelectedListener) {
this.onItemSelectedListener = onItemSelectedListener;
}
public interface OnItemSelectedListener<T> {
void onItemSelectedListener(T item, int selectedIndex);
}
}
public interface Listable {
String getLabel();
}
@InjectView(R.id.signup_text_input_job_category)
ClickToSelectEditText<JobCategory> editTextJobCategory;
...
editTextJobCategory.setItems(jobCategories);
editTextJobCategory.setOnItemSelectedListener(new ClickToSelectEditText.OnItemSelectedListener<JobCategory>() {
@Override
public void onItemSelectedListener(JobCategory item, int selectedIndex) {
selectedJobCategory = item;
}
});
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.your.package.ClickToSelectEditText
android:id="@+id/signup_text_input_job_category"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/hint_job_category" />
</android.support.design.widget.TextInputLayout>
@ovictorpinto
Copy link

suggestion setLongClickable(false); to avoid Past action

@ronak-lm
Copy link

ronak-lm commented Oct 25, 2016

Hey Rodrigo,
Thanks for this. However, I found a bug. This doesn't look consistent on all versions of Android. I tried running it on Android 2.3.7 and instead of using the AppCompat style of EditText, it used the old gingerbread style. Check the screenshot attached. Fortunately it gets fixed when you extend AppCompactEditText instead of just EditText. More on that here.
You can find my fork of this here.

Before vs After:-
before after

@rodrigohenriques
Copy link
Author

Thank you @ronak-lm. I just updated my gist according to your suggestion.

@shingz96
Copy link

Maybe now can extend TextInputEditText to have better support as it extend AppCompatEditText but with better support with TextInputLayout

@Prosquid1
Copy link

extends AppCompatEditText not AppCompactEditText.

@AdamMc331
Copy link

When I do this, I don't see the line below the input like I do if it's a TextInputEditText. I'm writing this in Kotlin, so I wonder if I'm doing something slightly wrong.

screen shot 2018-01-26 at 11 21 09 pm

screen shot 2018-01-26 at 11 21 19 pm

class SpinnerInputEditText<T> : AppCompatEditText, View.OnClickListener {
    var items: List<T> = ArrayList()

    private val displayItems: Array<String>
        get() = items.map { it.toString() }.toTypedArray()

    var onItemSelectedListener: OnItemSelectedListener<T>? = null

    constructor(context: Context?) : this(context, null)
    constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    init {
        setOnClickListener(this)
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        isFocusable = false
        isClickable = true
    }

    override fun onClick(v: View?) {
        v?.context?.let {
            AlertDialog.Builder(it)
                    .setTitle(hint)
                    .setItems(displayItems, { _, which ->
                        setText(displayItems[which])
                        onItemSelectedListener?.onItemSelected(items[which], which)
                    })
                    .setPositiveButton("Close", null)
                    .create()
                    .show()
        }
    }

    interface OnItemSelectedListener<in T> {
        fun onItemSelected(item: T, index: Int)
    }
}

@Garcia123
Copy link

hello you do not have your project to be able to see it

@peterMonteer
Copy link

peterMonteer commented Mar 1, 2018

Can you give an example of what JobCategory would look like?
Also what is this "selectedJobCategory "?
Thanks

@DjangoLC
Copy link

DjangoLC commented Jan 2, 2019

@peterMonteer JobCategory just a POJO class and selectedJobCategory is the the object selected in this case is object type JobCategory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment