Filter ListView using Spinner or SearchView

Filter Listview Android

The oldest view for listing or rendering lists of items in android is the listview. If you want the simplest way to list items then it is the way to go. However after listing items you may wish to filter or search items. if that’s the case then this tutorial is for you.

Concepts You will Learn

This tutorial basically teaches you various ways of filtering data. You will learn the following:

  1. Filtering items in a listview or gridView using a dropdown/spinner.
  2. Filtering/Searching items in a listvew or gridview using a search view.
  3. How to filter a custom listview.
  4. How to filter JSON data downloaded via Retrofit.

We follow an example based approach whereby you learn by following source code. The code is well commented.

(a). How to filter a ListView using a dropdown/spinner.

Tools Used

Here are the tools used in this project:

  1. IDE: Android Studio
  2. Programming language: Java

Step 1 – Dependencies

This project doesn’t require any third party libraries.

Step 2 – Code

Let’s write some code:

First Start by adding the necessary imports:

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.Toast;

import java.util.ArrayList;

Extend the activity or the appcompatactivity to create for us an activity:

public class MainActivity extends Activity {

As instance properties of this activity, declare some components we will need: like ListView and spinner, as well as an array to host our filter parameters:

    ListView myListView;
    Spinner mySpinner;
    ArrayAdapter<CosmicBody> adapter;
    String[] categories={"All","Planets","Stars","Galaxies"};

Now generate our comsic bodies using the following method. These cosmic bodies are what the user will be filtering:

    private ArrayList<CosmicBody> getCosmicBodies() {
        ArrayList<CosmicBody> data = new ArrayList<>();
        data.clear();

        data.add(new CosmicBody("Mercury", 1));
        data.add(new CosmicBody("UY Scuti", 1));
        data.add(new CosmicBody("Andromeda", 3));
        data.add(new CosmicBody("VV Cephei A", 2));
        data.add(new CosmicBody("IC 1011", 3));
        data.add(new CosmicBody("Sun", 2));
        data.add(new CosmicBody("Aldebaran", 2));
        data.add(new CosmicBody("Venus", 1));
        data.add(new CosmicBody("Malin 1", 3));
        data.add(new CosmicBody("Rigel", 2));
        data.add(new CosmicBody("Earth", 1));
        data.add(new CosmicBody("Whirlpool", 3));
        data.add(new CosmicBody("VY Canis Majoris", 2));
        data.add(new CosmicBody("Saturn", 1));
        data.add(new CosmicBody("Sombrero", 3));
        data.add(new CosmicBody("Betelgeuse", 2));
        data.add(new CosmicBody("Uranus", 1));
        data.add(new CosmicBody("Virgo Stellar Stream", 3));
        data.add(new CosmicBody("Epsillon Canis Majoris", 2));
        data.add(new CosmicBody("Jupiter", 1));
        data.add(new CosmicBody("VY Canis Majos", 2));
        data.add(new CosmicBody("Triangulum", 3));
        data.add(new CosmicBody("Cartwheel", 3));
        data.add(new CosmicBody("Antares", 2));
        data.add(new CosmicBody("Mayall's Object", 3));
        data.add(new CosmicBody("Proxima Centauri", 2));
        data.add(new CosmicBody("Black Eye", 3));
        data.add(new CosmicBody("Mars", 1));
        data.add(new CosmicBody("Sirius", 2));
        data.add(new CosmicBody("Centaurus A", 3));
        data.add(new CosmicBody("Pinwheel", 3));
        data.add(new CosmicBody("Small Magellonic Cloud", 3));
        data.add(new CosmicBody("Uranus", 1));
        data.add(new CosmicBody("Alpha Centauri", 2));
        data.add(new CosmicBody("Large Magellonic Cloud", 3));

        return data;
    }

Here is the fill code for this activity:

. MainActivity.java

Add the following code in your main activity:

package info.camposha.listviewdropdownspinnerjava;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.Toast;

import java.util.ArrayList;

public class MainActivity extends Activity {

    ListView myListView;
    Spinner mySpinner;
    ArrayAdapter<CosmicBody> adapter;
    String[] categories={"All","Planets","Stars","Galaxies"};

    /*
    Initialize ListView and Spinner, set their adapters and listen to spinner itemSelection events
    */
    private void initializeViews() {

        mySpinner = findViewById(R.id.mySpinner);
        mySpinner.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, categories));

        myListView = findViewById(R.id.myListView);
        myListView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, getCosmicBodies()));

        //spinner selection events
        mySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int position, long itemID) {
                if (position >= 0 && position < categories.length) {
                    getSelectedCategoryData(position);
                } else {
                    Toast.makeText(MainActivity.this, "Selected Category Does not Exist!", Toast.LENGTH_SHORT).show();
                }
            }
            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        });
    }
    /*
    Populate an arraylist that will act as our data source.
     */
    private ArrayList<CosmicBody> getCosmicBodies() {
        ArrayList<CosmicBody> data = new ArrayList<>();
        data.clear();

        data.add(new CosmicBody("Mercury", 1));
        data.add(new CosmicBody("UY Scuti", 1));
        data.add(new CosmicBody("Andromeda", 3));
        data.add(new CosmicBody("VV Cephei A", 2));
        data.add(new CosmicBody("IC 1011", 3));
        data.add(new CosmicBody("Sun", 2));
        data.add(new CosmicBody("Aldebaran", 2));
        data.add(new CosmicBody("Venus", 1));
        data.add(new CosmicBody("Malin 1", 3));
        data.add(new CosmicBody("Rigel", 2));
        data.add(new CosmicBody("Earth", 1));
        data.add(new CosmicBody("Whirlpool", 3));
        data.add(new CosmicBody("VY Canis Majoris", 2));
        data.add(new CosmicBody("Saturn", 1));
        data.add(new CosmicBody("Sombrero", 3));
        data.add(new CosmicBody("Betelgeuse", 2));
        data.add(new CosmicBody("Uranus", 1));
        data.add(new CosmicBody("Virgo Stellar Stream", 3));
        data.add(new CosmicBody("Epsillon Canis Majoris", 2));
        data.add(new CosmicBody("Jupiter", 1));
        data.add(new CosmicBody("VY Canis Majos", 2));
        data.add(new CosmicBody("Triangulum", 3));
        data.add(new CosmicBody("Cartwheel", 3));
        data.add(new CosmicBody("Antares", 2));
        data.add(new CosmicBody("Mayall's Object", 3));
        data.add(new CosmicBody("Proxima Centauri", 2));
        data.add(new CosmicBody("Black Eye", 3));
        data.add(new CosmicBody("Mars", 1));
        data.add(new CosmicBody("Sirius", 2));
        data.add(new CosmicBody("Centaurus A", 3));
        data.add(new CosmicBody("Pinwheel", 3));
        data.add(new CosmicBody("Small Magellonic Cloud", 3));
        data.add(new CosmicBody("Uranus", 1));
        data.add(new CosmicBody("Alpha Centauri", 2));
        data.add(new CosmicBody("Large Magellonic Cloud", 3));

        return data;
    }
    /*
    Get the selected category's cosmic bodies and bind to ListView
     */
    private void getSelectedCategoryData(int categoryID) {
        //arraylist to hold selected cosmic bodies
        ArrayList<CosmicBody> cosmicBodies = new ArrayList<>();
        if(categoryID == 0)
        {
            adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, getCosmicBodies());
        }else{
            //filter by id
            for (CosmicBody cosmicBody : getCosmicBodies()) {
                if (cosmicBody.getCategoryId() == categoryID) {
                    cosmicBodies.add(cosmicBody);
                }
            }
            //instatiate adapter a
            adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, cosmicBodies);
        }
        //set the adapter to GridView
        myListView.setAdapter(adapter);
    }
    /*
    when activity is created, setContentView then initializeViews.
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initializeViews();
    }
}
/*
Data Object class to represent a single Cosmic body. Class has default access modifier
 */
