Kotlin Android Search Filter Spinner Examples

Search

In this piece we want to look at how to search or filter a spinner. We specifically will look at some libraries that easen this for us so that we don’t have to roll it out on our own.

Example 1: Kotlin Android Searchable Spinner

This spinner allows you to search filter items contained in a spinner by utilizing a dialog with a searchview. Then the searched item will be rendered on the spinner.

Here is a demo of the what is created:

Kotlin Android searchable spinner

Step 1: Add Dependency

First add jitpack in your root build.gradle at the end of repositories:

    allprojects {
        repositories {
        ...
        maven { url "https://jitpack.io" }
        }
    }

Then add the dependency in the module build.gradle:

    dependencies {
        implementation 'com.github.DonMat:searchablespinner:v1.0.1'
    }

Step 2: Add to Layout

Now add the spinner to your xml layout:

    <pl.utkala.searchablespinner.SearchableSpinner
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"

            app:closeText="Zamknij"
            app:dialogTitle="Wybierz z listy"/>

Here is the full layout:

activity_main.xml

Place a spinner below a textview inside a LinearLayout as follows:

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

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:layout_gravity="center_horizontal"
        android:text="@string/app_name" />

    <pl.utkala.searchablespinner.SearchableSpinner
        android:id="@+id/searchableSpinner"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:layout_gravity="center_horizontal"

        app:closeText="@string/search_dialog_close"
        app:dialogTitle="@string/search_dialog_title" />

</LinearLayout>

Step 3: Write Kotlin Code

Create your main activity by extending the AppCompatActivity:

class MainActivity : AppCompatActivity()
    //...

Now Override the activity’s onCreate() method:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

Create a list of users:

        val users = listOf("Veniam penatibus", "reprehenderit", "fusce", "Ullamcorper lacinia", "Etiam dis")

Bind data to the SearchabeSpinner using an ArrayAdapter:

        searchableSpinner.adapter = ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, users)

Here’s the full code:

MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val users = listOf("Veniam penatibus", "reprehenderit", "fusce", "Ullamcorper lacinia", "Etiam dis")
        searchableSpinner.adapter = ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, users)
    }
}

Run

Finally run the project in android studio. Scroll above to see the demo screenshot.

Reference

Download the code below:

Number Link
1. Download code
2. Follow code author

Example 2: Android SearchableSpinner

Android SearchableSpinner Library Tutorial and Example.

What about if you have a spinner with plenty of items and you want to provide users with ability to search or filter those items.

What do you do then?

Well you have a solution is SearchableSpinner by @michaelprimez in SearcableSpinner.

Demo

Here’s SearchableSpinner in action. The source for this is found in the example below.

Android Searchable Spinner

Installation

You can fetch SearchableSpinner via gradle. All you need do is add the following in your app level build.gradle and sync your project:

implementation 'gr.escsoft.michaelprimez.searchablespinner:SearchableSpinner:1.0.9'

How to Use

To use SearchableSpinner first go over to your layout where you want to add it and add the following:

<gr.escsoft.michaelprimez.searchablespinner.SearchableSpinner
        android_id="@+id/SearchableSpinner"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_marginTop="24dp"
        android_layout_marginLeft="24dp"
        android_layout_marginRight="24dp"
        android_layout_marginStart="24dp"
        android_layout_marginEnd="24dp"
        android_gravity="center_horizontal"
        app_StartSearchTintColor="@android:color/white"
        app_DoneSearchTintColor="@android:color/holo_purple"
        app_RevealViewBackgroundColor="@android:color/holo_purple"
        app_SearchViewBackgroundColor="@android:color/secondary_text_dark"
        app_ShowBorders="false"
        app_RevealEmptyText="Touch to select"
        app_SpinnerExpandHeight="300dp"/>

For java usage continue over to full example section.

Full Searchable Spinner Example

Gradle Scripts

Here are our gradle scripts in our build.gradle file(s).

(a). build.gradle(app)

Here’s our app level build.gradle file. We have the dependencies DSL where we add our dependencies.

This file is called app level build.gradle since it’s located in the app folder of the project.

