Output :
colors.xml
<?xml version="1.0" encoding="utf-8"?><resources> <color name="colorPrimary">#3F51B5</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorAccent">#FF4081</color> <color name="list_even">#AAAAAA</color> <color name="list_odd">#E1E2E2</color> <color name="list_selected">#455FB6</color> <color name="red">#FF0000</color> </resources>
strings.xml
<resources> <string name="app_name">MultipleSelectionCheckBox</string> <string name="type_to_search">Type to Search</string> <string-array name="sports_array"> <item>Shuttle Badminton</item> <item>Tennis</item> <item>Table Tennis</item> <item>Basket Ball</item> <item>Foot Ball</item> <item>Volley Ball</item> <item>Hockey</item> <item>Swimming</item> <item>Shuttle Badminton 2</item> <item>Tennis 2</item> <item>Table Tennis 2</item> <item>Basket Ball 2</item> <item>Foot Ball 2</item> <item>Volley Ball 2</item> <item>Hockey 2</item> <item>Swimming 2</item> <item>Shuttle Badminton 3</item> <item>Tennis 3</item> <item>Table Tennis 3</item> <item>Basket Ball 3</item> <item>Foot Ball 3</item> <item>Volley Ball 3</item> <item>Hockey 3</item> <item>Swimming 3</item> <item>Shuttle Badminton 4</item> <item>Tennis 4</item> <item>Table Tennis 4</item> <item>Basket Ball 4</item> <item>Foot Ball 4</item> <item>Volley Ball 4</item> <item>Hockey 4</item> <item>Swimming 4</item> <item>Shuttle Badminton 5</item> <item>Tennis 5</item> <item>Table Tennis 5</item> <item>Basket Ball 5</item> <item>Foot Ball 5</item> <item>Volley Ball 5</item> <item>Hockey 5</item> <item>Swimming 5</item> </string-array> </resources>
styles.xml
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <style name="myDialog" parent="@android:style/Theme.Holo.Light.Dialog"> <item name="android:windowTitleStyle">@style/myDialogTitle</item> </style> <style name="myDialogTitle" parent="@android:style/TextAppearance.DialogWindowTitle"> <item name="android:gravity">center_horizontal</item> </style> <style name="DialogWindowTitle"> <item name="android:maxLines">1</item> <item name="android:scrollHorizontally">true</item> <item name="android:textAppearance">@android:style/TextAppearance.DialogWindowTitle</item> </style> <style name="LetterSectionListItem" parent="@android:style/TextAppearance.Medium"> <item name="android:paddingLeft">5dp</item> <item name="android:textColor">#000000</item> <item name="android:background">#898989</item> </style> </resources>
attrs.xml<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="MultiSpinnerSearch"> <attr name="hintText" format="string"/> </declare-styleable> </resources>KeyPairBoolData.javapackage com.jainishprajapati.multiselectcheckboxwithsearchandwithoutsearch; public class KeyPairBoolData { long id; String name; boolean isSelected; Object object; public Object getObject() { return object; } public void setObject(Object object) { this.object = object; } /** * @return the id */public long getId() { return id; } /** * @param id the id to set */public void setId(long id) { this.id = id; } /** * @return the name */public String getName() { return name; } /** * @param name the name to set */public void setName(String name) { this.name = name; } /** * @return the isSelected */public boolean isSelected() { return isSelected; } /** * @param isSelected the isSelected to set */public void setSelected(boolean isSelected) { this.isSelected = isSelected; } }MultiSpinner.javapackage com.jainishprajapati.multiselectcheckboxwithsearchandwithoutsearch; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnMultiChoiceClickListener; import android.content.res.TypedArray; import android.support.v7.widget.AppCompatSpinner; import android.util.AttributeSet; import android.widget.ArrayAdapter; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; public class MultiSpinner extends AppCompatSpinner implements OnMultiChoiceClickListener, OnCancelListener { private List<String> items; private boolean[] selected; private String defaultText = "Select Items"; private String spinnerTitle = ""; private MultiSpinnerListener listener; public MultiSpinner(Context context) { super(context); } public MultiSpinner(Context arg0, AttributeSet arg1) { super(arg0, arg1); TypedArray a = arg0.obtainStyledAttributes(arg1, R.styleable.MultiSpinnerSearch); final int N = a.getIndexCount(); for (int i = 0; i < N; ++i) { int attr = a.getIndex(i); if (attr == R.styleable.MultiSpinnerSearch_hintText) { spinnerTitle = a.getString(attr); } } a.recycle(); } public MultiSpinner(Context arg0, AttributeSet arg1, int arg2) { super(arg0, arg1, arg2); } @Override public void onClick(DialogInterface dialog, int which, boolean isChecked) { selected[which] = isChecked; } @Override public void onCancel(DialogInterface dialog) { // refresh text on spinnerStringBuilder spinnerBuffer = new StringBuilder(); for (int i = 0; i < items.size(); i++) { if (selected[i]) { spinnerBuffer.append(items.get(i)); spinnerBuffer.append(", "); } } String spinnerText = spinnerBuffer.toString(); if (spinnerText.length() > 2) { spinnerText = spinnerText.substring(0, spinnerText.length() - 2); } else { spinnerText = defaultText; } ArrayAdapter<String> adapter = new ArrayAdapter<>(getContext(), R.layout.textview_for_spinner, new String[]{spinnerText}); setAdapter(adapter); if (selected.length > 0) { listener.onItemsSelected(selected); } } @Override public boolean performClick() { AlertDialog.Builder builder = new AlertDialog.Builder(getContext(), R.style.myDialog); builder.setTitle(spinnerTitle); builder.setMultiChoiceItems( items.toArray(new CharSequence[items.size()]), selected, this); builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Overridepublic void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }); builder.setOnCancelListener(this); builder.show(); return true; } /** * Sets items to this spinner. ** @param itemsA TreeMap where the keys are the values to display in the spinner *and the value the initial selected state of the key. *@param listener A MultiSpinnerListener. */public void setItems(LinkedHashMap<String, Boolean> items, MultiSpinnerListener listener) {this.items = new ArrayList<>(items.keySet()); this.listener = listener; List<Boolean> values = new ArrayList<>(items.values()); selected = new boolean[values.size()]; for (int i = 0; i < items.size(); i++) { selected[i] = values.get(i); } // all text on the spinnerArrayAdapter<String> adapter = new ArrayAdapter<>(getContext(), R.layout.textview_for_spinner, new String[]{defaultText}); setAdapter(adapter); // Set Spinner TextonCancel(null); } }
MultiSpinnerListener.javapackage com.jainishprajapati.multiselectcheckboxwithsearchandwithoutsearch; public interface MultiSpinnerListener { void onItemsSelected(boolean[] selected); }MultiSpinnerSearch.javapackage com.jainishprajapati.multiselectcheckboxwithsearchandwithoutsearch; import android.annotation.SuppressLint; import android.app.SearchManager; import android.content.Context; import android.content.DialogInterface; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.Typeface; import android.support.v4.content.ContextCompat; import android.support.v7.app.AlertDialog; import android.support.v7.widget.AppCompatSpinner; import android.text.Editable; import android.text.TextWatcher; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.BaseAdapter; import android.widget.CheckBox; import android.widget.EditText; import android.widget.Filter; import android.widget.Filterable; import android.widget.ListView; import android.widget.TextView; import java.util.ArrayList; import java.util.List; public class MultiSpinnerSearch extends AppCompatSpinner implements DialogInterface.OnCancelListener { private static final String TAG = MultiSpinnerSearch.class.getSimpleName(); private List<KeyPairBoolData> items; private String defaultText = ""; private String spinnerTitle = ""; private SpinnerListener listener; private int limit = -1; private int selected = 0; private LimitExceedListener limitListener; MyAdapter adapter; public static AlertDialog.Builder builder; public static AlertDialog ad; public MultiSpinnerSearch(Context context) { super(context); } public MultiSpinnerSearch(Context arg0, AttributeSet arg1) { super(arg0, arg1); TypedArray a = arg0.obtainStyledAttributes(arg1, R.styleable.MultiSpinnerSearch); for (int i = 0; i < a.getIndexCount(); ++i) { int attr = a.getIndex(i); if (attr == R.styleable.MultiSpinnerSearch_hintText) { spinnerTitle = a.getString(attr); defaultText = spinnerTitle; break; } } Log.i(TAG, "spinnerTitle: "+spinnerTitle); a.recycle(); } public MultiSpinnerSearch(Context arg0, AttributeSet arg1, int arg2) { super(arg0, arg1, arg2); } public void setLimit(int limit, LimitExceedListener listener) { this.limit = limit; this.limitListener = listener; } public List<KeyPairBoolData> getSelectedItems() { List<KeyPairBoolData> selectedItems = new ArrayList<>(); for(KeyPairBoolData item : items){ if(item.isSelected()){ selectedItems.add(item); } } return selectedItems; } public List<Long> getSelectedIds() { List<Long> selectedItemsIds = new ArrayList<>(); for(KeyPairBoolData item : items){ if(item.isSelected()){ selectedItemsIds.add(item.getId()); } } return selectedItemsIds; } @Override public void onCancel(DialogInterface dialog) { // refresh text on spinner StringBuilder spinnerBuffer = new StringBuilder(); for (int i = 0; i < items.size(); i++) { if (items.get(i).isSelected()) { spinnerBuffer.append(items.get(i).getName()); spinnerBuffer.append(", "); } } String spinnerText = spinnerBuffer.toString(); if (spinnerText.length() > 2) spinnerText = spinnerText.substring(0, spinnerText.length() - 2); else spinnerText = defaultText; ArrayAdapter<String> adapterSpinner = new ArrayAdapter<>(getContext(), R.layout.textview_for_spinner, new String[]{spinnerText}); setAdapter(adapterSpinner); if (adapter != null) adapter.notifyDataSetChanged(); listener.onItemsSelected(items); } @Override public boolean performClick() { // builder = new AlertDialog.Builder(getContext(), R.style.myDialog);builder = new AlertDialog.Builder(getContext()); builder.setTitle(spinnerTitle); final LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); final View view = inflater.inflate(R.layout.alert_dialog_listview_search, null); builder.setView(view); final ListView listView = (ListView) view.findViewById(R.id.alertSearchListView); listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); listView.setFastScrollEnabled(false); adapter = new MyAdapter(getContext(), items); listView.setAdapter(adapter); final TextView emptyText = (TextView) view.findViewById(R.id.empty); listView.setEmptyView(emptyText); final EditText editText = (EditText) view.findViewById(R.id.alertSearchEditText); editText.addTextChangedListener(new TextWatcher() { @Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) { adapter.getFilter().filter(s.toString()); } @Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Overridepublic void afterTextChanged(Editable s) { } }); builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Log.i(TAG, " ITEMS : " + items.size()); dialog.cancel(); } }); builder.setOnCancelListener(this); ad = builder.show(); return true; } public void setItems(List<KeyPairBoolData> items, int position, SpinnerListener listener) { this.items = items; this.listener = listener; StringBuilder spinnerBuffer = new StringBuilder(); for (int i = 0; i < items.size(); i++) { if (items.get(i).isSelected()) { spinnerBuffer.append(items.get(i).getName()); spinnerBuffer.append(", "); } } if (spinnerBuffer.length() > 2) defaultText = spinnerBuffer.toString().substring(0, spinnerBuffer.toString().length() - 2); ArrayAdapter<String> adapterSpinner = new ArrayAdapter<>(getContext(), R.layout.textview_for_spinner, new String[]{defaultText}); setAdapter(adapterSpinner); if (position != -1) { items.get(position).setSelected(true); //listener.onItemsSelected(items);onCancel(null); } } public interface LimitExceedListener { void onLimitListener(KeyPairBoolData data); } //Adapter Class public class MyAdapter extends BaseAdapter implements Filterable { List<KeyPairBoolData> arrayList; List<KeyPairBoolData> mOriginalValues;// Original ValuesLayoutInflater inflater; public MyAdapter(Context context, List<KeyPairBoolData> arrayList) { this.arrayList = arrayList; inflater = LayoutInflater.from(context); } @Override public int getCount() { return arrayList.size(); } @Override public Object getItem(int position) { return position; } @Override public long getItemId(int position) { return position; } private class ViewHolder { TextView textView; CheckBox checkBox; } @Overridepublic View getView(final int position, View convertView, ViewGroup parent) { Log.i(TAG, "getView() enter"); ViewHolder holder; if (convertView == null) { holder = new ViewHolder(); convertView = inflater.inflate(R.layout.item_listview_multiple, parent, false); holder.textView = (TextView) convertView.findViewById(R.id.alertTextView); holder.checkBox = (CheckBox) convertView.findViewById(R.id.alertCheckbox); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } final int backgroundColor = (position%2 == 0) ? R.color.list_even : R.color.list_odd; convertView.setBackgroundColor(ContextCompat.getColor(getContext(), backgroundColor)); final KeyPairBoolData data = arrayList.get(position); holder.textView.setText(data.getName()); holder.textView.setTypeface(null, Typeface.NORMAL); holder.checkBox.setChecked(data.isSelected()); convertView.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if(data.isSelected()) {// deselectselected--; } else if(selected == limit) {// select with limitif(limitListener != null) limitListener.onLimitListener(data); return; } else {// selected
selected++; } final ViewHolder temp = (ViewHolder) v.getTag(); temp.checkBox.setChecked(!temp.checkBox.isChecked()); data.setSelected(!data.isSelected()); Log.i(TAG, "On Click Selected Item : " + data.getName() + " : " + data.isSelected()); notifyDataSetChanged(); } }); if (data.isSelected()) { holder.textView.setTypeface(null, Typeface.BOLD); holder.textView.setTextColor(Color.WHITE); convertView.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.list_selected)); } holder.checkBox.setTag(holder); return convertView; } @SuppressLint("DefaultLocale") @Override public Filter getFilter() { return new Filter() { @SuppressWarnings("unchecked") @Overrideprotected void publishResults(CharSequence constraint, FilterResults results) { arrayList = (List<KeyPairBoolData>) results.values;// has the filtered values
notifyDataSetChanged();
// notifies the data with new filtered values} @Overrideprotected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults();// Holds the results of a filtering operation in values
List<KeyPairBoolData> FilteredArrList = new ArrayList<>(); if (mOriginalValues == null) { mOriginalValues = new ArrayList<>(arrayList);// saves the original data in mOriginalValues
} /********** If constraint(CharSequence that is received) is null returns the mOriginalValues(Original) values
* else does the Filtering and returns FilteredArrList(Filtered)
* ********/if (constraint == null || constraint.length() == 0) { // set the Original result to returnresults.count = mOriginalValues.size(); results.values = mOriginalValues; } else { constraint = constraint.toString().toLowerCase(); for (int i = 0; i < mOriginalValues.size(); i++) { Log.i(TAG, "Filter : " + mOriginalValues.get(i).getName() + " -> " + mOriginalValues.get(i).isSelected()); String data = mOriginalValues.get(i).getName(); if (data.toLowerCase().contains(constraint.toString())) { FilteredArrList.add(mOriginalValues.get(i)); } } // set the Filtered result to returnresults.count = FilteredArrList.size(); results.values = FilteredArrList; } return results; } }; } } }SingleSpinner.javapackage com.jainishprajapati.multiselectcheckboxwithsearchandwithoutsearch; import android.support.v7.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.Typeface; import android.support.v4.content.ContextCompat; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.BaseAdapter; import android.widget.EditText; import android.widget.ListView; import android.widget.Spinner; import android.widget.TextView; import java.util.ArrayList; import java.util.List; public class SingleSpinner extends android.support.v7.widget.AppCompatSpinner implements OnCancelListener { private static final String TAG = SingleSpinner.class.getSimpleName(); private List<KeyPairBoolData> items; private String defaultText = ""; private String spinnerTitle = ""; private SpinnerListener listener; MyAdapter adapter; public static AlertDialog.Builder builder; public static AlertDialog ad; public SingleSpinner(Context context) { super(context); } public SingleSpinner(Context arg0, AttributeSet arg1) { super(arg0, arg1); TypedArray a = arg0.obtainStyledAttributes(arg1, R.styleable.MultiSpinnerSearch); final int N = a.getIndexCount(); for (int i = 0; i < N; ++i) { int attr = a.getIndex(i); if (attr == R.styleable.MultiSpinnerSearch_hintText) { spinnerTitle = a.getString(attr); defaultText = spinnerTitle; break; } } Log.i(TAG, "spinnerTitle: "+spinnerTitle); a.recycle(); } public SingleSpinner(Context arg0, AttributeSet arg1, int arg2) { super(arg0, arg1, arg2); } public List<KeyPairBoolData> getSelectedItems() { List<KeyPairBoolData> selectedItems = new ArrayList<>(); for(KeyPairBoolData item : items){ if(item.isSelected()){ selectedItems.add(item); } } return selectedItems; } public List<Long> getSelectedIds() { List<Long> selectedItemsIds = new ArrayList<>(); for(KeyPairBoolData item : items){ if(item.isSelected()){ selectedItemsIds.add(item.getId()); } } return selectedItemsIds; } @Override public void onCancel(DialogInterface dialog) { // refresh text on spinner String spinnerText = null; for (int i = 0; i < items.size(); i++) { if (items.get(i).isSelected()) { spinnerText = items.get(i).getName(); break; } } if (spinnerText==null){ spinnerText = defaultText; } ArrayAdapter<String> adapterSpinner = new ArrayAdapter<>(getContext(), R.layout.textview_for_spinner, new String[] { spinnerText }); setAdapter(adapterSpinner); if(adapter != null) adapter.notifyDataSetChanged(); listener.onItemsSelected(items); } @Override public boolean performClick() { // builder = new AlertDialog.Builder(getContext(), R.style.myDialog);builder = new AlertDialog.Builder(getContext()); builder.setTitle(spinnerTitle); LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE ); View view = inflater.inflate(R.layout.alert_dialog_listview_search, null); builder.setView(view); final ListView listView = (ListView) view.findViewById(R.id.alertSearchListView); listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); listView.setFastScrollEnabled(false); adapter = new MyAdapter(getContext(), items); listView.setAdapter(adapter); final TextView emptyText = (TextView) view.findViewById(R.id.empty); listView.setEmptyView(emptyText); EditText editText = (EditText) view.findViewById(R.id.alertSearchEditText); editText.setVisibility(GONE); builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Overridepublic void onClick(DialogInterface dialog, int which) { Log.i(TAG, " ITEMS : " + items.size() ); dialog.cancel(); } }); builder.setOnCancelListener(this); ad = builder.show(); return true; } public void setItems(List<KeyPairBoolData> items, int position, SpinnerListener listener) { this.items = items; this.listener = listener; for (KeyPairBoolData item : items){ if(item.isSelected()){ defaultText = item.getName(); break; } } ArrayAdapter<String> adapterSpinner = new ArrayAdapter<>(getContext(), R.layout.textview_for_spinner, new String[] { defaultText }); setAdapter(adapterSpinner); if(position != -1) { items.get(position).setSelected(true); //listener.onItemsSelected(items);onCancel(null); } } //Adapter Classpublic class MyAdapter extends BaseAdapter{ List<KeyPairBoolData> arrayList; LayoutInflater inflater; public MyAdapter(Context context, List<KeyPairBoolData> arrayList) { this.arrayList = arrayList; inflater = LayoutInflater.from(context); } @Override public int getCount() { return arrayList.size(); } @Override public Object getItem(int position) { return position; } @Override public long getItemId(int position) { return position; } private class ViewHolder { TextView textView; } @Override public View getView(final int position, View convertView, ViewGroup parent) { Log.i(TAG, "getView() enter"); ViewHolder holder = new ViewHolder(); convertView = inflater.inflate(R.layout.item_listview_single, parent, false); holder.textView = (TextView) convertView.findViewById(R.id.alertTextView); convertView.setTag(holder); if(position%2==0){ convertView.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.list_even)); }else{ convertView.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.list_odd)); } final KeyPairBoolData data = arrayList.get(position); holder.textView.setText(data.getName()); holder.textView.setTypeface(null, Typeface.NORMAL); convertView.setOnClickListener(new OnClickListener() { public void onClick(View v) { int len = arrayList.size(); for (int i = 0; i < len; i++) { arrayList.get(i).setSelected(false); if (i == position) { arrayList.get(i).setSelected(true); Log.i(TAG, "On Click Selected Item : " + arrayList.get(i).getName() + " : " + arrayList.get(i).isSelected()); } } ad.dismiss(); SingleSpinner.this.onCancel(ad); } }); if(data.isSelected()){ holder.textView.setTypeface(null, Typeface.BOLD); holder.textView.setTextColor(Color.WHITE); convertView.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.list_selected)); } return convertView; } } }SingleSpinnerSearch.javapackage com.jainishprajapati.multiselectcheckboxwithsearchandwithoutsearch; import android.annotation.SuppressLint; import android.support.v7.app.AlertDialog; //import android.app.AlertDialog;import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.Typeface; import android.support.v4.content.ContextCompat; import android.text.Editable; import android.text.TextWatcher; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.BaseAdapter; import android.widget.EditText; import android.widget.Filter; import android.widget.Filterable; import android.widget.ListView; import android.widget.TextView; import java.util.ArrayList; import java.util.List; public class SingleSpinnerSearch extends android.support.v7.widget.AppCompatSpinner implements OnCancelListener { private static final String TAG = SingleSpinnerSearch.class.getSimpleName(); private List<KeyPairBoolData> items; private String defaultText = ""; private String spinnerTitle = ""; private SpinnerListener listener; MyAdapter adapter; public static AlertDialog.Builder builder; public static AlertDialog ad; public SingleSpinnerSearch(Context context) { super(context); } public SingleSpinnerSearch(Context arg0, AttributeSet arg1) { super(arg0, arg1); TypedArray a = arg0.obtainStyledAttributes(arg1, R.styleable.MultiSpinnerSearch); final int N = a.getIndexCount(); for (int i = 0; i < N; ++i) { int attr = a.getIndex(i); if (attr == R.styleable.MultiSpinnerSearch_hintText) { spinnerTitle = a.getString(attr); defaultText = spinnerTitle; break; } } Log.i(TAG, "spinnerTitle: "+spinnerTitle); a.recycle(); } public SingleSpinnerSearch(Context arg0, AttributeSet arg1, int arg2) { super(arg0, arg1, arg2); } public List<KeyPairBoolData> getSelectedItems() { List<KeyPairBoolData> selectedItems = new ArrayList<>(); for(KeyPairBoolData item : items){ if(item.isSelected()){ selectedItems.add(item); } } return selectedItems; } public List<Long> getSelectedIds() { List<Long> selectedItemsIds = new ArrayList<>(); for(KeyPairBoolData item : items){ if(item.isSelected()){ selectedItemsIds.add(item.getId()); } } return selectedItemsIds; } @Override public void onCancel(DialogInterface dialog) { // refresh text on spinner String spinnerText = null; for (int i = 0; i < items.size(); i++) { if (items.get(i).isSelected()) { spinnerText = items.get(i).getName(); break; } } if (spinnerText==null){ spinnerText = defaultText; } ArrayAdapter<String> adapterSpinner = new ArrayAdapter<>(getContext(), R.layout.textview_for_spinner, new String[] { spinnerText }); setAdapter(adapterSpinner); if(adapter != null) adapter.notifyDataSetChanged(); listener.onItemsSelected(items); } @Override public boolean performClick() { // builder = new AlertDialog.Builder(getContext(), R.style.myDialog);builder = new AlertDialog.Builder(getContext()); builder.setTitle(spinnerTitle); final LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE ); final View view = inflater.inflate(R.layout.alert_dialog_listview_search, null); builder.setView(view); final ListView listView = (ListView) view.findViewById(R.id.alertSearchListView); listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); listView.setFastScrollEnabled(false); adapter = new MyAdapter(getContext(), items); listView.setAdapter(adapter); for(int i =0;i<items.size();i++){ if(items.get(i).isSelected()){ listView.setSelection(i); break; } } final TextView emptyText = (TextView) view.findViewById(R.id.empty); listView.setEmptyView(emptyText); EditText editText = (EditText) view.findViewById(R.id.alertSearchEditText); editText.addTextChangedListener(new TextWatcher() { @Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) { adapter.getFilter().filter(s.toString()); } @Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Overridepublic void afterTextChanged(Editable s) { } }); builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Log.i(TAG, " ITEMS : " + items.size() ); dialog.cancel(); } }); builder.setOnCancelListener(this); ad = builder.show(); return true; } public void setItems(List<KeyPairBoolData> items, int position, SpinnerListener listener) { this.items = items; this.listener = listener; for (KeyPairBoolData item : items){ if(item.isSelected()){ defaultText = item.getName(); break; } } ArrayAdapter<String> adapterSpinner = new ArrayAdapter<>(getContext(), R.layout.textview_for_spinner, new String[] { defaultText }); setAdapter(adapterSpinner); if(position != -1) { items.get(position).setSelected(true); //listener.onItemsSelected(items);onCancel(null); } } //Adapter Classpublic class MyAdapter extends BaseAdapter implements Filterable { List<KeyPairBoolData> arrayList; List<KeyPairBoolData> mOriginalValues;// Original Values
LayoutInflater inflater; public MyAdapter(Context context, List<KeyPairBoolData> arrayList) { this.arrayList = arrayList; inflater = LayoutInflater.from(context); } @Override public int getCount() { return arrayList.size(); } @Override public Object getItem(int position) { return position; } @Override public long getItemId(int position) { return position; } private class ViewHolder { TextView textView; } @Override public View getView(final int position, View convertView, ViewGroup parent) { Log.i(TAG, "getView() enter"); ViewHolder holder = new ViewHolder(); convertView = inflater.inflate(R.layout.item_listview_single, parent, false); holder.textView = (TextView) convertView.findViewById(R.id.alertTextView); convertView.setTag(holder); if(position%2==0){ convertView.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.list_even)); }else{ convertView.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.list_odd)); } final KeyPairBoolData data = arrayList.get(position); holder.textView.setText(data.getName()); holder.textView.setTypeface(null, Typeface.NORMAL); convertView.setOnClickListener(new OnClickListener() { public void onClick(View v) { int len = arrayList.size(); for (int i = 0; i < len; i++) { arrayList.get(i).setSelected(false); if (i == position) { arrayList.get(i).setSelected(true); Log.i(TAG, "On Click Selected Item : " + arrayList.get(i).getName() + " : " + arrayList.get(i).isSelected()); } } ad.dismiss(); SingleSpinnerSearch.this.onCancel(ad); } }); if(data.isSelected()){ holder.textView.setTypeface(null, Typeface.BOLD); holder.textView.setTextColor(Color.WHITE); convertView.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.list_selected)); } return convertView; } @SuppressLint("DefaultLocale") @Override public Filter getFilter() { return new Filter() { @SuppressWarnings("unchecked") @Overrideprotected void publishResults(CharSequence constraint,FilterResults results) { arrayList = (List<KeyPairBoolData>) results.values;// has the filtered values
notifyDataSetChanged(); // notifies the data with new filtered values } @Overrideprotected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults();// Holds the results of a filtering operation in values
List<KeyPairBoolData> FilteredArrList = new ArrayList<>(); if (mOriginalValues == null) { mOriginalValues = new ArrayList<>(arrayList);// saves the original data in mOriginalValues } /*********
* If constraint(CharSequence that is received) is null returns the mOriginalValues(Original) values* else does the Filtering and returns FilteredArrList(Filtered)
* ********/if (constraint == null || constraint.length() == 0) { // set the Original result to returnresults.count = mOriginalValues.size(); results.values = mOriginalValues; } else { constraint = constraint.toString().toLowerCase(); for (int i = 0; i < mOriginalValues.size(); i++) { Log.i(TAG, "Filter : " + mOriginalValues.get(i).getName() + " -> " + mOriginalValues.get(i).isSelected()); String data = mOriginalValues.get(i).getName(); if (data.toLowerCase().contains(constraint.toString())) { FilteredArrList.add(mOriginalValues.get(i)); } } // set the Filtered result to returnresults.count = FilteredArrList.size(); results.values = FilteredArrList; } return results; } }; } } }SpinnerListener.javapackage com.jainishprajapati.multiselectcheckboxwithsearchandwithoutsearch; import java.util.List; public interface SpinnerListener { void onItemsSelected(List<KeyPairBoolData> items); }activity_main.xml<LinearLayout 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="match_parent" android:layout_marginBottom="10dp" android:orientation="vertical"> <com.jainishprajapati.multiselectcheckboxwithsearchandwithoutsearch.MultiSpinnerSearch android:id="@+id/searchMultiSpinnerUnlimited" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_margin="10dp" app:hintText="Multi Selection With Filter Without Limit" /> <com.jainishprajapati.multiselectcheckboxwithsearchandwithoutsearch.MultiSpinnerSearch android:id="@+id/searchMultiSpinnerLimit" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_margin="10dp" app:hintText="Multi Selection With Filter And Limit" /> <com.jainishprajapati.multiselectcheckboxwithsearchandwithoutsearch.SingleSpinnerSearch android:id="@+id/searchSingleSpinner" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_margin="10dp" app:hintText="Single Selection With Filter" /> <com.jainishprajapati.multiselectcheckboxwithsearchandwithoutsearch.SingleSpinner android:id="@+id/singleSpinner" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_margin="10dp" app:hintText="Single Selection" /> </LinearLayout>MainActivity.javapackage com.jainishprajapati.multiselectcheckboxwithsearchandwithoutsearch; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.widget.Toast; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /** * Getting array of String to Bind in Spinner */final List<String> list = Arrays.asList(getResources().getStringArray(R.array.sports_array)); final List<KeyPairBoolData> listArray0 = new ArrayList<>(); for (int i = 0; i < list.size(); i++) { KeyPairBoolData h = new KeyPairBoolData(); h.setId(i + 1); h.setName(list.get(i)); h.setSelected(false); listArray0.add(h); } final List<KeyPairBoolData> listArray1 = new ArrayList<>(); for (int i = 0; i < list.size(); i++) { KeyPairBoolData h = new KeyPairBoolData(); h.setId(i + 1); h.setName(list.get(i)); h.setSelected(false); listArray1.add(h); } final List<KeyPairBoolData> listArray2 = new ArrayList<>(); for (int i = 0; i < list.size(); i++) { KeyPairBoolData h = new KeyPairBoolData(); h.setId(i + 1); h.setName(list.get(i)); h.setSelected(false); listArray2.add(h); } final List<KeyPairBoolData> listArray3 = new ArrayList<>(); for (int i = 0; i < list.size(); i++) { KeyPairBoolData h = new KeyPairBoolData(); h.setId(i + 1); h.setName(list.get(i)); h.setSelected(false); listArray3.add(h); }MultiSpinnerSearch searchMultiSpinnerUnlimited = (MultiSpinnerSearch) findViewById(R.id.searchMultiSpinnerUnlimited); MultiSpinnerSearch searchMultiSpinnerLimit = (MultiSpinnerSearch) findViewById(R.id.searchMultiSpinnerLimit); SingleSpinnerSearch searchSingleSpinner = (SingleSpinnerSearch) findViewById(R.id.searchSingleSpinner); SingleSpinner singleSpinner = (SingleSpinner) findViewById(R.id.singleSpinner); searchMultiSpinnerUnlimited.setItems(listArray0, -1, new SpinnerListener() { @Override public void onItemsSelected(List<KeyPairBoolData> items) { for (int i = 0; i < items.size(); i++) { if (items.get(i).isSelected()) { Log.i(TAG, i + " : " + items.get(i).getName() + " : " + items.get(i).isSelected()); } } } }); /*** * -1 is no by default selection * 0 to length will select corresponding values */ searchMultiSpinnerLimit.setItems(listArray1, -1, new SpinnerListener() { @Override public void onItemsSelected(List<KeyPairBoolData> items) { for (int i = 0; i < items.size(); i++) { if (items.get(i).isSelected()) { Log.i(TAG, i + " : " + items.get(i).getName() + " : " + items.get(i).isSelected()); } } } }); searchMultiSpinnerLimit.setLimit(2, new MultiSpinnerSearch.LimitExceedListener() { @Override public void onLimitListener(KeyPairBoolData data) { Toast.makeText(getApplicationContext(), "Limit exceed ", Toast.LENGTH_LONG).show(); } }); searchSingleSpinner.setItems(listArray2, -1, new SpinnerListener() { @Override public void onItemsSelected(List<KeyPairBoolData> items) { for (int i = 0; i < items.size(); i++) { if (items.get(i).isSelected()) { Log.i(TAG, i + " : " + items.get(i).getName() + " : " + items.get(i).isSelected()); } } } }); singleSpinner.setItems(listArray3, -1, new SpinnerListener() { @Override public void onItemsSelected(List<KeyPairBoolData> items) { for (int i = 0; i < items.size(); i++) { if (items.get(i).isSelected()) { Log.i(TAG, i + " : " + items.get(i).getName() + " : " + items.get(i).isSelected()); } } } }); } }