class CosmicBody {
    private String name;
    private int categoryID;

    public String getName() {
        return name;
    }

    public int getCategoryId() {
        return categoryID;
    }

    public CosmicBody(String name, int categoryID) {
        this.name = name;
        this.categoryID = categoryID;
    }

    @Override
    public String toString() {
        return name;
    }
}

That’s the whole code required.

Step 3: Layouts

Copy the layout from the source code.

Step 4: Run

If your run the project you’ll get the following:

Step 5: Download

Download the code below:

No. Link
1. Browse/Download Code
2. Follow @Oclemy

(b). How to filter a listview using dropdown/spinner in Kotlin

These days kotlin is the goto language for android development. Solet’s see the first example re-written for Kotlin.

This example:

  1. Filters a listview using a dropdown/spinner.

Step 1: Dependencies

No third party dependencies used.

Step 2: Code

We have only one file:

MainActivity.kt

package info.camposha.kotlinlistviewfilter

import android.os.Bundle
import android.view.View
import android.widget.*
import android.widget.AdapterView.OnItemSelectedListener
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
   private var adapter: ArrayAdapter<CosmicBody>? = null
    var categories = arrayOf("All", "Planets", "Stars", "Galaxies")

    /*
    Initialize ListView and Spinner, set their adapters and listen to spinner itemSelection events
    */
    private fun initializeViews() {
        mySpinner.adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, categories)
        myListView.adapter = ArrayAdapter(
            this, android.R.layout.simple_list_item_1,
            cosmicBodies
        )
        //myListView.adapter=adapter

        //spinner selection events
        mySpinner.onItemSelectedListener = object : OnItemSelectedListener {
            override fun onItemSelected(
                adapterView: AdapterView<*>?,
                view: View,
                position: Int,
                itemID: Long
            ) {
                if (position >= 0 && position < categories.size) {
                    getSelectedCategoryData(position)
                } else {
                    Toast.makeText(
                        this@MainActivity,
                        "Selected Category Does not Exist!",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            }

            override fun onNothingSelected(adapterView: AdapterView<*>?) {}
        }
    }

    /*
   Populate an arraylist that will act as our data source.
    */
    private val cosmicBodies: ArrayList<CosmicBody>
        get() {
            val data = ArrayList<CosmicBody>()
            data.add(CosmicBody("Mercury", 1))
            data.add(CosmicBody("UY Scuti", 1))
            data.add(CosmicBody("Andromeda", 3))
            data.add(CosmicBody("VV Cephei A", 2))
            data.add(CosmicBody("IC 1011", 3))
            data.add(CosmicBody("Sun", 2))
            data.add(CosmicBody("Aldebaran", 2))
            data.add(CosmicBody("Venus", 1))
            data.add(CosmicBody("Malin 1", 3))
            data.add(CosmicBody("Rigel", 2))
            data.add(CosmicBody("Earth", 1))
            data.add(CosmicBody("Whirlpool", 3))
            data.add(CosmicBody("VY Canis Majoris", 2))
            data.add(CosmicBody("Saturn", 1))
            data.add(CosmicBody("Sombrero", 3))
            data.add(CosmicBody("Betelgeuse", 2))
            data.add(CosmicBody("Uranus", 1))
            data.add(CosmicBody("Virgo Stellar Stream", 3))
            data.add(CosmicBody("Epsillon Canis Majoris", 2))
            data.add(CosmicBody("Jupiter", 1))
            data.add(CosmicBody("VY Canis Majos", 2))
            data.add(CosmicBody("Triangulum", 3))
            data.add(CosmicBody("Cartwheel", 3))
            data.add(CosmicBody("Antares", 2))
            data.add(CosmicBody("Mayall's Object", 3))
            data.add(CosmicBody("Proxima Centauri", 2))
            data.add(CosmicBody("Black Eye", 3))
            data.add(CosmicBody("Mars", 1))
            data.add(CosmicBody("Sirius", 2))
            data.add(CosmicBody("Centaurus A", 3))
            data.add(CosmicBody("Pinwheel", 3))
            data.add(CosmicBody("Small Magellonic Cloud", 3))
            data.add(CosmicBody("Uranus", 1))
            data.add(CosmicBody("Alpha Centauri", 2))
            data.add(CosmicBody("Large Magellonic Cloud", 3))
            return data
        }

    /*
   Get the selected category's cosmic bodies and bind to ListView
    */
    private fun getSelectedCategoryData(categoryID: Int) {
        //arraylist to hold selected cosmic bodies
        val data = ArrayList<CosmicBody>()
        adapter = if (categoryID == 0) {
            ArrayAdapter(
                this, android.R.layout.simple_list_item_1,
                cosmicBodies
            )

        } else {
            //filter by id
            for (cosmicBody in cosmicBodies) {
                if (cosmicBody.categoryId == categoryID) {
                    data.add(cosmicBody)
                }
            }
            //instatiate adapter a
            ArrayAdapter(this, android.R.layout.simple_list_item_1, data)
        }
        //set the adapter to GridView
        myListView!!.adapter = adapter
    }

    /*
    when activity is created, setContentView then initializeViews.
     */
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initializeViews()
    }
}

/*
Data Object class to represent a single Cosmic body. Class has default access modifier
 */
class CosmicBody(private val name: String, val categoryId: Int) {