If you are using Android Studio version 3 and above use implementation keyword while if you are using a version less than 3 then still use the compile keyword.

Once you’ve modified this build.gradle file you have to sync your project. Android Studio will indeed prompt you to do so.

implementation 'gr.escsoft.michaelprimez.searchablespinner:SearchableSpinner:1.0.9'

Resources.

Android platform provides a powerful and flexible way of adding static content as a resource.

These static content will also be packaged into the APK file. The static content will be stored either as a resource or as an asset.

Resources belong to a given type. These types can be:

  1. Drawable.
  2. Layout.
  3. Value.

Let’s start by looking at the layout resources

(a). activity_main.xml

This layout will get inflated into the main activity’s user interface. This will happen via the Activity’s setContentView() method which will require us to pass it the layout.

We will do so inside the onCreate() method of Activity.

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout

    android_layout_width="match_parent"
    android_layout_height="match_parent"
    tools_context="gr.escsoft.michaelprimez.searchablespinnerexamples.MainActivity">

    <android.support.design.widget.AppBarLayout
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android_id="@+id/toolbar"
            android_layout_width="match_parent"
            android_layout_height="?attr/actionBarSize"
            android_background="?attr/colorPrimary"
            app_popupTheme="@style/AppTheme.PopupOverlay"/>

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main"/>

</android.support.design.widget.CoordinatorLayout>
(b). content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout

    android_id="@+id/content_main"
    android_layout_width="match_parent"
    android_layout_height="match_parent"
    android_orientation="vertical"
    app_layout_behavior="@string/appbar_scrolling_view_behavior"
    tools_context="gr.escsoft.michaelprimez.searchablespinnerexamples.MainActivity"
    tools_showIn="@layout/activity_main">

    <gr.escsoft.michaelprimez.searchablespinner.SearchableSpinner
        android_id="@+id/SearchableSpinner"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_marginTop="24dp"
        android_layout_marginLeft="24dp"
        android_layout_marginRight="24dp"
        android_layout_marginStart="24dp"
        android_layout_marginEnd="24dp"
        android_gravity="center_horizontal"
        app_ShowBorders="true"
        app_BordersSize="1dp"
        app_RevealEmptyText="Touch to select"
        app_BoarderColor="@color/colorPrimary"
        app_SpinnerExpandHeight="250dp"/>

    <gr.escsoft.michaelprimez.searchablespinner.SearchableSpinner
        android_id="@+id/SearchableSpinner1"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_marginTop="24dp"
        android_layout_marginLeft="24dp"
        android_layout_marginRight="24dp"
        android_layout_marginStart="24dp"
        android_layout_marginEnd="24dp"
        android_gravity="center_horizontal"
        app_StartSearchTintColor="@android:color/white"
        app_DoneSearchTintColor="@android:color/white"
        app_RevealViewBackgroundColor="@android:color/holo_blue_light"
        app_SearchViewBackgroundColor="@android:color/holo_blue_light"
        app_ShowBorders="true"
        app_BordersSize="1dp"
        app_BoarderColor="@android:color/holo_blue_light"
        app_SpinnerExpandHeight="0dp"/>

    <gr.escsoft.michaelprimez.searchablespinner.SearchableSpinner
        android_id="@+id/SearchableSpinner2"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_marginTop="24dp"
        android_layout_marginLeft="24dp"
        android_layout_marginRight="24dp"
        android_layout_marginStart="24dp"
        android_layout_marginEnd="24dp"
        android_gravity="center_horizontal"
        app_StartSearchTintColor="@android:color/white"
        app_DoneSearchTintColor="@android:color/holo_purple"
        app_RevealViewBackgroundColor="@android:color/holo_purple"
        app_SearchViewBackgroundColor="@android:color/secondary_text_dark"
        app_ShowBorders="true"
        app_RevealEmptyText="Touch to select"
        app_SpinnerExpandHeight="300dp"
        app_ItemsDivider="@color/gray_400"
        app_DividerHeight="0.5dp"/>

    <gr.escsoft.michaelprimez.searchablespinner.SearchableSpinner
        android_id="@+id/SearchableSpinner3"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_marginTop="24dp"
        android_layout_marginLeft="24dp"
        android_layout_marginRight="24dp"
        android_layout_marginStart="24dp"
        android_layout_marginEnd="24dp"
        android_gravity="center_horizontal"
        app_StartSearchTintColor="@android:color/white"
        app_DoneSearchTintColor="@android:color/holo_purple"
        app_RevealViewBackgroundColor="@android:color/holo_purple"
        app_SearchViewBackgroundColor="@android:color/secondary_text_dark"
        app_ShowBorders="false"
        app_BordersSize="4dp"
        app_RevealEmptyText="Touch to select"
        app_SpinnerExpandHeight="300dp"
        app_ItemsDivider="@color/gray_400"
        app_DividerHeight="0.5dp"/>

