Hello Friends, we have already seen how to make multiple filters and sorting in android before but today we are going to see multiple filters and sorting with Firebase Database in Android. I am sharing this because one of our visitor asked for. Firebase currently offers two types of database solution Realtime Database and Cloud Firestore. We are going to use Cloud Firestore here instead of Realtime Database because it is newest database and faster than Realtime Database. We are going to use same logic and method to filter and sort the items as Cloud Firestore supports limited compound queries. And if you are new to firebase then you can also check Firebase Cloud Firestore Database Example in Android.
So, here is the code
build.gradle (Project Level)
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 |
// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.6.1' classpath 'com.google.gms:google-services:4.3.3'//added // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { google() jcenter() } } task clean(type: Delete) { delete rootProject.buildDir } |
build.gradle (Module Level)
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 |
apply plugin: 'com.android.application' apply plugin: 'com.google.gms.google-services'//added android { compileSdkVersion 28 defaultConfig { applicationId "com.zatackcoder.filtersortfirebasedatabaseexample" minSdkVersion 16 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" //to fix Cannot fit requested classes in a single dex file error multiDexEnabled true //added } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' implementation 'com.google.firebase:firebase-auth:19.2.0' //added implementation 'com.google.firebase:firebase-firestore:21.4.1' //added implementation 'androidx.recyclerview:recyclerview:1.1.0' //added //Cannot fit requested classes in a single dex file implementation 'com.android.support:multidex:1.0.3' //added } |
MainActivity.java
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 |
package com.zatackcoder.filtersortfirebasedatabaseexample; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button addItemB = findViewById(R.id.addItemB); Button viewItemsB = findViewById(R.id.viewItemsB); addItemB.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(MainActivity.this, AddItemActivity.class)); } }); viewItemsB.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(MainActivity.this, ViewItemsActivity.class)); } }); } } |
activity_main.xml
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 |
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <Button android:id="@+id/addItemB" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Add Item" /> <Button android:id="@+id/viewItemsB" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="View Items" /> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout> |
Item.java
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 |
package com.zatackcoder.filtersortfirebasedatabaseexample.classes; import java.util.Comparator; public class Item { private String name; private String color; private Integer size; private Double price; public static final Comparator<Item> nameComparator = new Comparator<Item>() { @Override public int compare(Item o1, Item o2) { return o1.getName().compareTo(o2.getName()); } }; public static final Comparator<Item> sizeComparator = new Comparator<Item>() { @Override public int compare(Item o1, Item o2) { return o1.getSize() - o2.getSize(); } }; public static final Comparator<Item> priceComparator = new Comparator<Item>() { @Override public int compare(Item o1, Item o2) { return (int) (o1.getPrice() - o2.getPrice()); } }; /** * required to deserialize from firebase database */ public Item() {} public Item(String name, String color, Integer size, Double price) { this.name = name; this.color = color; this.size = size; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public Integer getSize() { return size; } //customised setter to overcome deserialize object error //java.lang.RuntimeException: Could not deserialize object. Failed to convert a value of type java.lang.String to int public void setSize(Object size) { try { this.size = Integer.parseInt(size.toString()); } catch (Exception e) { this.size = 0; } } public Double getPrice() { return price; } //customised setter to overcome deserialize object error //java.lang.RuntimeException: Could not deserialize object. Failed to convert a value of type java.lang.String to double public void setPrice(Object price) { try { this.price = Double.parseDouble(price.toString()); } catch (Exception e) { this.price = 0.00; } } } |
AddItemActivity.java
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 |
package com.zatackcoder.filtersortfirebasedatabaseexample; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; import com.google.firebase.firestore.DocumentReference; import com.google.firebase.firestore.FirebaseFirestore; import com.zatackcoder.filtersortfirebasedatabaseexample.classes.Item; public class AddItemActivity extends AppCompatActivity { private FirebaseFirestore db; private EditText nameET; private EditText colorET; private EditText sizeET; private EditText priceET; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_add_item); // Access a Cloud Firestore instance from your Activity db = FirebaseFirestore.getInstance(); initControls(); } private void initControls() { nameET = findViewById(R.id.nameET); colorET = findViewById(R.id.colorET); sizeET = findViewById(R.id.sizeET); priceET = findViewById(R.id.priceET); Button saveB = findViewById(R.id.saveB); saveB.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // Add a new document with a generated ID db.collection("items") .add(new Item(nameET.getText().toString(), colorET.getText().toString(), Integer.parseInt(sizeET.getText().toString()), Double.parseDouble(priceET.getText().toString()))) .addOnSuccessListener(new OnSuccessListener<DocumentReference>() { @Override public void onSuccess(DocumentReference documentReference) { nameET.setText(""); colorET.setText(""); sizeET.setText(""); priceET.setText(""); Toast.makeText(getApplicationContext(), "Item Added with ID: " + documentReference.getId(), Toast.LENGTH_LONG).show(); } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Toast.makeText(getApplicationContext(), "Error Adding Item! - " + e, Toast.LENGTH_LONG).show(); } }); } }); } } |
activity_add_item.xml
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 |
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".AddItemActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Add Item" android:textSize="18sp" android:textStyle="bold" /> <EditText android:id="@+id/nameET" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="50dp" android:ems="10" android:hint="Name" /> <EditText android:id="@+id/colorET" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="10" android:hint="Color" /> <EditText android:id="@+id/sizeET" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="10" android:hint="Size" /> <EditText android:id="@+id/priceET" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="10" android:hint="Price" /> <Button android:id="@+id/saveB" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="50dp" android:text="Save" /> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout> |
ItemAdapter.java
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 |
package com.zatackcoder.filtersortfirebasedatabaseexample.adaptors; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.zatackcoder.filtersortfirebasedatabaseexample.R; import com.zatackcoder.filtersortfirebasedatabaseexample.classes.Item; import java.util.List; public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ItemViewHolder> { private final Context context; private final List<Item> items; public ItemAdapter(Context context, List<Item> items) { this.context = context; this.items = items; } @NonNull @Override public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int position) { View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item, viewGroup, false); return new ItemViewHolder(view); } @Override public void onBindViewHolder(@NonNull final ItemViewHolder itemViewHolder, final int position) { itemViewHolder.container.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String message = "You clicked on " + items.get(position).getName() + " - color:" + items.get(position).getColor() + " | size:" + items.get(position).getSize() + " | price:" + items.get(position).getPrice(); Toast.makeText(context, message, Toast.LENGTH_LONG).show(); } }); itemViewHolder.name.setText(items.get(position).getName()); itemViewHolder.color.setText("Color: " + items.get(position).getColor()); itemViewHolder.size.setText("Size: " + items.get(position).getSize()); itemViewHolder.price.setText("Price: " + items.get(position).getPrice()); } @Override public int getItemCount() { return items.size(); } public static class ItemViewHolder extends RecyclerView.ViewHolder { final View container; final TextView name; final TextView color; final TextView size; final TextView price; ItemViewHolder(View view) { super(view); container = view; name = view.findViewById(R.id.name); color = view.findViewById(R.id.color); size = view.findViewById(R.id.size); price = view.findViewById(R.id.price); } } } |
list_item.xml
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 |
<?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="wrap_content" android:layout_margin="5dp" android:background="#ffffff" android:clickable="true" android:orientation="vertical" android:focusable="true"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?android:attr/selectableItemBackground" android:orientation="vertical" android:padding="5dp"> <TextView android:id="@+id/name" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Name" android:textFontWeight="bold" android:textSize="15dp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/color" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Color: Red" android:textSize="12dp" /> <View android:layout_width="1dp" android:layout_height="match_parent" android:layout_margin="5dp" android:background="#ADABAB" /> <TextView android:id="@+id/size" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Size: 10" android:textSize="12dp" /> <View android:layout_width="1dp" android:layout_height="match_parent" android:layout_margin="5dp" android:background="#ADABAB" /> <TextView android:id="@+id/price" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Price: 100" android:textSize="12dp" /> </LinearLayout> </LinearLayout> </LinearLayout> |
ViewItemsActivity.java
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 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
package com.zatackcoder.filtersortfirebasedatabaseexample; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.RadioButton; import android.widget.RadioGroup; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.Task; import com.google.firebase.firestore.FirebaseFirestore; import com.google.firebase.firestore.Query; import com.google.firebase.firestore.QuerySnapshot; import com.zatackcoder.filtersortfirebasedatabaseexample.adaptors.ItemAdapter; import com.zatackcoder.filtersortfirebasedatabaseexample.classes.Filter; import com.zatackcoder.filtersortfirebasedatabaseexample.classes.Item; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class ViewItemsActivity extends AppCompatActivity { private Query query; private List<Item> items = new ArrayList<>(); private RecyclerView mRecyclerView; private ItemAdapter mAdapter; private ProgressBar loadPB; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_view_items); FirebaseFirestore db = FirebaseFirestore.getInstance(); query = db.collection("items"); initControls(); } private void initControls() { mRecyclerView = findViewById(R.id.recycler_view); mRecyclerView.setHasFixedSize(true); RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this); mRecyclerView.setLayoutManager(mLayoutManager); mAdapter = new ItemAdapter(getApplicationContext(), items); mRecyclerView.setAdapter(mAdapter); RadioButton rb = findViewById(R.id.sortByName); switch (Preferences.ORDER_BY) { case "name" : rb = findViewById(R.id.sortByName); break; case "size" : rb = findViewById(R.id.sortBySize); break; case "price" : rb = findViewById(R.id.sortByPrice); break; } rb.setChecked(true); loadPB = findViewById(R.id.loadPB); loadPB.setVisibility(View.VISIBLE); query.orderBy(Preferences.ORDER_BY).get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() { @Override public void onComplete(@NonNull Task<QuerySnapshot> task) { items = task.getResult().toObjects(Item.class); if(!Preferences.filters.isEmpty()) { ArrayList<Item> filteredItems = new ArrayList<>(); List<String> colors = Preferences.filters.get(Filter.INDEX_COLOR).getSelected(); List<String> sizes = Preferences.filters.get(Filter.INDEX_SIZE).getSelected(); List<String> prices = Preferences.filters.get(Filter.INDEX_PRICE).getSelected(); for (Item item : items) { boolean colorMatched = true; if (colors.size() > 0 && !colors.contains(item.getColor())) { colorMatched = false; } boolean sizeMatched = true; if (sizes.size() > 0 && !sizes.contains(item.getSize().toString())) { sizeMatched = false; } boolean priceMatched = true; if (prices.size() > 0 && !priceContains(prices, item.getPrice())) { priceMatched = false; } if (colorMatched && sizeMatched && priceMatched) { filteredItems.add(item); } } items = filteredItems; } mAdapter = new ItemAdapter(getApplicationContext(), items); mRecyclerView.setAdapter(mAdapter); loadPB.setVisibility(View.GONE); } }); final LinearLayout sortContainerBackLL = findViewById(R.id.sortContainerBackLL); final LinearLayout sortContainerLL = findViewById(R.id.sortContainerLL); //sortContainerLL.setTranslationY(-sortContainerLL.getHeight()); sortContainerBackLL.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { sortContainerLL.animate() .translationY(-sortContainerLL.getHeight()) .setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { sortContainerLL.animate().setListener(null); sortContainerBackLL.setVisibility(View.GONE); } }); } }); Button sortB = findViewById(R.id.sortB); sortB.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { sortContainerBackLL.setVisibility(View.VISIBLE); sortContainerLL.animate().translationY(0); } }); Button filterB = findViewById(R.id.filterB); filterB.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(ViewItemsActivity.this, FilterActivity.class)); } }); RadioGroup sortRG = findViewById(R.id.sortRG); sortRG.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { Item[] itemsArr = new Item[items.size()]; itemsArr = items.toArray(itemsArr); switch (checkedId) { case R.id.sortByName: Arrays.sort(itemsArr, Item.nameComparator); Preferences.ORDER_BY = "name"; break; case R.id.sortBySize: Arrays.sort(itemsArr, Item.sizeComparator); Preferences.ORDER_BY = "size"; break; case R.id.sortByPrice: Arrays.sort(itemsArr, Item.priceComparator); Preferences.ORDER_BY = "price"; break; } items = Arrays.asList(itemsArr); mAdapter = new ItemAdapter(getApplicationContext(), items); mRecyclerView.setAdapter(mAdapter); sortContainerLL.animate() .translationY(-sortContainerLL.getHeight()) .setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { sortContainerLL.animate().setListener(null); sortContainerBackLL.setVisibility(View.GONE); } }); } }); } private boolean priceContains(List<String> prices, Double price) { boolean flag = false; for (String p : prices) { String[] tmpPrices = p.split("-"); if (price >= Double.parseDouble(tmpPrices[0]) && price <= Double.parseDouble(tmpPrices[1])) { flag = true; break; } } return flag; } } |
activity_view_items.xml
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"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ViewItemsActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0" android:orientation="horizontal"> <Button android:id="@+id/sortB" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:drawableLeft="@drawable/ic_sort_black_24dp" android:text="Sort" /> <Button android:id="@+id/filterB" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:drawableLeft="@drawable/ic_filter_list_black_24dp" android:text="Filter" /> </LinearLayout> </LinearLayout> <LinearLayout android:id="@+id/sortContainerBackLL" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#C4000000" android:orientation="vertical" android:visibility="gone" tools:ignore="MissingConstraints" tools:layout_editor_absoluteX="0dp" tools:layout_editor_absoluteY="0dp"> <LinearLayout android:id="@+id/sortContainerLL" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#FFFFFFFF" android:orientation="vertical" tools:ignore="MissingConstraints" tools:layout_editor_absoluteX="0dp" tools:layout_editor_absoluteY="0dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:text="SORT BY" android:textSize="15dp" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#929191" /> <RadioGroup android:id="@+id/sortRG" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp"> <RadioButton android:id="@+id/sortByName" android:layout_width="match_parent" android:layout_height="wrap_content" android:layoutDirection="rtl" android:text="Name" android:checked="true"/> <RadioButton android:id="@+id/sortBySize" android:layout_width="match_parent" android:layout_height="wrap_content" android:layoutDirection="rtl" android:text="Size" /> <RadioButton android:id="@+id/sortByPrice" android:layout_width="match_parent" android:layout_height="wrap_content" android:layoutDirection="rtl" android:text="Price" /> </RadioGroup> </LinearLayout> </LinearLayout> <ProgressBar android:id="@+id/loadPB" style="?android:attr/progressBarStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="gone" android:progress="-1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> |
Filter.java
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 |
package com.zatackcoder.filtersortfirebasedatabaseexample.classes; import java.util.List; public class Filter { public static final Integer INDEX_COLOR = 0; public static final Integer INDEX_SIZE = 1; public static final Integer INDEX_PRICE = 2; private String name; private List<String> values; private List<String> selected; public Filter(String name, List<String> values, List<String> selected) { this.name = name; this.values = values; this.selected = selected; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getValues() { return values; } public void setValues(List<String> values) { this.values = values; } public List<String> getSelected() { return selected; } public void setSelected(List<String> selected) { this.selected = selected; } } |
FilterActivity.java
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 |
package com.zatackcoder.filtersortfirebasedatabaseexample; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.zatackcoder.filtersortfirebasedatabaseexample.adaptors.FilterAdapter; import com.zatackcoder.filtersortfirebasedatabaseexample.classes.Filter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class FilterActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_filter); initControls(); } private void initControls() { RecyclerView filterRV = findViewById(R.id.filterRV); RecyclerView filterValuesRV = findViewById(R.id.filterValuesRV); filterRV.setLayoutManager(new LinearLayoutManager(this)); filterValuesRV.setLayoutManager(new LinearLayoutManager(this)); List<String> colors = Arrays.asList("Red", "Green", "Blue", "White", "Yellow"); if (!Preferences.filters.containsKey(Filter.INDEX_COLOR)) { Preferences.filters.put(Filter.INDEX_COLOR, new Filter("Color", colors, new ArrayList())); } List<String> sizes = Arrays.asList("10", "12", "14", "16", "18", "20", "30", "40"); if (!Preferences.filters.containsKey(Filter.INDEX_SIZE)) { Preferences.filters.put(Filter.INDEX_SIZE, new Filter("Size", sizes, new ArrayList())); } List<String> prices = Arrays.asList("0-100", "101-200", "201-300"); if (!Preferences.filters.containsKey(Filter.INDEX_PRICE)) { Preferences.filters.put(Filter.INDEX_PRICE, new Filter("Price", prices, new ArrayList())); } FilterAdapter filterAdapter = new FilterAdapter(Preferences.filters, filterValuesRV); filterRV.setAdapter(filterAdapter); Button clearB = findViewById(R.id.clearB); clearB.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Preferences.filters.get(Filter.INDEX_COLOR).setSelected(new ArrayList()); Preferences.filters.get(Filter.INDEX_SIZE).setSelected(new ArrayList()); Preferences.filters.get(Filter.INDEX_PRICE).setSelected(new ArrayList()); startActivity(new Intent(FilterActivity.this, ViewItemsActivity.class)); finish(); } }); Button applyB = findViewById(R.id.applyB); applyB.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(FilterActivity.this, ViewItemsActivity.class)); finish(); } }); } } |
activity_filter.xml
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 |
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".FilterActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:orientation="horizontal"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/filterRV" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="0" android:background="#F2F2F2" /> <androidx.recyclerview.widget.RecyclerView android:id="@+id/filterValuesRV" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:background="#ffffff" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0" android:orientation="horizontal"> <Button android:id="@+id/clearB" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="Clear" /> <Button android:id="@+id/applyB" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:text="Apply" /> </LinearLayout> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout> |
FilterAdapter.java
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 |
package com.zatackcoder.filtersortfirebasedatabaseexample.adaptors; import android.graphics.Color; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.zatackcoder.filtersortfirebasedatabaseexample.R; import com.zatackcoder.filtersortfirebasedatabaseexample.classes.Filter; import java.util.HashMap; public class FilterAdapter extends RecyclerView.Adapter<FilterAdapter.MyViewHolder> { private final HashMap<Integer, Filter> filters; private final RecyclerView filterValuesRV; private int selectedPosition = 0; public FilterAdapter(HashMap<Integer, Filter> filters, RecyclerView filterValuesRV) { this.filters = filters; this.filterValuesRV = filterValuesRV; } @NonNull @Override public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int position) { View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.filter_item, viewGroup, false); return new MyViewHolder(view); } @Override public void onBindViewHolder(@NonNull final MyViewHolder myViewHolder, final int position) { myViewHolder.container.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { filterValuesRV.setAdapter(new FilterValuesAdapter(position)); selectedPosition = position; notifyDataSetChanged(); } }); filterValuesRV.setAdapter(new FilterValuesAdapter(selectedPosition)); myViewHolder.container.setBackgroundColor(selectedPosition == position ? Color.WHITE : Color.TRANSPARENT); myViewHolder.title.setText(filters.get(position).getName()); } @Override public int getItemCount() { return filters.size(); } public static class MyViewHolder extends RecyclerView.ViewHolder { final View container; final TextView title; MyViewHolder(View view) { super(view); container = view; title = view.findViewById(R.id.title); } } } |
filter_item.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?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="wrap_content" android:layout_marginLeft="5dp" android:layout_marginTop="5dp" android:layout_marginRight="0dp" android:layout_marginBottom="5dp" android:background="?android:attr/selectableItemBackground" android:clickable="true" android:focusable="true" android:orientation="vertical"> <TextView android:id="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:text="Color" android:textFontWeight="bold" android:textSize="15dp" /> </LinearLayout> |
FilterValuesAdapter.java
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 |
package com.zatackcoder.filtersortfirebasedatabaseexample.adaptors; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.zatackcoder.filtersortfirebasedatabaseexample.R; import com.zatackcoder.filtersortfirebasedatabaseexample.Preferences; import com.zatackcoder.filtersortfirebasedatabaseexample.classes.Filter; import java.util.List; public class FilterValuesAdapter extends RecyclerView.Adapter<FilterValuesAdapter.MyViewHolder> { private final Integer filterIndex; public FilterValuesAdapter(Integer filterIndex) { this.filterIndex = filterIndex; } @NonNull @Override public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int position) { View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.filter_value_item, viewGroup, false); return new MyViewHolder(view); } @Override public void onBindViewHolder(@NonNull final MyViewHolder myViewHolder, final int position) { final Filter tmpFilter = Preferences.filters.get(filterIndex); myViewHolder.value.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { List<String> selected = tmpFilter.getSelected(); if(myViewHolder.value.isChecked()) { selected.add(tmpFilter.getValues().get(position)); tmpFilter.setSelected(selected); } else { selected.remove(tmpFilter.getValues().get(position)); tmpFilter.setSelected(selected); } Preferences.filters.put(filterIndex, tmpFilter); } }); myViewHolder.value.setText(tmpFilter.getValues().get(position)); if(tmpFilter.getSelected().contains(tmpFilter.getValues().get(position))) { myViewHolder.value.setChecked(true); } } @Override public int getItemCount() { return Preferences.filters.get(filterIndex).getValues().size(); } public static class MyViewHolder extends RecyclerView.ViewHolder { final CheckBox value; MyViewHolder(View view) { super(view); value = view.findViewById(R.id.value); } } } |
filter_value_item.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?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="wrap_content" android:layout_margin="5dp" android:clickable="true" android:orientation="vertical" android:focusable="true"> <CheckBox android:id="@+id/value" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Red" android:textFontWeight="bold" android:textSize="15dp" /> </LinearLayout> |
Preferences.java
1 2 3 4 5 6 7 8 9 10 |
package com.zatackcoder.filtersortfirebasedatabaseexample; import com.zatackcoder.filtersortfirebasedatabaseexample.classes.Filter; import java.util.HashMap; public abstract class Preferences { public static final HashMap<Integer, Filter> filters = new HashMap<>(); public static String ORDER_BY = "name"; } |
Directory/Package Structure
Video
AndroidStudio Project Download
FilterSortFirebaseDatabaseExample AndroidStudio Project
Thanks for Stoping by
If you find this helpful then please do share
Comments