    override fun toString(): String {
        return name
    }
}

Step 3: Layouts

Copy layout from the source code reference.

Step 4: Run

If you run the project you get the following:

Kotlin Filter ListView

Step 5: Download

Download the code below:

No. Link
1. Browse/Download Code
2. Follow @Oclemy

Example 3: Android Filter GridView Using Spinner/Dropdown

Android Filter GridView using Spinner Example

In this tutorial we want to see how to filter a gridview using a spinner widget. You select a category from the spinner or dropdown and that is used as a constraint thus allowing us filter a simple gridview.

Demo

Here’s the gif demo of the project:

Layouts

We have only a single layout:

(a). activity_main.xml

Our mainactivity’s layout. Here we have a header textview, a spinner which is our dropdown widget and a gridview which is our adapterview.

This is our only layout and it gets inflated into our main activity.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout

    android_layout_width="match_parent"
    android_layout_height="match_parent"
    tools_context="info.camposha.gridviewdropdownfilter.MainActivity">

    <TextView
        android_id="@+id/headerLabel"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_alignParentTop="true"
        android_layout_centerHorizontal="true"
        android_fontFamily="casual"
        android_text="Cosmic Bodies"
        android_textAllCaps="true"
        android_textSize="24sp"
        android_textStyle="bold" />

    <Spinner
        android_id="@+id/mySpinner"
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_padding="5dp"
        android_layout_below="@id/headerLabel"
        android_layout_centerHorizontal="true"
        android_background="@android:drawable/editbox_dropdown_light_frame" />
    <GridView
        android_id="@+id/myGridView"
        android_numColumns="auto_fit"
        android_layout_below="@id/mySpinner"
        android_layout_width="match_parent"
        android_layout_height="wrap_content" />

</RelativeLayout>

Java Code

We have one class:

(a). MainActivity.java

The main activity is the entry point to our Kotlin app. We have cleanly commented the code for inline explanations.

package info.camposha.gridviewdropdownfilter;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.Spinner;
import android.widget.Toast;

import java.util.ArrayList;

public class MainActivity extends Activity {

    GridView myGridView;
    Spinner mySpinner;
    ArrayAdapter<CosmicBody> adapter;
    String[] categories={"All","Planets","Stars","Galaxies"};
    /*
    when activity is created
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initializeViews();
    }
    /*
    Initialize GridView and Spinner, set their adapters and listen to spinner itemSelection events
    */
    private void initializeViews() {

    mySpinner = findViewById(R.id.mySpinner);
        mySpinner.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, categories));

        myGridView = findViewById(R.id.myGridView);
        myGridView.setAdapter(new ArrayAdapter<CosmicBody>(this, android.R.layout.simple_list_item_1, getCosmicBodies()));

        //spinner selection events
        mySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int position, long itemID) {
                if (position >= 0 && position < categories.length) {
                    getSelectedCategoryData(position);
                } else {
                    Toast.makeText(MainActivity.this, "Selected Category Does not Exist!", Toast.LENGTH_SHORT).show();
                }
            }
            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        });
    }
    /*
    Populate an arraylist that will act as our data source.
     */
    private ArrayList<CosmicBody> getCosmicBodies() {
        ArrayList<CosmicBody> data = new ArrayList<>();
        data.clear();

        data.add(new CosmicBody("Mercury", 1));
        data.add(new CosmicBody("UY Scuti", 1));
        data.add(new CosmicBody("Andromeda", 3));
        data.add(new CosmicBody("VV Cephei A", 2));
        data.add(new CosmicBody("IC 1011", 3));
        data.add(new CosmicBody("Sun", 2));
        data.add(new CosmicBody("Aldebaran", 2));
        data.add(new CosmicBody("Venus", 1));
        data.add(new CosmicBody("Malin 1", 3));
        data.add(new CosmicBody("Rigel", 2));
        data.add(new CosmicBody("Earth", 1));
        data.add(new CosmicBody("Whirlpool", 3));
        data.add(new CosmicBody("VY Canis Majoris", 2));
        data.add(new CosmicBody("Saturn", 1));
        data.add(new CosmicBody("Sombrero", 3));
        data.add(new CosmicBody("Betelgeuse", 2));
        data.add(new CosmicBody("Uranus", 1));
        data.add(new CosmicBody("Virgo Stellar Stream", 3));
        data.add(new CosmicBody("Epsillon Canis Majoris", 2));
        data.add(new CosmicBody("Jupiter", 1));
        data.add(new CosmicBody("VY Canis Majos", 2));
        data.add(new CosmicBody("Triangulum", 3));
        data.add(new CosmicBody("Cartwheel", 3));
        data.add(new CosmicBody("Antares", 2));
        data.add(new CosmicBody("Mayall's Object", 3));
        data.add(new CosmicBody("Proxima Centauri", 2));
        data.add(new CosmicBody("Black Eye", 3));
        data.add(new CosmicBody("Mars", 1));
        data.add(new CosmicBody("Sirius", 2));
        data.add(new CosmicBody("Centaurus A", 3));
        data.add(new CosmicBody("Pinwheel", 3));
        data.add(new CosmicBody("Small Magellonic Cloud", 3));
        data.add(new CosmicBody("Uranus", 1));
        data.add(new CosmicBody("Alpha Centauri", 2));
        data.add(new CosmicBody("Large Magellonic Cloud", 3));

        return data;
    }
    /*
    Get the selected category's cosmic bodies and bind to GridView
     */
    private void getSelectedCategoryData(int categoryID) {
        //arraylist to hold selected cosmic bodies
        ArrayList<CosmicBody> cosmicBodies = new ArrayList<>();
        if(categoryID == 0)
        {
            adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, getCosmicBodies());
        }else{
            //filter by id
            for (CosmicBody cosmicBody : getCosmicBodies()) {
                if (cosmicBody.getCategoryId() == categoryID) {
                    cosmicBodies.add(cosmicBody);
                }
            }
    //instatiate adapter a
        adapter = new ArrayAdapter<CosmicBody>(this, android.R.layout.simple_list_item_1, cosmicBodies);
        }
        //set the adapter to GridView
        myGridView.setAdapter(adapter);
    }
}
   /*
   Data Object class to represent a single Cosmic body. Class has default access modifier
    */
class CosmicBody {
    private String name;
    private int categoryID;

    public String getName() {
        return name;
    }

    public int getCategoryId() {
        return categoryID;
    }

    public CosmicBody(String name, int categoryID) {
        this.name = name;
        this.categoryID = categoryID;
    }

    @Override
    public String toString() {
        return name;
    }
}
Download

You can download the full source code below or watch the video from the link provided.

No. Location Link
1. GitHub Direct Download
2. GitHub Browse
3. YouTube Video Tutorial
4. YouTube ProgrammingWizards TV Channel

Part 2 – Filtering Using a Searchview

In this part we will see how to filter search a gridview or listview using a searchview.

Example 1: Android ListView – Search/Filter

In this example, we’ll see how to search filter an android listview.

We’ll use a SearchView component.

Step 1: Gradle Files

We do not need any special dependencies for this project.

Step 2: Create Layouts

We’ll have these three layouts in our project:

1. activity_main.xml

Our main activity’s layout:

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

        android_layout_width="match_parent"
        android_layout_height="match_parent"
        android_fitsSystemWindows="true"
        tools_context="com.tutorials.hp.lvfilter.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.FloatingActionButton
            android_id="@+id/fab"
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_layout_gravity="bottom|end"
            android_layout_margin="@dimen/fab_margin"
            android_src="@android:drawable/ic_dialog_email" />

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

2. content_main.xml

  • This layout will hold our ListView and SearchView.
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout

        android_layout_width="match_parent"
        android_layout_height="match_parent"
        android_paddingBottom="@dimen/activity_vertical_margin"
        android_paddingLeft="@dimen/activity_horizontal_margin"
        android_paddingRight="@dimen/activity_horizontal_margin"
        android_paddingTop="@dimen/activity_vertical_margin"
        app_layout_behavior="@string/appbar_scrolling_view_behavior"
        tools_context="com.tutorials.hp.lvfilter.MainActivity"
        tools_showIn="@layout/activity_main">

        <android.support.v7.widget.SearchView
            android_id="@+id/mSearch"
            android_layout_width="match_parent"
            android_layout_height="50dp"

            app_defaultQueryHint="Search.."

            />
        <ListView
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_id="@+id/lv"
            android_layout_below="@+id/mSearch"
            android_layout_alignParentLeft="true"
            android_layout_alignParentStart="true" />
    </RelativeLayout>

3. model.xml

This layout will define the model for our custom rows.Our ListView will have images and text.

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.v7.widget.CardView
        android_orientation="horizontal" android_layout_width="match_parent"

        android_layout_margin="10dp"
        card_view_cardCornerRadius="10dp"
        card_view_cardElevation="10dp"

        android_layout_height="wrap_content">

        <RelativeLayout
            android_layout_width="match_parent"
            android_layout_height="match_parent">

            <ImageView
                android_layout_width="wrap_content"
                android_layout_height="wrap_content"
                android_id="@+id/movieImage"
                android_padding="10dp"
                android_src="@drawable/ghost" />

            <TextView
                android_layout_width="wrap_content"
                android_layout_height="wrap_content"
                android_textAppearance="?android:attr/textAppearanceLarge"
                android_text="Name"
                android_id="@+id/nameTxt"
                android_padding="10dp"
                android_textColor="@color/colorAccent"
                android_layout_below="@+id/movieImage"
                android_layout_alignParentLeft="true"
                 />

            <TextView
                android_layout_width="wrap_content"
                android_layout_height="wrap_content"
                android_textAppearance="?android:attr/textAppearanceLarge"
                android_text=" John Doe a former FBI Agent and now Physics teacher .is wrongly accussed of murdering an innocent child.He makes it his business to find the bad guys who did taht.He convinces hacker Aram to join him.....
                "
                android_id="@+id/descTxt"
                android_padding="10dp"
                android_layout_below="@+id/nameTxt"
                android_layout_alignParentLeft="true"
                />

            <TextView
                android_layout_width="wrap_content"
                android_layout_height="wrap_content"
                android_textAppearance="?android:attr/textAppearanceMedium"
                android_text="TV Show"
                android_id="@+id/posTxt"
                android_padding="10dp"

                android_layout_below="@+id/movieImage"
                android_layout_alignParentRight="true" />

            <CheckBox
                android_layout_width="wrap_content"
                android_layout_height="wrap_content"
                android_id="@+id/chk"
                android_layout_alignParentRight="true"
                />

        </RelativeLayout>
    </android.support.v7.widget.CardView>

Step 3 Write Java Code

Here are our Java classes:

1. Create Model Class:

Movie.java

  • Our data object.
  • Will represent a single movies.
    package com.tutorials.hp.lvfilter;

    public class Movie {

        private String name;
        private int image;

        public Movie(String name, int image) {
            this.name = name;
            this.image = image;
        }

        public String getName() {
            return name;
        }

        public int getImage() {
            return image;
        }
    }

2. Create Item Click Listener

ItemClickListner

An interface.It will define the signature for our OnItemClick() method.

    package com.tutorials.hp.lvfilter;

    import android.view.View;

    public interface ItemClickListener {

        void onItemClick(View v);
    }

3. Create ViewHolder

MyViewHolder.java

Our View holder class.

    package com.tutorials.hp.lvfilter;

    import android.view.View;
    import android.widget.ImageView;
    import android.widget.TextView;

    public class MyViewHolder implements View.OnClickListener {

        ImageView img;
        TextView nameTxt;
        ItemClickListener itemClickListener;

        public MyViewHolder(View v) {
            img= (ImageView) v.findViewById(R.id.movieImage);
            nameTxt= (TextView) v.findViewById(R.id.nameTxt);

            v.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            this.itemClickListener.onItemClick(v);
        }

        public void setItemClickListener(ItemClickListener ic)
        {
            this.itemClickListener=ic;
        }
    }

Create an Adapter class

MyAdapter.java

Our adapter class.It will Derive from BaseAdapter.It Implements Filterable interface.

    package com.tutorials.hp.lvfilter;

    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.Filter;
    import android.widget.Filterable;
    import android.widget.Toast;

    import java.util.ArrayList;

    public class MyAdapter extends BaseAdapter implements Filterable {

        Context c;
        ArrayList<Movie> movies;
        LayoutInflater inflater;

        ArrayList<Movie> filterList;
        CustomFilter filter;

        public MyAdapter(Context c, ArrayList<Movie> movies) {
            this.c = c;
            this.movies = movies;
            this.filterList=movies;
        }

        //TOTLA NUM OF MOVIES
        @Override
        public int getCount() {
            return movies.size();
        }

        //GET A SINGLE MOVIE
        @Override
        public Object getItem(int position) {
            return movies.get(position);
        }

        //IDENTITDIER
        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {

            if(inflater==null)
            {
                inflater= (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            }

            //PERFORM INFLATION
            if(convertView==null)
            {
                convertView=inflater.inflate(R.layout.model,null);
            }

            //BIND DATA TO VIEWS
            MyViewHolder holder=new MyViewHolder(convertView);
            holder.nameTxt.setText(movies.get(position).getName());
            holder.img.setImageResource(movies.get(position).getImage());

            holder.setItemClickListener(new ItemClickListener() {
                @Override
                public void onItemClick(View v) {
                    Toast.makeText(c,movies.get(position).getName(),Toast.LENGTH_SHORT).show();
                }
            });

            //RETURN A ROW
            return convertView;
        }

        @Override
        public Filter getFilter() {

            if(filter==null)
            {
                filter=new CustomFilter(filterList,this);
            }

            return filter;
        }
    }

Create a Custom Filter

CustomFilter.java

This class is responsible for our custom filtering.It Derives from android.widget.Filter.

    package com.tutorials.hp.lvfilter;

    import android.widget.Filter;

    import java.util.ArrayList;

    public class CustomFilter extends Filter {

        ArrayList<Movie> filterList;
        MyAdapter adapter;

        public CustomFilter(ArrayList<Movie> filterList, MyAdapter adapter) {
            this.filterList = filterList;
            this.adapter = adapter;
        }

        //FILTERING
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {

            //RESULTS
            FilterResults results=new FilterResults();

            //VALIDATION
            if(constraint != null && constraint.length()>0)
            {

                //CHANGE TO UPPER FOR CONSISTENCY
                constraint=constraint.toString().toUpperCase();

                ArrayList<Movie> filteredMovies=new ArrayList<>();

                //LOOP THRU FILTER LIST
                for(int i=0;i<filterList.size();i++)
                {
                    //FILTER
                    if(filterList.get(i).getName().toUpperCase().contains(constraint))
                    {
                        filteredMovies.add(filterList.get(i));
                    }
                }

                results.count=filteredMovies.size();
                results.values=filteredMovies;
            }else
            {
                results.count=filterList.size();
               results.values=filterList;
            }

            return results;
        }

        //PUBLISH RESULTS

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {

            adapter.movies= (ArrayList<Movie>) results.values;
            adapter.notifyDataSetChanged();

        }
    }

Create activity

MainActivity.java

This is Our launcher activity. It References both our ListView and SearchView.It Then sets the adapter to ListView. It also Listens to OnQueryTextChange events on the searchview.

    package com.tutorials.hp.lvfilter;

    import android.os.Bundle;
    import android.support.design.widget.FloatingActionButton;
    import android.support.design.widget.Snackbar;
    import android.support.v7.app.AppCompatActivity;
    import android.support.v7.widget.SearchView;
    import android.support.v7.widget.Toolbar;
    import android.view.View;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.widget.AdapterView;
    import android.widget.ListView;
    import android.widget.Toast;

    import java.util.ArrayList;

    public class MainActivity extends AppCompatActivity {

        SearchView sv;
        ListView lv;
        MyAdapter adapter;

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

            FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
            fab.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                            .setAction("Action", null).show();
                }
            });

            sv= (SearchView) findViewById(R.id.mSearch);
            lv= (ListView) findViewById(R.id.lv);

            adapter=new MyAdapter(this,getMovies());
            lv.setAdapter(adapter);

            sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
                @Override
                public boolean onQueryTextSubmit(String query) {
                    return false;
                }

                @Override
                public boolean onQueryTextChange(String query) {
                    adapter.getFilter().filter(query);
                    return false;
                }
            });

        }

        private ArrayList<Movie> getMovies() {
            //COLECTION OF CRIME MOVIES
            ArrayList<Movie> movies=new ArrayList<>();

            Movie movie=new Movie("BlackList",R.drawable.red);

            //ADD ITR TO COLLECTION
            movies.add(movie);

            movie=new Movie("Fruts",R.drawable.fruits);
            movies.add(movie);

            movie=new Movie("Breaking Bad",R.drawable.breaking);
            movies.add(movie);

            movie=new Movie("Crisis",R.drawable.crisis);
            movies.add(movie);

            movie=new Movie("Ghost Rider",R.drawable.rider);
            movies.add(movie);

            movie=new Movie("Star Wars",R.drawable.starwars);
            movies.add(movie);

            movie=new Movie("Shuttle Carrier",R.drawable.shuttlecarrier);
            movies.add(movie);

            movie=new Movie("Men In Black",R.drawable.meninblack);
            movies.add(movie);

            movie=new Movie("Game Of Thrones",R.drawable.thrones);
            movies.add(movie);

            return movies;
        }

    }

Example 2: Android Custom Filter/Search ListView With Images Text [BaseAdapter]

We cover how to perform a Custom Filter against data in your ListView.Our adapter is BaseAdapter and we shall be searching ListView with images and text.We shall implement Filterable interface and derive from Filter class.

PLATFORM : Android Java
TOOLS : Eclipse,Bluestacks Emulator

Step 1: Our Player Class

Purpose :

  1. Is our POJO class.Plain Old Java Object
  2. Holds data consisting of a single Player.
package com.tutorials.listviewcustomfilterbase;

public class Player {

  private String name;
  private int img;

  public Player(String name,int img) {
    // TODO Auto-generated constructor stub

    this.name=name;
    this.img=img;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getImg() {
    return img;
  }

  public void setImg(int img) {
    this.img = img;
  }
}

Step 2 : Our Custom Adapter class

Purpose:

  1. Adapts our images and Text to our ListView
  2. Is where we bind data to views
  3. Has an inner class CustomFilter that implements Filtering or Searching for us.
  4. Implements Filterable method hence we override getFilter() method that in turn returns a filter object.
package com.tutorials.listviewcustomfilterbase;

import java.util.ArrayList;

import android.content.Context;
import android.view.LayoutInflater;
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;

public class Adapter extends BaseAdapter implements Filterable{

  Context c;
  ArrayList<Player> players;
  CustomFilter filter;
  ArrayList<Player> filterList;

  public Adapter(Context ctx,ArrayList<Player> players) {
    // TODO Auto-generated constructor stub

    this.c=ctx;
    this.players=players;
    this.filterList=players;
  }

  @Override
  public int getCount() {
    // TODO Auto-generated method stub
    return players.size();
  }

  @Override
  public Object getItem(int pos) {
    // TODO Auto-generated method stub
    return players.get(pos);
  }

  @Override
  public long getItemId(int pos) {
    // TODO Auto-generated method stub
    return players.indexOf(getItem(pos));
  }

  @Override
  public View getView(int pos, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub

    LayoutInflater inflater=(LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    if(convertView==null)
    {
      convertView=inflater.inflate(R.layout.model, null);
    }

    TextView nameTxt=(TextView) convertView.findViewById(R.id.nameTv);
    ImageView img=(ImageView) convertView.findViewById(R.id.imageView1);

    //SET DATA TO THEM
    nameTxt.setText(players.get(pos).getName());
    img.setImageResource(players.get(pos).getImg());

    return convertView;
  }

  @Override
  public Filter getFilter() {
    // TODO Auto-generated method stub
    if(filter == null)
    {
      filter=new CustomFilter();
    }

    return filter;
  }

  //INNER CLASS
  class CustomFilter extends Filter
  {

    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
      // TODO Auto-generated method stub

      FilterResults results=new FilterResults();

      if(constraint != null && constraint.length()>0)
      {
        //CONSTARINT TO UPPER
        constraint=constraint.toString().toUpperCase();

        ArrayList<Player> filters=new ArrayList<Player>();

        //get specific items
        for(int i=0;i<filterList.size();i++)
        {
          if(filterList.get(i).getName().toUpperCase().contains(constraint))
          {
            Player p=new Player(filterList.get(i).getName(), filterList.get(i).getImg());

            filters.add(p);
          }
        }

        results.count=filters.size();
        results.values=filters;

      }else
      {
        results.count=filterList.size();
        results.values=filterList;

      }

      return results;
    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
      // TODO Auto-generated method stub

      players=(ArrayList<Player>) results.values;
      notifyDataSetChanged();
    }

  }

}

Step 3: Our MainActivity class

Purpose :

  1. Our launcher activity
  2. We set reference our ListView from XML and attach its BaseAdapter subclass to it.
  3. We reference our SearchView and implement its onQueryTextChangeListener.
package com.tutorials.listviewcustomfilterbase;

import java.util.ArrayList;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;

public class MainActivity extends Activity {

  ListView lv;
  SearchView sv;

  String[] names={"Juan Mata","Ander Herera","Wayne Rooney","Eden Hazard","Michael Carrick","Diego Costa","Jose Mourinho"};
  int[] images={R.drawable.mata,R.drawable.herera,R.drawable.rooney,R.drawable.hazard,R.drawable.carrick,R.drawable.costa,R.drawable.mourinho};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        lv=(ListView) findViewById(R.id.listView1);
        sv=(SearchView) findViewById(R.id.searchView1);

        //ADASPTER
        final Adapter adapter=new Adapter(this, getPlayers());
        lv.setAdapter(adapter);

        sv.setOnQueryTextListener(new OnQueryTextListener() {

      @Override
      public boolean onQueryTextSubmit(String arg0) {
        // TODO Auto-generated method stub
        return false;
      }

      @Override
      public boolean onQueryTextChange(String query) {
        // TODO Auto-generated method stub

        adapter.getFilter().filter(query);

        return false;
      }
    });

    }

    private ArrayList<Player> getPlayers()
    {
        ArrayList<Player> players=new ArrayList<Player>();
        Player p;

        for(int i=0;i<names.length;i++)
        {
            p=new Player(names[i], images[i]);
            players.add(p);
        }

        return players;
    }

}

Step 4 : Our ActivityMain.xml layout

Purpose :

  1. Acts as our template Layout.
  2. Hold our ListView and SearchView
<RelativeLayout

    android_layout_width="match_parent"
    android_layout_height="match_parent"
    android_paddingBottom="@dimen/activity_vertical_margin"
    android_paddingLeft="@dimen/activity_horizontal_margin"
    android_paddingRight="@dimen/activity_horizontal_margin"
    android_paddingTop="@dimen/activity_vertical_margin"
    tools_context=".MainActivity" >

    <SearchView
        android_id="@+id/searchView1"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_alignParentLeft="true"
        android_layout_alignParentTop="true"
        android_layout_alignRight="@+id/listView1"
        android_layout_marginLeft="14dp"
        android_queryHint="Search.." >

    </SearchView>

    <ListView
        android_id="@+id/listView1"
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_layout_alignParentLeft="true"
        android_layout_below="@+id/searchView1" >

    </ListView>

</RelativeLayout>

Step 5: Create Our Model.xml Layout

Purpose :

  1. Acts as our Row Model.Remember we want to display Listview with images and text.So its how a single row in our ListView shall appear.
  2. Contains Images andText.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    android_layout_width="match_parent"
    android_layout_height="match_parent" >

    <ImageView
        android_id="@+id/imageView1"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_alignParentLeft="true"
        android_layout_alignParentTop="true"
        android_layout_marginLeft="40dp"
        android_layout_marginTop="44dp"
        android_src="@drawable/ic_launcher" />

    <TextView
        android_id="@+id/nameTv"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_alignTop="@+id/imageView1"
        android_layout_toRightOf="@+id/imageView1"
        android_text="Name"
        android_padding="10dp"
        android_textAppearance="?android:attr/textAppearanceMedium" />

</RelativeLayout>

Example 3: Android ListView – Download JSON Images Text then Search/Filter

This is an android tutorial for searching json data bound to a custom listview with images and text.

We retrieve both images and text json data and bind to a custom listview. We then search/filter these data on the client side.

This is because we are dealing with raw json without any server side processing like with php or something. However our JSON comes from online and we make a HTTP GET request to download it.

While downloading our JSON data we show an indetereminate progress bar. The downloded json data as we said contains images and text.

In fact it contains text with image urls. Then via Picasso Image Loader, the images are fetched and bound to a custom listview with cardviews.

The user can then search this data via a searchview.

Let’s start.

We are Building a Vibrant YouTube Community

Here’s this tutorial in Video Format.

Resources

I want to use a custom material design theme so I will start by setting up some resources:

Step 1: Create Colors

Colors that will color our application:

colors.xml

We are using a custom material design theme so first we will create some material colors.This is optional. Add these to your 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="colorPrimary">#f39c12</color>
    <!--<color name="colorPrimaryDark">#125688</color>-->

    <color name="colorPrimaryDark">#FFC107</color>
    <color name="textColorPrimary">#FFFFFF</color>
    <color name="windowBackground">#FFFFFF</color>
    <color name="navigationBarColor">#000000</color>
    <!--<color name="colorAccent">#c8e8ff</color>-->
</resources>

Step 2: Create Styles

(a). styles.xml

I am creating a custom material theme called MyCustomMaterialTheme.

I specify it’s parent. Copy this code to your styles.xml. However if you don’t desire the custom theme skip this part and move to layouts.

<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="MyCustomMaterialTheme" parent="MyCustomMaterialTheme.Base">

    </style>

    <style name="MyCustomMaterialTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="windowNoTitle">false</item>
        <item name="windowActionBar">true</item>
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>

(b). styles.xml(v21)

Another skippable part. Create another XML values resource under the res/values folder. Name it styles-v21, this will target android lollipop.

Add the following code:

<resources>

    <style name="MyCustomMaterialTheme" parent="MyCustomMaterialTheme.Base">
        <item name="android:windowContentTransitions">true</item>
        <item name="android:windowAllowEnterTransitionOverlap">true</item>
        <item name="android:windowAllowReturnTransitionOverlap">true</item>
        <item name="android:windowSharedElementEnterTransition">@android:transition/move</item>
        <item name="android:windowSharedElementExitTransition">@android:transition/move</item>
    </style>
</resources>

Step 3: Add Necessary Permissions

You need to add the necessary permissions like the internet permission in your android manifest file. We also need to register our android components like the activities.

AndroidManifest.xml

This part is a must, add the permission for internet connectivity as we’ve done in your AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest
    package="info.camposha.listviewsearchjson">

    <uses-permission android_name="android.permission.INTERNET"/>

    <application
        android_allowBackup="true"
        android_icon="@mipmap/ic_launcher"
        android_label="@string/app_name"
        android_roundIcon="@mipmap/ic_launcher_round"
        android_supportsRtl="true"
        android_theme="@style/MyCustomMaterialTheme">
        <!--android:theme="@style/AppTheme">-->
        <activity android_name=".MainActivity">
            <intent-filter>
                <action android_name="android.intent.action.MAIN" />

                <category android_name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Step 4: Create Main Activity Layout

activity_main.xml

This layout is our Main Activity’s layout file. It defines the user interface of our main activity.

We write in XML which stands for eXtensible Markup Language. In android development, user interfaces are normally created in XML. However it’s also possible to create them programmatically in Java/Kotlin.

But XML is the easier yet more flexible option.

So as our root element we have a LinearLayout. LinearLayout usually arranges it’s child elements in a linear manner, either vertcially or horizontally.

So you have to specify the orientation. Am ranging my widgets vertically, one on top of another.

Then I create a textView to act as my header label. I will make it bold and give it the accent color.

Below the header label I will have a SearchView, which we will use to type our queries.Please assign it an id as we will need to reference it from java code.

Below the SearchView I will have a progressbar, which will show us the progress of the download of json data.

Finally we will have a ListView which will render our json data.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout

    android_layout_width="match_parent"
    android_layout_height="match_parent"
    android_orientation="vertical"
    tools_context="info.camposha.listviewsearchjson.MainActivity">
    <TextView
        android_id="@+id/textView"
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_text="Spacecrafts Searcher"
        android_textAlignment="center"
        android_textStyle="bold"
        android_textAppearance="@style/TextAppearance.AppCompat.Large"
        android_textColor="@color/colorAccent" />
    <SearchView
        android_id="@+id/mySearchView"
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_text="Spacecrafts Searcher"
        android_padding="5dp"
        android_queryHint="Search.."
        android_textAlignment="center" />

    <ProgressBar
        android_id="@+id/myProgressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_indeterminate="true"
        android_indeterminateBehavior="cycle"
        android_visibility="gone" />

    <ListView
        android_id="@+id/myListView"
        android_layout_weight="0.5"
        android_numColumns="auto_fit"
        android_layout_width="match_parent"
        android_layout_height="wrap_content" />
</LinearLayout>

Step 5: Create ListView Item Layout:

model.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    android_orientation="horizontal" android_layout_width="match_parent"

    android_layout_margin="5dp"
    card_view_cardCornerRadius="10dp"
    card_view_cardElevation="5dp"
    android_layout_height="match_parent">

    <RelativeLayout
        android_layout_width="match_parent"
        android_layout_height="match_parent">
        <ImageView
            android_layout_width="150dp"
            android_layout_height="150dp"
            android_id="@+id/spacecraftImageView"
            android_padding="5dp"
            android_src="@drawable/placeholder" />

        <TextView
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_textAppearance="?android:attr/textAppearanceLarge"
            android_text="Spacecraft Name"
            android_id="@+id/nameTextView"
            android_padding="5dp"
            android_textColor="@color/colorAccent"
            android_layout_alignParentTop="true"
            android_layout_toRightOf="@+id/spacecraftImageView" />

        <TextView
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_textAppearance="?android:attr/textAppearanceMedium"
            android_text="Propellant"
            android_textStyle="italic"
            android_id="@+id/propellantTextView"
            android_padding="5dp"
            android_layout_alignBottom="@+id/spacecraftImageView"
            android_layout_toRightOf="@+id/spacecraftImageView" />
        <CheckBox
            android_layout_width="wrap_content"
            android_layout_height="wrap_content"
            android_id="@+id/myCheckBox"
            android_text="Tech Exists?"
            android_layout_alignParentRight="true"
            />

    </RelativeLayout>
</android.support.v7.widget.CardView>

Here’s the json data we will use:

Activities

Create Main Activity

MainActivity.java

package info.camposha.listviewsearchjson;

import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ListView;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.SearchView;
import android.widget.Space;
import android.widget.TextView;
import android.widget.Toast;