</LinearLayout>
(c). view_list_item.xml
?xml version="1.0" encoding="utf-8"?>
<LinearLayout

              android_layout_width="wrap_content"
              android_layout_height="wrap_content"
              android_paddingTop="4dp"
              android_paddingBottom="4dp"
              android_paddingRight="4dp"
              android_paddingLeft="8dp"
              android_orientation="horizontal"
              app_layout_collapseMode="parallax"
              app_layout_collapseParallaxMultiplier="0.5">

    <ImageView
        android_id="@+id/ImgVw_Letters"
        android_layout_width="32dp"
        android_layout_height="32dp"/>

    <TextView
        android_id="@+id/TxtVw_DisplayName"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_marginLeft="8dp"
        android_layout_gravity="center_vertical"/>

</LinearLayout>
(d). view_no_selection_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout

              android_layout_width="wrap_content"
              android_layout_height="wrap_content"
              android_paddingTop="8dp"
              android_paddingBottom="8dp"
              android_paddingRight="4dp"
              android_paddingLeft="8dp"
              android_orientation="horizontal"
              app_layout_collapseMode="parallax"
              app_layout_collapseParallaxMultiplier="0.5">

    <TextView
        android_id="@+id/TxtVw_NoSelection"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_marginLeft="8dp"
        android_layout_gravity="center_vertical"
        android_text="@string/no_selection"/>
</LinearLayout>

Java Code.

Android apps can be mainly written in Java or Kotlin. These days however there are many frameworks like Flutter also which use languages like Dart.

In this class we are using Java programming language.

We will have these classes in our project.

(a). MainActivity.java

This is our launcher activity as the name suggests. This means it will be the main entry point to our app in that when the user clicks the icon for our app, this activity will get rendered first.

We override a method called onCreate(). Here we will start by inflating our main layout via the setContentView() method.

Our main activity is actually an activity since it’s deriving from the AppCompatActivity.

package gr.escsoft.michaelprimez.searchablespinnerexamples;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MotionEvent;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

import java.util.ArrayList;

import gr.escsoft.michaelprimez.searchablespinner.SearchableSpinner;
import gr.escsoft.michaelprimez.searchablespinner.interfaces.IStatusListener;
import gr.escsoft.michaelprimez.searchablespinner.interfaces.OnItemSelectedListener;

public class MainActivity extends AppCompatActivity {

    private SearchableSpinner mSearchableSpinner;
    private SearchableSpinner mSearchableSpinner1;
    private SearchableSpinner mSearchableSpinner2;
    private SearchableSpinner mSearchableSpinner3;
    private SimpleListAdapter mSimpleListAdapter;
    private SimpleArrayListAdapter mSimpleArrayListAdapter;
    private final ArrayList<String> mStrings = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        initListValues();
        mSimpleListAdapter = new SimpleListAdapter(this, mStrings);
        mSimpleArrayListAdapter = new SimpleArrayListAdapter(this, mStrings);

        mSearchableSpinner = (SearchableSpinner) findViewById(R.id.SearchableSpinner);
        mSearchableSpinner.setAdapter(mSimpleArrayListAdapter);
        mSearchableSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
        mSearchableSpinner.setStatusListener(new IStatusListener() {
            @Override
            public void spinnerIsOpening() {
                mSearchableSpinner1.hideEdit();
                mSearchableSpinner2.hideEdit();
            }

            @Override
            public void spinnerIsClosing() {

            }
        });

        mSearchableSpinner1 = (SearchableSpinner) findViewById(R.id.SearchableSpinner1);
        mSearchableSpinner1.setAdapter(mSimpleListAdapter);
        mSearchableSpinner1.setOnItemSelectedListener(mOnItemSelectedListener);
        mSearchableSpinner1.setStatusListener(new IStatusListener() {
            @Override
            public void spinnerIsOpening() {
                mSearchableSpinner.hideEdit();
                mSearchableSpinner2.hideEdit();
            }

            @Override
            public void spinnerIsClosing() {

            }
        });

        mSearchableSpinner2 = (SearchableSpinner) findViewById(R.id.SearchableSpinner2);
        mSearchableSpinner2.setAdapter(mSimpleListAdapter);
        mSearchableSpinner2.setOnItemSelectedListener(mOnItemSelectedListener);
        mSearchableSpinner2.setStatusListener(new IStatusListener() {
            @Override
            public void spinnerIsOpening() {
                mSearchableSpinner.hideEdit();
                mSearchableSpinner1.hideEdit();
            }

            @Override
            public void spinnerIsClosing() {

            }
        });

        mSearchableSpinner3 = (SearchableSpinner) findViewById(R.id.SearchableSpinner3);
        mSearchableSpinner3.setAdapter(mSimpleListAdapter);
        mSearchableSpinner3.setOnItemSelectedListener(mOnItemSelectedListener);
        mSearchableSpinner3.setStatusListener(new IStatusListener() {
            @Override
            public void spinnerIsOpening() {
                mSearchableSpinner.hideEdit();
                mSearchableSpinner3.hideEdit();
            }

            @Override
            public void spinnerIsClosing() {

            }
        });
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!mSearchableSpinner.isInsideSearchEditText(event)) {
            mSearchableSpinner.hideEdit();
        }
        if (!mSearchableSpinner1.isInsideSearchEditText(event)) {
            mSearchableSpinner1.hideEdit();
        }
        if (!mSearchableSpinner2.isInsideSearchEditText(event)) {
            mSearchableSpinner2.hideEdit();
        }
        return super.onTouchEvent(event);
    }

    private OnItemSelectedListener mOnItemSelectedListener = new OnItemSelectedListener() {
        @Override
        public void onItemSelected(View view, int position, long id) {
            Toast.makeText(MainActivity.this, "Item on position " + position + " : " + mSimpleListAdapter.getItem(position) + " Selected", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onNothingSelected() {
            Toast.makeText(MainActivity.this, "Nothing Selected", Toast.LENGTH_SHORT).show();
        }
    };

    private void initListValues() {
        mStrings.add("Brigida Kurz");
        mStrings.add("Tracy Mckim");
        mStrings.add("Iesha Davids");
        mStrings.add("Ozella Provenza");
        mStrings.add("Florentina Carriere");
        mStrings.add("Geri Eiler");
        mStrings.add("Tammara Belgrave");
        mStrings.add("Ashton Ridinger");
        mStrings.add("Jodee Dawkins");
        mStrings.add("Florine Cruzan");
        mStrings.add("Latia Stead");
        mStrings.add("Kai Urbain");
        mStrings.add("Liza Chi");
        mStrings.add("Clayton Laprade");
        mStrings.add("Wilfredo Mooney");
        mStrings.add("Roseline Cain");
        mStrings.add("Chadwick Gauna");
        mStrings.add("Carmela Bourn");
        mStrings.add("Valeri Dedios");
        mStrings.add("Calista Mcneese");
        mStrings.add("Willard Cuccia");
        mStrings.add("Ngan Blakey");
        mStrings.add("Reina Medlen");
        mStrings.add("Fabian Steenbergen");
        mStrings.add("Edmond Pine");
        mStrings.add("Teri Quesada");
        mStrings.add("Vernetta Fulgham");
        mStrings.add("Winnifred Kiefer");
        mStrings.add("Chiquita Lichty");
        mStrings.add("Elna Stiltner");
        mStrings.add("Carly Landon");
        mStrings.add("Hans Morford");
        mStrings.add("Shawanna Kapoor");
        mStrings.add("Thomasina Naron");
        mStrings.add("Melba Massi");
        mStrings.add("Sal Mangano");
        mStrings.add("Mika Weitzel");
        mStrings.add("Phylis France");
        mStrings.add("Illa Winzer");
        mStrings.add("Kristofer Boyden");
        mStrings.add("Idalia Cryan");
        mStrings.add("Jenni Sousa");
        mStrings.add("Eda Forkey");
        mStrings.add("Birgit Rispoli");
        mStrings.add("Janiece Mcguffey");
        mStrings.add("Barton Busick");
        mStrings.add("Gerald Westerman");
        mStrings.add("Shalanda Baran");
        mStrings.add("Margherita Pazos");
        mStrings.add("Yuk Fitts");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_reset) {
            mSearchableSpinner.setSelectedItem(0);
            mSearchableSpinner1.setSelectedItem(0);
            mSearchableSpinner2.setSelectedItem(0);
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}
(b). SearchableSpinnerApp.java
import android.app.Application;

import com.facebook.stetho.Stetho;

public class SearchableSpinnerApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Stetho.initializeWithDefaults(this);
    }
}
(c). SimpleArrayListAdapter.java

The SimpleArrayListAdapter class.

Here’s the full code.

package gr.escsoft.michaelprimez.searchablespinnerexamples;

import android.content.Context;
import android.graphics.Color;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;

import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;

import java.util.ArrayList;

import gr.escsoft.michaelprimez.revealedittext.tools.UITools;
import gr.escsoft.michaelprimez.searchablespinner.interfaces.ISpinnerSelectedView;

public class SimpleArrayListAdapter extends ArrayAdapter<String> implements Filterable, ISpinnerSelectedView {

    private Context mContext;
    private ArrayList<String> mBackupStrings;
    private ArrayList<String> mStrings;
    private StringFilter mStringFilter = new StringFilter();

    public SimpleArrayListAdapter(Context context, ArrayList<String> strings) {
        super(context, R.layout.view_list_item);
        mContext = context;
        mStrings = strings;
        mBackupStrings = strings;
    }

    @Override
    public int getCount() {
        return mStrings == null ? 0 : mStrings.size() + 1;
    }

    @Override
    public String getItem(int position) {
        if (mStrings != null && position > 0)
            return mStrings.get(position - 1);
        else
            return null;
    }

    @Override
    public long getItemId(int position) {
        if (mStrings == null && position > 0)
            return mStrings.get(position).hashCode();
        else
            return -1;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = null;
        if (position == 0) {
            view = getNoSelectionView();
        } else {
            view = View.inflate(mContext, R.layout.view_list_item, null);
            ImageView letters = (ImageView) view.findViewById(R.id.ImgVw_Letters);
            TextView dispalyName = (TextView) view.findViewById(R.id.TxtVw_DisplayName);
            letters.setImageDrawable(getTextDrawable(mStrings.get(position-1)));
            dispalyName.setText(mStrings.get(position-1));
        }
        return view;
    }

    @Override
    public View getSelectedView(int position) {
        View view = null;
        if (position == 0) {
            view = getNoSelectionView();
        } else {
            view = View.inflate(mContext, R.layout.view_list_item, null);
            ImageView letters = (ImageView) view.findViewById(R.id.ImgVw_Letters);
            TextView dispalyName = (TextView) view.findViewById(R.id.TxtVw_DisplayName);
            letters.setImageDrawable(getTextDrawable(mStrings.get(position-1)));
            dispalyName.setText(mStrings.get(position-1));
        }
        return view;
    }

    @Override
    public View getNoSelectionView() {
        View view = View.inflate(mContext, R.layout.view_list_no_selection_item, null);
        return view;
    }

    private TextDrawable getTextDrawable(String displayName) {
        TextDrawable drawable = null;
        if (!TextUtils.isEmpty(displayName)) {
            int color2 = ColorGenerator.MATERIAL.getColor(displayName);
            drawable = TextDrawable.builder()
                    .beginConfig()
                    .width(UITools.dpToPx(mContext, 32))
                    .height(UITools.dpToPx(mContext, 32))
                    .textColor(Color.WHITE)
                    .toUpperCase()
                    .endConfig()
                    .round()
                    .build(displayName.substring(0, 1), color2);
        } else {
            drawable = TextDrawable.builder()
                    .beginConfig()
                    .width(UITools.dpToPx(mContext, 32))
                    .height(UITools.dpToPx(mContext, 32))
                    .endConfig()
                    .round()
                    .build("?", Color.GRAY);
        }
        return drawable;
    }

    @Override
    public Filter getFilter() {
        return mStringFilter;
    }

    public class StringFilter extends Filter {

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            final FilterResults filterResults = new FilterResults();
            if (TextUtils.isEmpty(constraint)) {
                filterResults.count = mBackupStrings.size();
                filterResults.values = mBackupStrings;
                return filterResults;
            }
            final ArrayList<String> filterStrings = new ArrayList<>();
            for (String text : mBackupStrings) {
                if (text.toLowerCase().contains(constraint)) {
                    filterStrings.add(text);
                }
            }
            filterResults.count = filterStrings.size();
            filterResults.values = filterStrings;
            return filterResults;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            mStrings = (ArrayList) results.values;
            notifyDataSetChanged();
        }
    }

    private class ItemView {
        public ImageView mImageView;
        public TextView mTextView;
    }

    public enum ItemViewType {
        ITEM, NO_SELECTION_ITEM;
    }
}
(d). SimpleListAdapter.java

The SimpleListAdapter class.

Here’s the full code.

package gr.escsoft.michaelprimez.searchablespinnerexamples;

import android.content.Context;
import android.graphics.Color;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;

import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;

import java.util.ArrayList;

import gr.escsoft.michaelprimez.revealedittext.tools.UITools;
import gr.escsoft.michaelprimez.searchablespinner.interfaces.ISpinnerSelectedView;
import gr.escsoft.michaelprimez.searchablespinner.interfaces.OnItemSelectedListener;

public class SimpleListAdapter extends BaseAdapter implements Filterable, ISpinnerSelectedView {

    private Context mContext;
    private ArrayList<String> mBackupStrings;
    private ArrayList<String> mStrings;
    private StringFilter mStringFilter = new StringFilter();

    public SimpleListAdapter(Context context, ArrayList<String> strings) {
        mContext = context;
        mStrings = strings;
        mBackupStrings = strings;
    }

    @Override
    public int getCount() {
        return mStrings == null ? 0 : mStrings.size() + 1;
    }

    @Override
    public Object getItem(int position) {
        if (mStrings != null && position > 0)
            return mStrings.get(position - 1);
        else
            return null;
    }

    @Override
    public long getItemId(int position) {
        if (mStrings == null && position > 0)
            return mStrings.get(position).hashCode();
        else
            return -1;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = null;
        if (position == 0) {
            view = getNoSelectionView();
        } else {
            view = View.inflate(mContext, R.layout.view_list_item, null);
            ImageView letters = (ImageView) view.findViewById(R.id.ImgVw_Letters);
            TextView dispalyName = (TextView) view.findViewById(R.id.TxtVw_DisplayName);
            letters.setImageDrawable(getTextDrawable(mStrings.get(position-1)));
            dispalyName.setText(mStrings.get(position-1));
        }
        return view;
    }

    @Override
    public View getSelectedView(int position) {
        View view = null;
        if (position == 0) {
            view = getNoSelectionView();
        } else {
            view = View.inflate(mContext, R.layout.view_list_item, null);
            ImageView letters = (ImageView) view.findViewById(R.id.ImgVw_Letters);
            TextView dispalyName = (TextView) view.findViewById(R.id.TxtVw_DisplayName);
            letters.setImageDrawable(getTextDrawable(mStrings.get(position-1)));
            dispalyName.setText(mStrings.get(position-1));
        }
        return view;
    }

    @Override
    public View getNoSelectionView() {
        View view = View.inflate(mContext, R.layout.view_list_no_selection_item, null);
        return view;
    }

    private TextDrawable getTextDrawable(String displayName) {
        TextDrawable drawable = null;
        if (!TextUtils.isEmpty(displayName)) {
            int color2 = ColorGenerator.MATERIAL.getColor(displayName);
            drawable = TextDrawable.builder()
                    .beginConfig()
                    .width(UITools.dpToPx(mContext, 32))
                    .height(UITools.dpToPx(mContext, 32))
                    .textColor(Color.WHITE)
                    .toUpperCase()
                    .endConfig()
                    .round()
                    .build(displayName.substring(0, 1), color2);
        } else {
            drawable = TextDrawable.builder()
                    .beginConfig()
                    .width(UITools.dpToPx(mContext, 32))
                    .height(UITools.dpToPx(mContext, 32))
                    .endConfig()
                    .round()
                    .build("?", Color.GRAY);
        }
        return drawable;
    }

    @Override
    public Filter getFilter() {
        return mStringFilter;
    }

    public class StringFilter extends Filter {

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            final FilterResults filterResults = new FilterResults();
            if (TextUtils.isEmpty(constraint)) {
                filterResults.count = mBackupStrings.size();
                filterResults.values = mBackupStrings;
                return filterResults;
            }
            final ArrayList<String> filterStrings = new ArrayList<>();
            for (String text : mBackupStrings) {
                if (text.toLowerCase().contains(constraint)) {
                    filterStrings.add(text);
                }
            }
            filterResults.count = filterStrings.size();
            filterResults.values = filterStrings;
            return filterResults;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            mStrings = (ArrayList) results.values;
            notifyDataSetChanged();
        }
    }

    private class ItemView {
        public ImageView mImageView;
        public TextView mTextView;
    }

    public enum ItemViewType {
        ITEM, NO_SELECTION_ITEM;
    }
}

Download

Download the project below.

No. Location Link
1. GitHub Direct Download
2. GitHub Browse

Credit to the Original Creator michaelprimez

How to Run

  1. Download the project.
  2. Go over to app folder and edit import it to your android studio.Alternatively you can just copy paste the classes as well as the layouts and maybe other resources into your already created project.
  3. Then edit the app level build/gradle to add our dependency.

Example 3: Searchable Spinner Dialog

This example is a searchable spinner but with a dialog being shown. The spinner is rendered on a dialog. It can be claimed that this type of configuration is even more convenient since you can link the spinner to almost any widget. All you need is handle the click event of that widget and consequently display the dialog with the spinner.

Let as look at an example. Here is the demo of what will be created:

Searchable Spinner Example

Following the following steps:

Step 1: Dependencies

In your app level build.gradle add the following implementation statement then sync your project:

implementation 'kenmeidearu.searchablespinner:searchablespinnerlibrary:1.5.0'

Step 2: Add Spinner to Layout

In your xml layout, add the searchable spinner as follows:

    <com.kenmeidearu.searchablespinnerlibrary.SearchableSpinner
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

Here is the full layout:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="16dp"
    android:orientation="vertical"
    tools:context="com.kenmeidearu.sample.MainActivity">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:gravity="center"
        android:text="Kenmeidearu Spinner"/>

    <com.kenmeidearu.searchablespinnerlibrary.SearchableSpinner
        android:id="@+id/spinner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="20dp"
        android:layout_gravity="center"
        android:gravity="center" />

    <com.kenmeidearu.searchablespinnerlibrary.SearchableSpinner
        android:id="@+id/spinner1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="20dp"
        app:hintText="Select Customer"/>

    <com.kenmeidearu.searchablespinnerlibrary.SearchableSpinner
        android:id="@+id/spinner2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="20dp"
        app:hintText="Select Customer"/>
</LinearLayout>

Write Activity Code

Here generate your data. For example to load data from a string array into an arraylist:

       ArrayList<mListString> StringIsi = new ArrayList<>();
        customerNama = getResources().getStringArray(R.array.planets);
        int id = 0;
        for (String s : customerNama) {
            StringIsi.add(new mListString(id, s, s, s, s));
            id++;
        }

Then specify the spinner prompt message or title:

        sp.setTitleList("--Select Planet--");

Then set the adapter to the spinner:

        sp.setAdapter(StringIsi, 2, 1);/

Here’s the full code:

MainActivity.kt

public class MainActivity extends AppCompatActivity {
    String[] customerNama = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SearchableSpinner sp = (SearchableSpinner) findViewById(R.id.spinner);
        final SearchableSpinner sp1 = (SearchableSpinner) findViewById(R.id.spinner1);
        SearchableSpinner sp2 = (SearchableSpinner) findViewById(R.id.spinner2);

        //for two data
        ArrayList<mListString> StringIsi = new ArrayList<>();//must crete this to generate data there are n1-n4
        customerNama = getResources().getStringArray(R.array.planets);
        int id = 0;
        for (String s : customerNama) {
            StringIsi.add(new mListString(id, s, s, s, s));
            id++;
        }
        assert sp != null;
        sp.setTitleList("--Select Planet--");//use this to create initial search first
        sp.setAdapter(StringIsi, 2, 1);// type spinner 1-4, search option 1-4

        //for 4 data
        final ArrayList<mListString> listStringsCustomer = new ArrayList<>();
        listStringsCustomer.add(new mListString(1, "Andi", "Ambon Street", "Active", "New"));
        listStringsCustomer.add(new mListString(2, "Budi", "Bandung Street", "Active", "New"));
        listStringsCustomer.add(new mListString(3, "Carli", "Chille Street", "Non Active", "New"));
        listStringsCustomer.add(new mListString(4, "Deni", "Denmark Street", "Active", "New"));
        listStringsCustomer.add(new mListString(5, "Eko", "Estonia Street", "Active", "New"));
        sp1.setTitleList("--Select Customer--");//use this to create initial search first
        sp1.setAdapter(listStringsCustomer, 4, 4);// type spinner 1-4, search option 1-4

        //for immage
        final ArrayList<mListString> listStringsNegara = new ArrayList<>();
        listStringsNegara.add(new mListString(1, "Indonesia", "INA", "https://upload.wikimedia.org/wikipedia/id/2/2d/Bendera_Indonesia_%28Merah_Putih%29_by_Vibriel.jpg", true));
        listStringsNegara.add(new mListString(1, "Amerika Serikat", "USA", "http://2fm.rte.ie/wp-content/uploads/2017/05/american-flag-1459201553ppe-1.jpg", true));
        listStringsNegara.add(new mListString(1, "England", "UK", "http://1.bp.blogspot.com/-G7UhV_i5Rcc/T_15FYC57KI/AAAAAAAAAEc/-Trp7ugfE74/s1600/uk-flag.jpg", true));
        listStringsNegara.add(new mListString(1, "Jepang", "JP", "http://www.id.emb-japan.go.jp/image/expl12_01.jpg", true));
        sp2.setAdapter(listStringsNegara, 0, 2);//type zero for list with image

        sp1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                Log.e("tes posisi", id + " ," + position + "," + listStringsCustomer.get(position - 1).get_id() + "," + sp1.getSelectedItem().toString());

                mListString layerName = ((mListString) sp1.getSelectedItem());
                Toast.makeText(MainActivity.this, "You choose:" + layerName.getNilai1(), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
    }

}

Run

Run the project in android studio.

Reference

Download the code below:

Number Link
1. Download code
2. Follow code author

BEFORE YOU GO

YOU'VE BEEN SELECTED FOR A GIFT

Thanks for stopping by. My name is Oclemy(Clement Ochieng) and we have selected you as a recipient of a GIFT you may like ! Together with Skillshare we are offering you PROJECTS and 1000s of PREMIUM COURSES at Skillshare for FREE for 1 MONTH. To be eligible all you need is by sign up right now using my profile .

Related Examples

Leave a Reply

Your email address will not be published. Required fields are marked *

*

code