Today we are going to learn how to add search functionality to ListView, GridView and RecyclerView. In this tutorial you can filter search list by multiple items.
1. Create a new project in Android Studio by navigating to File ⇒ New ⇒ New Project and fill required details. By default my activity is MainActivity.java.
2. Open build.gradle and include this libraries show below:
1 2 |
compile 'com.android.support:design:25.1.0'//Library need for material tabs compile 'com.android.support:recyclerview-v7:25.1.0' //Library need for recycler view |
3. Now create 3 material tabs naming ListView, GridView and RecyclerView. For this you can check this link for reference.
4. After creating tabs lets move to creating xml layouts for individual tabs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp"> <include android:id="@+id/top_container" layout="@layout/top_container" android:layout_width="match_parent" android:layout_height="wrap_content" /> <ListView android:id="@+id/list_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/top_container" android:layout_marginTop="5dp" /> </RelativeLayout> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp"> <include android:id="@+id/top_container" android:layout_width="match_parent" android:layout_height="wrap_content" layout="@layout/top_container" /> <GridView android:id="@+id/grid_view" android:layout_width="match_parent" android:layout_below="@+id/top_container" android:layout_marginTop="5dp" android:layout_height="match_parent" android:horizontalSpacing="2dp" android:numColumns="2" android:verticalSpacing="2dp" /> </RelativeLayout> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp"> <include android:id="@+id/top_container" android:layout_width="match_parent" android:layout_height="wrap_content" layout="@layout/top_container" /> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_marginTop="5dp" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/top_container" /> </RelativeLayout> |
5. In all the above xml layouts i am using one common layout i.e. top_container.xml. Lets create the common layout xml, this layout contains some radio buttons for custom filter.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/search_via_label" android:layout_width="match_parent" android:layout_height="wrap_content" android:drawableRight="@drawable/up_dropdown" android:padding="5dp" android:text="@string/search_via" android:textColor="@android:color/black" android:textSize="10sp" /> <!-- Search Via Radio Group --> <RadioGroup android:id="@+id/search_via_radio_group" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:visibility="gone"> <RadioButton android:id="@+id/name_radio_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:checked="true" android:gravity="center_vertical" android:padding="5dp" android:text="@string/name" android:textColor="@android:color/black" android:textSize="12sp" /> <RadioButton android:id="@+id/number_radio_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_vertical" android:padding="5dp" android:text="@string/number" android:textColor="@android:color/black" android:textSize="12sp" /> <RadioButton android:id="@+id/email_radio_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_vertical" android:padding="5dp" android:text="@string/emailid" android:textColor="@android:color/black" android:textSize="12sp" /> </RadioGroup> <View android:layout_width="match_parent" android:layout_height="1px" android:layout_marginTop="5dp" android:background="@android:color/darker_gray" /> <TextView android:id="@+id/filter_by_label" android:layout_width="match_parent" android:layout_height="wrap_content" android:drawableRight="@drawable/up_dropdown" android:padding="5dp" android:text="@string/filter_by" android:textColor="@android:color/black" android:textSize="10sp" /> <!-- Filter By Radio Group --> <RadioGroup android:id="@+id/filter_type_radio_group" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:visibility="gone"> <RadioButton android:id="@+id/query_contains_radio_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:checked="true" android:gravity="center_vertical" android:padding="5dp" android:text="@string/contains" android:textColor="@android:color/black" android:textSize="12sp" /> <RadioButton android:id="@+id/query_starts_With_radio_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_vertical" android:padding="5dp" android:text="@string/starts_with" android:textColor="@android:color/black" android:textSize="12sp" /> </RadioGroup> <!-- EditText for User Input --> <EditText android:id="@+id/search_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:background="@drawable/search_bg" android:drawableLeft="@drawable/ic_search" android:drawablePadding="5dp" android:gravity="center_vertical" android:hint="@string/enter_text_to_search" android:maxLines="1" android:padding="8dp" android:textColor="@android:color/black" android:textColorHint="@android:color/darker_gray" android:textSize="12sp" /> </LinearLayout> |
6. Now create custom background for Search EditText naming search_bg.xml.
1 2 3 4 5 6 7 8 9 10 |
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:radius="4dp" /> <solid android:color="@android:color/white" /> <stroke android:width="1px" android:color="@android:color/darker_gray" /> </shape> |
7. Now lets create java classes for all the above three xml files.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
package com.listsearch_demo.main; import android.content.Context; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; import android.widget.ListView; import android.widget.RadioGroup; import android.widget.TextView; import com.listsearch_demo.R; import com.listsearch_demo.adapter.GridListAdapter; import com.listsearch_demo.helper.FilterType; import com.listsearch_demo.helper.GetUserModelData; import com.listsearch_demo.helper.UserModel; import java.util.ArrayList; /** * Created by sonu on 08/02/17. */ public class ListViewFragment extends Fragment implements RadioGroup.OnCheckedChangeListener, View.OnClickListener { private Context context; private GridListAdapter adapter; private ArrayList<UserModel> arrayList; private RadioGroup searchViaRadioGroup, filterByRadioGroup; private EditText searchEditText; private TextView searchViaLabel, filterByLabel; /* Filter Type to identify the type of Filter */ private FilterType filterType; /* boolean variable for Filtering */ private boolean isSearchWithPrefix = false; public ListViewFragment() { } @Override public void onAttach(Context context) { super.onAttach(context); this.context = context; } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.list_view_fragment, container, false); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); loadListView(view); findViews(view); implementEvents(); } //Bind all Views private void findViews(View view) { filterType = FilterType.NAME; searchViaRadioGroup = (RadioGroup) view.findViewById(R.id.search_via_radio_group); filterByRadioGroup = (RadioGroup) view.findViewById(R.id.filter_type_radio_group); searchEditText = (EditText) view.findViewById(R.id.search_text); searchViaLabel = (TextView) view.findViewById(R.id.search_via_label); filterByLabel = (TextView) view.findViewById(R.id.filter_by_label); } private void loadListView(View view) { ListView listView = (ListView) view.findViewById(R.id.list_view); arrayList = GetUserModelData.getUserModelData(); adapter = new GridListAdapter(context, arrayList, true); listView.setAdapter(adapter); } private void implementEvents() { filterByRadioGroup.setOnCheckedChangeListener(this); searchViaRadioGroup.setOnCheckedChangeListener(this); searchViaLabel.setOnClickListener(this); filterByLabel.setOnClickListener(this); searchEditText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { //On text changed in Edit text start filtering the list adapter.filter(filterType, charSequence.toString(), isSearchWithPrefix); } @Override public void afterTextChanged(Editable editable) { } }); } @Override public void onCheckedChanged(RadioGroup radioGroup, int checkedId) { int pos = radioGroup.indexOfChild(radioGroup.findViewById(checkedId));//get the checked position of radio button switch (radioGroup.getId()) { case R.id.search_via_radio_group: switch (pos) { case 0: filterType = FilterType.NAME;//Change filter type to Name if pos = 0 break; case 1: filterType = FilterType.NUMBER;//Change filter type to Number if pos = 1 break; case 2: filterType = FilterType.EMAIL;//Change filter type to Email if pos = 2 break; } break; case R.id.filter_type_radio_group: switch (pos) { case 0: isSearchWithPrefix = false;//Set boolean value to false break; case 1: isSearchWithPrefix = true;//Set boolean value to true break; } break; } } @Override public void onClick(View view) { switch (view.getId()) { case R.id.search_via_label: //show hide the radio group if (searchViaRadioGroup.isShown()) { searchViaLabel.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.up_dropdown, 0); searchViaRadioGroup.setVisibility(View.GONE); } else { searchViaLabel.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.down_dropdown, 0); searchViaRadioGroup.setVisibility(View.VISIBLE); } break; case R.id.filter_by_label: //show hide the radio group if (filterByRadioGroup.isShown()) { filterByLabel.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.up_dropdown, 0); filterByRadioGroup.setVisibility(View.GONE); } else { filterByLabel.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.down_dropdown, 0); filterByRadioGroup.setVisibility(View.VISIBLE); } break; } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
package com.listsearch_demo.main; import android.content.Context; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; import android.widget.GridView; import android.widget.RadioGroup; import android.widget.TextView; import com.listsearch_demo.R; import com.listsearch_demo.adapter.GridListAdapter; import com.listsearch_demo.helper.FilterType; import com.listsearch_demo.helper.GetUserModelData; import com.listsearch_demo.helper.UserModel; import java.util.ArrayList; /** * Created by sonu on 08/02/17. */ public class GridViewFragment extends Fragment implements RadioGroup.OnCheckedChangeListener, View.OnClickListener { private Context context; private GridListAdapter adapter; private ArrayList<UserModel> arrayList; private RadioGroup searchViaRadioGroup, filterByRadioGroup; private EditText searchEditText; private TextView searchViaLabel, filterByLabel; /* Filter Type to identify the type of Filter */ private FilterType filterType; /* boolean variable for Filtering */ private boolean isSearchWithPrefix = false; public GridViewFragment() { } @Override public void onAttach(Context context) { super.onAttach(context); this.context = context; } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.grid_view_fragment, container, false); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); loadGridView(view); findViews(view); implementEvents(); } //Bind all Views private void findViews(View view) { filterType = FilterType.NAME; searchViaRadioGroup = (RadioGroup) view.findViewById(R.id.search_via_radio_group); filterByRadioGroup = (RadioGroup) view.findViewById(R.id.filter_type_radio_group); searchEditText = (EditText) view.findViewById(R.id.search_text); searchViaLabel = (TextView) view.findViewById(R.id.search_via_label); filterByLabel = (TextView) view.findViewById(R.id.filter_by_label); } private void loadGridView(View view) { GridView gridView = (GridView) view.findViewById(R.id.grid_view); arrayList = GetUserModelData.getUserModelData(); adapter = new GridListAdapter(context, arrayList, false); gridView.setAdapter(adapter); } private void implementEvents() { filterByRadioGroup.setOnCheckedChangeListener(this); searchViaRadioGroup.setOnCheckedChangeListener(this); searchViaLabel.setOnClickListener(this); filterByLabel.setOnClickListener(this); searchEditText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { //On text changed in Edit text start filtering the list adapter.filter(filterType, charSequence.toString(), isSearchWithPrefix); } @Override public void afterTextChanged(Editable editable) { } }); } @Override public void onCheckedChanged(RadioGroup radioGroup, int checkedId) { int pos = radioGroup.indexOfChild(radioGroup.findViewById(checkedId));//get the checked position of radio button switch (radioGroup.getId()) { case R.id.search_via_radio_group: switch (pos) { case 0: filterType = FilterType.NAME;//Change filter type to Name if pos = 0 break; case 1: filterType = FilterType.NUMBER;//Change filter type to Number if pos = 1 break; case 2: filterType = FilterType.EMAIL;//Change filter type to Email if pos = 2 break; } break; case R.id.filter_type_radio_group: switch (pos) { case 0: isSearchWithPrefix = false;//Set boolean value to false break; case 1: isSearchWithPrefix = true;//Set boolean value to true break; } break; } } @Override public void onClick(View view) { switch (view.getId()) { case R.id.search_via_label: //show hide the radio group if (searchViaRadioGroup.isShown()) { searchViaLabel.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.up_dropdown, 0); searchViaRadioGroup.setVisibility(View.GONE); } else { searchViaLabel.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.down_dropdown, 0); searchViaRadioGroup.setVisibility(View.VISIBLE); } break; case R.id.filter_by_label: //show hide the radio group if (filterByRadioGroup.isShown()) { filterByLabel.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.up_dropdown, 0); filterByRadioGroup.setVisibility(View.GONE); } else { filterByLabel.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.down_dropdown, 0); filterByRadioGroup.setVisibility(View.VISIBLE); } break; } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
package com.listsearch_demo.main; import android.content.Context; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; import android.widget.RadioGroup; import android.widget.TextView; import com.listsearch_demo.R; import com.listsearch_demo.adapter.RecyclerViewAdapter; import com.listsearch_demo.helper.FilterType; import com.listsearch_demo.helper.GetUserModelData; import com.listsearch_demo.helper.UserModel; import java.util.ArrayList; /** * Created by sonu on 08/02/17. */ public class RecyclerViewFragment extends Fragment implements RadioGroup.OnCheckedChangeListener, View.OnClickListener { private Context context; private RecyclerViewAdapter adapter; private ArrayList<UserModel> arrayList; private RadioGroup searchViaRadioGroup, filterByRadioGroup; private EditText searchEditText; private TextView searchViaLabel, filterByLabel; /* Filter Type to identify the type of Filter */ private FilterType filterType; /* boolean variable for Filtering */ private boolean isSearchWithPrefix = false; public RecyclerViewFragment() { } @Override public void onAttach(Context context) { super.onAttach(context); this.context = context; } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.recycler_view_fragment, container, false); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); findViews(view); populateRecyclerView(view); implementEvents(); } //Bind all Views private void findViews(View view) { filterType = FilterType.NAME; searchViaRadioGroup = (RadioGroup) view.findViewById(R.id.search_via_radio_group); filterByRadioGroup = (RadioGroup) view.findViewById(R.id.filter_type_radio_group); searchEditText = (EditText) view.findViewById(R.id.search_text); searchViaLabel = (TextView) view.findViewById(R.id.search_via_label); filterByLabel = (TextView) view.findViewById(R.id.filter_by_label); } //Populate recycler view private void populateRecyclerView(View view) { RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view); recyclerView.setHasFixedSize(true); LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context); recyclerView.setLayoutManager(linearLayoutManager); arrayList = GetUserModelData.getUserModelData(); adapter = new RecyclerViewAdapter(context, arrayList); recyclerView.setAdapter(adapter); } private void implementEvents() { filterByRadioGroup.setOnCheckedChangeListener(this); searchViaRadioGroup.setOnCheckedChangeListener(this); searchViaLabel.setOnClickListener(this); filterByLabel.setOnClickListener(this); searchEditText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { //On text changed in Edit text start filtering the list adapter.filter(filterType, charSequence.toString(), isSearchWithPrefix); } @Override public void afterTextChanged(Editable editable) { } }); } @Override public void onCheckedChanged(RadioGroup radioGroup, int checkedId) { int pos = radioGroup.indexOfChild(radioGroup.findViewById(checkedId));//get the checked position of radio button switch (radioGroup.getId()) { case R.id.search_via_radio_group: switch (pos) { case 0: filterType = FilterType.NAME;//Change filter type to Name if pos = 0 break; case 1: filterType = FilterType.NUMBER;//Change filter type to Number if pos = 1 break; case 2: filterType = FilterType.EMAIL;//Change filter type to Email if pos = 2 break; } break; case R.id.filter_type_radio_group: switch (pos) { case 0: isSearchWithPrefix = false;//Set boolean value to false break; case 1: isSearchWithPrefix = true;//Set boolean value to true break; } break; } } @Override public void onClick(View view) { switch (view.getId()) { case R.id.search_via_label: //show hide the radio group if (searchViaRadioGroup.isShown()) { searchViaLabel.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.up_dropdown, 0); searchViaRadioGroup.setVisibility(View.GONE); } else { searchViaLabel.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.down_dropdown, 0); searchViaRadioGroup.setVisibility(View.VISIBLE); } break; case R.id.filter_by_label: //show hide the radio group if (filterByRadioGroup.isShown()) { filterByLabel.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.up_dropdown, 0); filterByRadioGroup.setVisibility(View.GONE); } else { filterByLabel.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.down_dropdown, 0); filterByRadioGroup.setVisibility(View.VISIBLE); } break; } } } |
In all the above fragment classes the common code to do filtering is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
searchEditText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { //On text changed in Edit text start filtering the list adapter.filter(filterType, charSequence.toString(), isSearchWithPrefix); } @Override public void afterTextChanged(Editable editable) { } }); |
Here we need to call the filter method created in adapter class by passing the filter query.
8. Now after creating all fragment classes we have to create Adapters for ListView, GridView and RecyclerView.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
package com.listsearch_demo.adapter; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import com.listsearch_demo.R; import com.listsearch_demo.helper.FilterType; import com.listsearch_demo.helper.UserModel; import java.util.ArrayList; import java.util.Locale; /** * Created by sonu on 08/02/17. */ public class GridListAdapter extends BaseAdapter { private Context context; private ArrayList<UserModel> arrayList; private LayoutInflater inflater; private boolean isListView; private ArrayList<UserModel> filterArrayList;//duplicate list for filtering public GridListAdapter(Context context, ArrayList<UserModel> arrayList, boolean isListView) { this.context = context; this.arrayList = arrayList; this.isListView = isListView; inflater = LayoutInflater.from(context); this.filterArrayList = new ArrayList<>();//initiate filter list this.filterArrayList.addAll(arrayList);//add all items of array list to filter list } @Override public int getCount() { return arrayList.size(); } @Override public Object getItem(int i) { return arrayList.get(i); } @Override public long getItemId(int i) { return i; } @Override public View getView(final int i, View view, ViewGroup viewGroup) { ViewHolder viewHolder; if (view == null) { viewHolder = new ViewHolder(); //inflate the layout on basis of boolean if (isListView) view = inflater.inflate(R.layout.list_custom_row_layout, viewGroup, false); else view = inflater.inflate(R.layout.grid_custom_row_layout, viewGroup, false); viewHolder.name = (TextView) view.findViewById(R.id.name_label); viewHolder.number = (TextView) view.findViewById(R.id.number_label); viewHolder.emailID = (TextView) view.findViewById(R.id.email_label); view.setTag(viewHolder); } else viewHolder = (ViewHolder) view.getTag(); UserModel model = arrayList.get(i); viewHolder.name.setText(model.getName()); viewHolder.number.setText(model.getNumber()); viewHolder.emailID.setText(model.getEmailID()); return view; } private class ViewHolder { private TextView name, number, emailID; } // Filter Class to filter data public void filter(FilterType filterType, String charText, boolean isSearchWithPrefix) { //If Filter type is NAME and EMAIL then only do lowercase, else in case of NUMBER no need to do lowercase because of number format if (filterType == FilterType.NAME || filterType == FilterType.EMAIL) charText = charText.toLowerCase(Locale.getDefault()); arrayList.clear();//Clear the main ArrayList //If search query is null or length is 0 then add all filterList items back to arrayList if (charText.length() == 0) { arrayList.addAll(filterArrayList); } else { //Else if search query is not null do a loop to all filterList items for (UserModel model : filterArrayList) { //Now check the type of search filter switch (filterType) { case NAME: if (isSearchWithPrefix) { //if STARTS WITH radio button is selected then it will match the exact NAME which match with search query if (model.getName().toLowerCase(Locale.getDefault()).startsWith(charText)) arrayList.add(model); } else { //if CONTAINS radio button is selected then it will match the NAME wherever it contains search query if (model.getName().toLowerCase(Locale.getDefault()).contains(charText)) arrayList.add(model); } break; case EMAIL: if (isSearchWithPrefix) { //if STARTS WITH radio button is selected then it will match the exact EMAIL which match with search query if (model.getEmailID().toLowerCase(Locale.getDefault()).startsWith(charText)) arrayList.add(model); } else { //if CONTAINS radio button is selected then it will match the EMAIL wherever it contains search query if (model.getEmailID().toLowerCase(Locale.getDefault()).contains(charText)) arrayList.add(model); } break; case NUMBER: if (isSearchWithPrefix) { //if STARTS WITH radio button is selected then it will match the exact NUMBER which match with search query if (model.getNumber().startsWith(charText)) arrayList.add(model); } else { //if CONTAINS radio button is selected then it will match the NUMBER wherever it contains search query if (model.getNumber().contains(charText)) arrayList.add(model); } break; } } } notifyDataSetChanged(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
package com.listsearch_demo.adapter; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.listsearch_demo.R; import com.listsearch_demo.helper.FilterType; import com.listsearch_demo.helper.UserModel; import java.util.ArrayList; import java.util.Locale; /** * Created by sonu on 19/09/16. */ public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.RecyclerViewHolder> { static class RecyclerViewHolder extends RecyclerView.ViewHolder { private TextView name, number, emailID; RecyclerViewHolder(View view) { super(view); name = (TextView) view.findViewById(R.id.name_label); number = (TextView) view.findViewById(R.id.number_label); emailID = (TextView) view.findViewById(R.id.email_label); } } private ArrayList<UserModel> arrayList; private ArrayList<UserModel> filterArrayList;//duplicate list for filtering private Context context; public RecyclerViewAdapter(Context context, ArrayList<UserModel> arrayList) { this.arrayList = arrayList; this.context = context; this.filterArrayList = new ArrayList<>();//initiate filter list this.filterArrayList.addAll(arrayList);//add all items of array list to filter list } @Override public RecyclerViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_custom_row_layout, viewGroup, false); return new RecyclerViewHolder(v); } @Override public void onBindViewHolder(final RecyclerViewHolder holder, final int i) { UserModel model = arrayList.get(i); holder.name.setText(model.getName()); holder.number.setText(model.getNumber()); holder.emailID.setText(model.getEmailID()); } @Override public int getItemCount() { return (null != arrayList ? arrayList.size() : 0); } // Filter Class to filter data public void filter(FilterType filterType, String charText, boolean isSearchWithPrefix) { //If Filter type is NAME and EMAIL then only do lowercase, else in case of NUMBER no need to do lowercase because of number format if (filterType == FilterType.NAME || filterType == FilterType.EMAIL) charText = charText.toLowerCase(Locale.getDefault()); arrayList.clear();//Clear the main ArrayList //If search query is null or length is 0 then add all filterList items back to arrayList if (charText.length() == 0) { arrayList.addAll(filterArrayList); } else { //Else if search query is not null do a loop to all filterList items for (UserModel model : filterArrayList) { //Now check the type of search filter switch (filterType) { case NAME: if (isSearchWithPrefix) { //if STARTS WITH radio button is selected then it will match the exact NAME which match with search query if (model.getName().toLowerCase(Locale.getDefault()).startsWith(charText)) arrayList.add(model); } else { //if CONTAINS radio button is selected then it will match the NAME wherever it contains search query if (model.getName().toLowerCase(Locale.getDefault()).contains(charText)) arrayList.add(model); } break; case EMAIL: if (isSearchWithPrefix) { //if STARTS WITH radio button is selected then it will match the exact EMAIL which match with search query if (model.getEmailID().toLowerCase(Locale.getDefault()).startsWith(charText)) arrayList.add(model); } else { //if CONTAINS radio button is selected then it will match the EMAIL wherever it contains search query if (model.getEmailID().toLowerCase(Locale.getDefault()).contains(charText)) arrayList.add(model); } break; case NUMBER: if (isSearchWithPrefix) { //if STARTS WITH radio button is selected then it will match the exact NUMBER which match with search query if (model.getNumber().startsWith(charText)) arrayList.add(model); } else { //if CONTAINS radio button is selected then it will match the NUMBER wherever it contains search query if (model.getNumber().contains(charText)) arrayList.add(model); } break; } } } notifyDataSetChanged(); } } |
In both the above adapter the common code to filter is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
// Filter Class to filter data public void filter(FilterType filterType, String charText, boolean isSearchWithPrefix) { //If Filter type is NAME and EMAIL then only do lowercase, else in case of NUMBER no need to do lowercase because of number format if (filterType == FilterType.NAME || filterType == FilterType.EMAIL) charText = charText.toLowerCase(Locale.getDefault()); arrayList.clear();//Clear the main ArrayList //If search query is null or length is 0 then add all filterList items back to arrayList if (charText.length() == 0) { arrayList.addAll(filterArrayList); } else { //Else if search query is not null do a loop to all filterList items for (UserModel model : filterArrayList) { //Now check the type of search filter switch (filterType) { case NAME: if (isSearchWithPrefix) { //if STARTS WITH radio button is selected then it will match the exact NAME which match with search query if (model.getName().toLowerCase(Locale.getDefault()).startsWith(charText)) arrayList.add(model); } else { //if CONTAINS radio button is selected then it will match the NAME wherever it contains search query if (model.getName().toLowerCase(Locale.getDefault()).contains(charText)) arrayList.add(model); } break; case EMAIL: if (isSearchWithPrefix) { //if STARTS WITH radio button is selected then it will match the exact EMAIL which match with search query if (model.getEmailID().toLowerCase(Locale.getDefault()).startsWith(charText)) arrayList.add(model); } else { //if CONTAINS radio button is selected then it will match the EMAIL wherever it contains search query if (model.getEmailID().toLowerCase(Locale.getDefault()).contains(charText)) arrayList.add(model); } break; case NUMBER: if (isSearchWithPrefix) { //if STARTS WITH radio button is selected then it will match the exact NUMBER which match with search query if (model.getNumber().startsWith(charText)) arrayList.add(model); } else { //if CONTAINS radio button is selected then it will match the NUMBER wherever it contains search query if (model.getNumber().contains(charText)) arrayList.add(model); } break; } } } notifyDataSetChanged(); } |
9. Some helper java classes that we need in this article are:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
package com.listsearch_demo.helper; /** * Created by sonu on 14/02/17. */ /* POJO Class of UserModel */ public class UserModel { private String name, number, emailID; public UserModel(String name, String number, String emailID) { this.name = name; this.number = number; this.emailID = emailID; } public String getName() { return name; } public String getNumber() { return number; } public String getEmailID() { return emailID; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
package com.listsearch_demo.helper; import java.util.ArrayList; /** * Created by sonu on 14/02/17. */ /* Get ArrayList of UserModel type */ public class GetUserModelData { public static ArrayList<UserModel> getUserModelData() { ArrayList<UserModel> arrayList = new ArrayList<>(); return arrayList; } } |
1 2 3 4 5 6 7 8 9 10 11 |
package com.listsearch_demo.helper; /** * Created by sonu on 14/02/17. */ /* Enum Class to identify the type of Filter/Search type */ public enum FilterType { NAME, NUMBER, EMAIL; } |
10. Finally all things done. Now you can also make filterable ListView.
Thanks. 🙂
Subscribe to us and get the latest news.
1 Comment
Putri Ananta Natasha
Wednesday, December 23rd, 2020Waw, its work
thanks