import com.androidnetworking.AndroidNetworking;
import com.androidnetworking.common.Priority;
import com.androidnetworking.error.ANError;
import com.androidnetworking.interfaces.JSONArrayRequestListener;
import com.squareup.picasso.Picasso;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    /*
    Our data object
     */
    public class Spacecraft {
        /*
        INSTANCE FIELDS
         */
        private int id;
        private String name;
        private String propellant;
        private String imageURL;
        private int technologyExists;
        /*
        GETTERS AND SETTERS
         */
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getPropellant() {
            return propellant;
        }
        public void setPropellant(String propellant) {
            this.propellant = propellant;
        }
        public String getImageURL() {
            return imageURL;
        }
        public void setImageURL(String imageURL) {
            this.imageURL = imageURL;
        }
        public int getTechnologyExists() {
            return technologyExists;
        }
        public void setTechnologyExists(int technologyExists) {
            this.technologyExists = technologyExists;
        }
        /*
        TOSTRING
         */
        @Override
        public String toString() {
            return name;
        }
    }
    class FilterHelper extends Filter {
        ArrayList<Spacecraft> currentList;
        ListViewAdapter adapter;
        Context c;

        public FilterHelper(ArrayList<Spacecraft> currentList, ListViewAdapter adapter,Context c) {
            this.currentList = currentList;
            this.adapter = adapter;
            this.c=c;
        }
        /*
        - Perform actual filtering.
         */
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults filterResults=new FilterResults();

            if(constraint != null && constraint.length()>0)
            {
                //CHANGE TO UPPER
                constraint=constraint.toString().toUpperCase();

                //HOLD FILTERS WE FIND
                ArrayList<Spacecraft> foundFilters=new ArrayList<>();

                Spacecraft spacecraft=null;

                //ITERATE CURRENT LIST
                for (int i=0;i<currentList.size();i++)
                {
                    spacecraft= currentList.get(i);

                    //SEARCH
                    if(spacecraft.getName().toUpperCase().contains(constraint) )
                    {
                        //ADD IF FOUND
                        foundFilters.add(spacecraft);
                    }
                }

                //SET RESULTS TO FILTER LIST
                filterResults.count=foundFilters.size();
                filterResults.values=foundFilters;
            }else
            {
                //NO ITEM FOUND.LIST REMAINS INTACT
                filterResults.count=currentList.size();
                filterResults.values=currentList;
            }

            //RETURN RESULTS
            return filterResults;
        }

        @Override
        protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
            adapter.setSpacecrafts((ArrayList<Spacecraft>) filterResults.values);
            adapter.refresh();
        }
    }

    /*
    Our custom adapter class
     */
    public class ListViewAdapter extends BaseAdapter implements Filterable {

        Context c;
        ArrayList<Spacecraft> spacecrafts;
        public ArrayList<Spacecraft> currentList;
        FilterHelper filterHelper;

        public ListViewAdapter(Context c, ArrayList<Spacecraft> spacecrafts) {
            this.c = c;
            this.spacecrafts = spacecrafts;
            this.currentList=spacecrafts;
        }
        @Override
        public int getCount() {
            return spacecrafts.size();
        }
        @Override
        public Object getItem(int i) {
            return spacecrafts.get(i);
        }
        @Override
        public long getItemId(int i) {
            return i;
        }
        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            if(view==null)
            {
                view= LayoutInflater.from(c).inflate(R.layout.model,viewGroup,false);
            }

            TextView txtName = view.findViewById(R.id.nameTextView);
            TextView txtPropellant = view.findViewById(R.id.propellantTextView);
            CheckBox chkTechExists = view.findViewById(R.id.myCheckBox);
            ImageView spacecraftImageView = view.findViewById(R.id.spacecraftImageView);

            final Spacecraft s= (Spacecraft) this.getItem(i);

            txtName.setText(s.getName());
            txtPropellant.setText(s.getPropellant());
            //chkTechExists.setEnabled(true);
            chkTechExists.setChecked( s.getTechnologyExists()==1);
            chkTechExists.setEnabled(false);

            if(s.getImageURL() != null && s.getImageURL().length()>0)
            {
                Picasso.get().load(s.getImageURL()).placeholder(R.drawable.placeholder).into(spacecraftImageView);
            }else {
                Toast.makeText(c, "Empty Image URL", Toast.LENGTH_LONG).show();
                Picasso.get().load(R.drawable.placeholder).into(spacecraftImageView);
            }
            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Toast.makeText(c, s.getName(), Toast.LENGTH_SHORT).show();
                }
            });

            return view;
        }
        public void setSpacecrafts(ArrayList<Spacecraft> filteredSpacecrafts)
        {
            this.spacecrafts=filteredSpacecrafts;

        }
        @Override
        public Filter getFilter() {
            if(filterHelper==null)
        {
            filterHelper=new FilterHelper(currentList,this,c);
        }

            return filterHelper;
        }
        public void refresh(){
            notifyDataSetChanged();
        }
    }

    /*
    Our HTTP Client
     */
    public class JSONDownloader {

        //SAVE/RETRIEVE URLS
        private static final String JSON_DATA_URL="https://cdn.rawgit.com/Oclemy/SampleJSON/338d9585/spacecrafts.json";
        //INSTANCE FIELDS
        private final Context c;

        public JSONDownloader(Context c) {
            this.c = c;
        }
        /*
        Fetch JSON Data
         */
        public ArrayList<Spacecraft> retrieve(final ListView mListView, final ProgressBar myProgressBar)
        {
            final ArrayList<Spacecraft> downloadedData=new ArrayList<>();
            myProgressBar.setIndeterminate(true);
            myProgressBar.setVisibility(View.VISIBLE);

            AndroidNetworking.get(JSON_DATA_URL)
                    .setPriority(Priority.HIGH)
                    .build()
                    .getAsJSONArray(new JSONArrayRequestListener() {
                        @Override
                        public void onResponse(JSONArray response) {
                            JSONObject jo;
                            Spacecraft s;
                            try
                            {
                                for(int i=0;i<response.length();i++)
                                {
                                    jo=response.getJSONObject(i);

                                    int id=jo.getInt("id");
                                    String name=jo.getString("name");
                                    String propellant=jo.getString("propellant");
                                    String techExists=jo.getString("technologyexists");
                                    String imageURL=jo.getString("imageurl");

                                    s=new Spacecraft();
                                    s.setId(id);
                                    s.setName(name);
                                    s.setPropellant(propellant);
                                    s.setImageURL(imageURL);
                                    s.setTechnologyExists(techExists.equalsIgnoreCase("1") ? 1 : 0);

                                    downloadedData.add(s);
                                }
                                myProgressBar.setVisibility(View.GONE);

                            }catch (JSONException e)
                            {
                                myProgressBar.setVisibility(View.GONE);
                                Toast.makeText(c, "GOOD RESPONSE BUT JAVA CAN'T PARSE JSON IT RECEIEVED. "+e.getMessage(), Toast.LENGTH_LONG).show();
                            }
                        }
                        //ERROR
                        @Override
                        public void onError(ANError anError) {
                            anError.printStackTrace();
                            myProgressBar.setVisibility(View.GONE);
                            Toast.makeText(c, "UNSUCCESSFUL :  ERROR IS : "+anError.getMessage(), Toast.LENGTH_LONG).show();
                        }
                    });
            return downloadedData;
        }
    }
    ArrayList<Spacecraft> spacecrafts = new ArrayList<>();
    ListView myListView;
    ListViewAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        myListView= findViewById(R.id.myListView);
        final ProgressBar myProgressBar= findViewById(R.id.myProgressBar);
        SearchView mySearchView=findViewById(R.id.mySearchView);

        mySearchView.setIconified(true);
        mySearchView.setOnSearchClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

            }
        });
        mySearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {
                adapter.getFilter().filter(s);
                return false;
            }

            @Override
            public boolean onQueryTextChange(String query) {
                adapter.getFilter().filter(query);
                return false;
            }
        });
        spacecrafts=new JSONDownloader(MainActivity.this).retrieve(myListView,myProgressBar);
        adapter=new ListViewAdapter(this,spacecrafts);
        myListView.setAdapter(adapter);

    }
}

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