Skip to content

Instantly share code, notes, and snippets.

@Popalay
Last active June 6, 2017 07:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Popalay/c81d3f53f32c0998999fad95043fbc76 to your computer and use it in GitHub Desktop.
Save Popalay/c81d3f53f32c0998999fad95043fbc76 to your computer and use it in GitHub Desktop.
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.annotation.ArrayRes;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.widget.AppCompatAutoCompleteTextView;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import java.util.Calendar;
public class MaterialSpinner extends AppCompatAutoCompleteTextView implements AdapterView.OnItemClickListener {
private static final int DEFAULT_RES = -1;
private static final int MAX_CLICK_DURATION = 200;
private long startClickTime;
private boolean isPopup;
private int mPosition = ListView.INVALID_POSITION;
private Object mSelectedItem;
private OnItemSelectedListener mOnItemSelectedListener;
private int mDrawableTint = DEFAULT_RES;
private Drawable mDrawableRight;
public MaterialSpinner(Context context) {
super(context);
inflate(context, null);
setOnItemClickListener(this);
}
public MaterialSpinner(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
inflate(context, attributeSet);
setOnItemClickListener(this);
}
public MaterialSpinner(Context context, AttributeSet attributeSet, int arg2) {
super(context, attributeSet, arg2);
inflate(context, attributeSet);
setOnItemClickListener(this);
}
@Override
public boolean enoughToFilter() {
return true;
}
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
if (focused && getFilter() != null) {
performFiltering("", 0);
final InputMethodManager imm = (InputMethodManager) getContext()
.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getWindowToken(), 0);
setKeyListener(null);
dismissDropDown();
} else {
isPopup = false;
}
}
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
mPosition = position;
mSelectedItem = adapterView.getItemAtPosition(position);
isPopup = false;
if (mOnItemSelectedListener != null) {
mOnItemSelectedListener.onItemSelected(position);
}
}
@Override
public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top, Drawable right, Drawable bottom) {
final Drawable dropdownIcon = ContextCompat.getDrawable(getContext(), R.drawable.ic_dropdown);
if (dropdownIcon != null) {
mDrawableRight = dropdownIcon;
right = dropdownIcon;
}
super.setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
startClickTime = Calendar.getInstance().getTimeInMillis();
break;
}
case MotionEvent.ACTION_UP: {
final long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime;
if (clickDuration < MAX_CLICK_DURATION) {
if (isPopup) {
dismissDropDown();
isPopup = false;
} else {
requestFocus();
showDropDown();
isPopup = true;
}
}
}
}
return super.onTouchEvent(event);
}
public void setOnItemSelectedListener(OnItemSelectedListener onItemSelectedListener) {
mOnItemSelectedListener = onItemSelectedListener;
}
public void setupSpinner(@ArrayRes int arrayRes, @StringRes int stringRes) {
final ArrayAdapter<String> adapter = new ArrayAdapter<>(getContext(),
android.R.layout.simple_dropdown_item_1line,
getResources().getStringArray(arrayRes));
setAdapter(adapter);
setSelectedItem(getContext().getString(stringRes));
}
public int getPosition() {
return mPosition;
}
@Nullable
public <T> T getSelectedItem() {
//noinspection unchecked
return (T) mSelectedItem;
}
/**
* To use this method you must override equals method
*/
public <T> void setSelectedItem(T item) {
if (getAdapter() == null || item == null) {
return;
}
post(() -> {
for (int i = 0; i < getAdapter().getCount(); i++) {
final Object current = getAdapter().getItem(i);
if (current.equals(item)) {
mPosition = i;
mSelectedItem = current;
setText(current.toString());
if (mOnItemSelectedListener != null) {
mOnItemSelectedListener.onItemSelected(mPosition);
}
return;
}
}
});
}
private void inflate(Context context, AttributeSet attributeSet) {
final TypedArray typedArray = context
.obtainStyledAttributes(attributeSet, R.styleable.MaterialSpinner, 0, 0);
try {
mDrawableTint = typedArray.getColor(R.styleable.MaterialSpinner_drawableTintColor, mDrawableTint);
if (mDrawableTint != DEFAULT_RES) {
final Drawable wrappedDrawable = DrawableCompat.wrap(mDrawableRight).mutate();
DrawableCompat.setTint(wrappedDrawable, mDrawableTint);
}
} finally {
typedArray.recycle();
}
invalidate();
}
private void setText(String text) {
setFocusable(false);
setFocusableInTouchMode(false);
super.setText(text);
setFocusable(true);
setFocusableInTouchMode(true);
}
public interface OnItemSelectedListener {
void onItemSelected(int position);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment