Dialog for sorting search results

This commit is contained in:
Clayton Wilson 2020-09-29 12:53:31 -04:00
parent 9d41a3078c
commit 550483a708
11 changed files with 310 additions and 34 deletions

View File

@ -10,20 +10,29 @@ import android.widget.ImageView;
import android.widget.ListView; import android.widget.ListView;
import android.widget.SearchView; import android.widget.SearchView;
import android.widget.Toast; import android.widget.Toast;
import com.example.listify.adapter.SearchResultsListAdapter; import com.example.listify.adapter.SearchResultsListAdapter;
import com.example.listify.model.Product; import com.example.listify.model.Product;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
public class SearchResults extends AppCompatActivity { public class SearchResults extends AppCompatActivity implements SortDialogFragment.OnSortingListener {
private ListView listView; private ListView listView;
private SearchResultsListAdapter searchResultsListAdapter; private SearchResultsListAdapter searchResultsListAdapter;
private List<Product> resultsProductList = new ArrayList<>(); private List<Product> resultsProductList = new ArrayList<>();
private List<Product> resultsProductListFiltered = new ArrayList<>(); private List<Product> resultsProductListSorted = new ArrayList<>();
private ArrayList<String> stores = new ArrayList<>();
private int storeSelection;
private int sortMode;
private boolean descending;
@Override
public void sendSort(int storeSelection, int sortMode, boolean descending) {
this.storeSelection = storeSelection;
this.sortMode = sortMode;
this.descending = descending;
sortResults();
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -63,12 +72,12 @@ public class SearchResults extends AppCompatActivity {
}); });
listView = (ListView) findViewById(R.id.search_results_list); listView = (ListView) findViewById(R.id.search_results_list);
searchResultsListAdapter = new SearchResultsListAdapter(this, resultsProductListFiltered); searchResultsListAdapter = new SearchResultsListAdapter(this, resultsProductListSorted);
listView.setAdapter(searchResultsListAdapter); listView.setAdapter(searchResultsListAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override @Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(SearchResults.this, resultsProductListFiltered.get(position).getItemName(), Toast.LENGTH_SHORT).show(); Toast.makeText(SearchResults.this, resultsProductListSorted.get(position).getItemName(), Toast.LENGTH_SHORT).show();
} }
}); });
@ -86,7 +95,27 @@ public class SearchResults extends AppCompatActivity {
} }
}); });
// Create a dialog for filtering and sorting search results
ImageButton sortButton = (ImageButton) findViewById(R.id.results_sort_button);
sortButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Sort the store list
stores.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
} }
});
SortDialogFragment sortDialog = new SortDialogFragment(storeSelection, stores, sortMode, descending);
sortDialog.show(getSupportFragmentManager(), "Sort");
}
});
}
// Override default phone back button to add animation // Override default phone back button to add animation
@Override @Override
@ -116,22 +145,38 @@ public class SearchResults extends AppCompatActivity {
resultsProductList.add(f); resultsProductList.add(f);
} }
// Add all results to the filtered list // Create a list of all stores in the results so the user can filter by store name
resultsProductListFiltered.addAll(resultsProductList); for (int i = 0; i < resultsProductList.size(); i++) {
if (!stores.contains(resultsProductList.get(i).getChainName())) {
stores.add(resultsProductList.get(i).getChainName());
}
}
// Add all results to the sorted list
resultsProductListSorted.addAll(resultsProductList);
// Apply selected sorting to the list
sortResults();
} }
// Sorts the search results // Sorts the search results
private void sortResults(int sortMode, boolean descending) { private void sortResults() {
// Sort Modes // Sort Modes
// 0 itemName // 0 default (no sorting)
// 1 price // 1 itemName
// 2 chainName // 2 price
// 3 upc // 3 chainName
// 4 upc
// Sort based on mode // Sort based on mode
switch (sortMode) { switch (this.sortMode) {
case 0: case 0:
resultsProductListFiltered.sort(new Comparator<Product>() { resultsProductListSorted.clear();
resultsProductListSorted.addAll(resultsProductList);
searchResultsListAdapter.notifyDataSetChanged();
return;
case 1:
resultsProductListSorted.sort(new Comparator<Product>() {
@Override @Override
public int compare(Product a, Product b) { public int compare(Product a, Product b) {
return a.getItemName().compareToIgnoreCase(b.getItemName()); return a.getItemName().compareToIgnoreCase(b.getItemName());
@ -140,17 +185,23 @@ public class SearchResults extends AppCompatActivity {
break; break;
// TODO: May need to change this depending on if price is stored as a string or a double // TODO: May need to change this depending on if price is stored as a string or a double
case 1: case 2:
resultsProductListFiltered.sort(new Comparator<Product>() { resultsProductListSorted.sort(new Comparator<Product>() {
@Override @Override
public int compare(Product a, Product b) { public int compare(Product a, Product b) {
return (int)(a.getPrice() - b.getPrice()); if (a.getPrice() - b.getPrice() > 0) {
return 1;
} else if (a.getPrice() - b.getPrice() < 0) {
return -1;
} else {
return 0;
}
} }
}); });
break; break;
case 2: case 3:
resultsProductListFiltered.sort(new Comparator<Product>() { resultsProductListSorted.sort(new Comparator<Product>() {
@Override @Override
public int compare(Product a, Product b) { public int compare(Product a, Product b) {
return a.getChainName().compareToIgnoreCase(b.getChainName()); return a.getChainName().compareToIgnoreCase(b.getChainName());
@ -158,8 +209,8 @@ public class SearchResults extends AppCompatActivity {
}); });
break; break;
case 3: case 4:
resultsProductListFiltered.sort(new Comparator<Product>() { resultsProductListSorted.sort(new Comparator<Product>() {
@Override @Override
public int compare(Product a, Product b) { public int compare(Product a, Product b) {
return a.getUpc().compareToIgnoreCase(b.getUpc()); return a.getUpc().compareToIgnoreCase(b.getUpc());
@ -168,12 +219,14 @@ public class SearchResults extends AppCompatActivity {
break; break;
} }
if (descending) { if (this.descending) {
for (int i = 0; i < resultsProductListFiltered.size() / 2; i++) { for (int i = 0; i < resultsProductListSorted.size() / 2; i++) {
Product temp = resultsProductListFiltered.get(i); Product temp = resultsProductListSorted.get(i);
resultsProductListFiltered.set(i, resultsProductListFiltered.get(resultsProductListFiltered.size() - i - 1)); resultsProductListSorted.set(i, resultsProductListSorted.get(resultsProductListSorted.size() - i - 1));
resultsProductListFiltered.set(resultsProductListFiltered.size() - i - 1, temp); resultsProductListSorted.set(resultsProductListSorted.size() - i - 1, temp);
} }
} }
searchResultsListAdapter.notifyDataSetChanged();
} }
} }

View File

@ -0,0 +1,124 @@
package com.example.listify;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.Spinner;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import java.util.ArrayList;
public class SortDialogFragment extends DialogFragment {
public interface OnSortingListener {
void sendSort(int storeSelection, int sortMode, boolean descending);
}
public OnSortingListener onSortingListener;
private int storeSelection;
private int sortMode;
private boolean descending;
private ArrayList<String> stores;
public SortDialogFragment(int storeSelection, ArrayList<String> stores, int sortMode, boolean descending) {
this.storeSelection = storeSelection;
this.stores = stores;
this.sortMode = sortMode;
this.descending = descending;
}
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
LayoutInflater inflater = requireActivity().getLayoutInflater();
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
View root = inflater.inflate(R.layout.dialog_sort, null);
builder.setView(root)
// Add action buttons
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
onSortingListener.sendSort(storeSelection, sortMode, descending);
}
})
.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
SortDialogFragment.this.getDialog().cancel();
}
});
Spinner storeDropdown = (Spinner) root.findViewById(R.id.sort_store_dropdown);
String[] storeChoices = new String[stores.size() + 1];
storeChoices[0] = "All";
for (int i = 1; i < stores.size() + 1; i++) {
storeChoices[i] = stores.get(i - 1);
}
ArrayAdapter<String> storeAdapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_dropdown_item, storeChoices);
storeDropdown.setAdapter(storeAdapter);
storeDropdown.setSelection(this.storeSelection);
storeDropdown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
storeSelection = position;
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
Spinner sortDropdown = (Spinner) root.findViewById(R.id.sort_mode_dropdown);
String[] items = new String[] {"<Default>", "Name", "Price", "Store"};
ArrayAdapter<String> adapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_dropdown_item, items);
sortDropdown.setAdapter(adapter);
sortDropdown.setSelection(this.sortMode);
sortDropdown.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
sortMode = position;
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
ImageButton sortDirectionButton = root.findViewById(R.id.sort_direction_button);
sortDirectionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (descending) {
descending = false;
} else {
descending = true;
}
}
});
return builder.create();
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
try {
onSortingListener = (OnSortingListener) getActivity();
} catch (ClassCastException e) {
Log.e("SortDialogFragment", "onAttach: ClassCastException: " + e.getMessage());
}
}
}

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M7,10l5,5 5,-5z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M10,18h4v-2h-4v2zM3,6v2h18L21,6L3,6zM6,13h12v-2L6,11v2z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="28dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24"
android:width="28dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M3,18h6v-2L3,16v2zM3,6v2h18L21,6L3,6zM3,13h12v-2L3,11v2z"/>
</vector>

View File

@ -36,10 +36,17 @@
> >
</SearchView> </SearchView>
<ImageButton
android:id="@+id/results_sort_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentDescription="@string/sort_button_desc"
android:background="@null"
app:srcCompat="@drawable/ic_baseline_sort_28" />
</androidx.appcompat.widget.Toolbar> </androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/content_search_results" />\ <include layout="@layout/content_search_results" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -23,7 +23,7 @@
android:layout_gravity="end" android:layout_gravity="end"
android:layout_marginEnd="5dp" android:layout_marginEnd="5dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:srcCompat="@android:drawable/ic_menu_search" app:srcCompat="@drawable/ic_baseline_search_28"
android:contentDescription="@string/search_button_desc" android:contentDescription="@string/search_button_desc"
android:background="@null"/> android:background="@null"/>
</androidx.appcompat.widget.Toolbar> </androidx.appcompat.widget.Toolbar>

View File

@ -0,0 +1,61 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<!-- <ImageView-->
<!-- android:src="@drawable/ic_baseline_filter_list_28"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="64dp"-->
<!-- android:scaleType="center"-->
<!-- android:background="#FFFFBB33"-->
<!-- android:contentDescription="@string/app_name" />-->
<!-- <EditText-->
<!-- android:id="@+id/username"-->
<!-- android:inputType="textEmailAddress"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginTop="16dp"-->
<!-- android:layout_marginLeft="4dp"-->
<!-- android:layout_marginRight="4dp"-->
<!-- android:layout_marginBottom="4dp"-->
<!-- android:hint="Username" />-->
<Spinner
android:id="@+id/sort_store_dropdown"
android:layout_width="260dp"
android:layout_height="wrap_content"
android:background="@android:drawable/spinner_dropdown_background"
android:spinnerMode="dropdown"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="150dp"
android:padding="15dp">
<Spinner
android:id="@+id/sort_mode_dropdown"
android:layout_width="260dp"
android:layout_height="wrap_content"
android:background="@android:drawable/spinner_dropdown_background"
android:spinnerMode="dropdown"/>
<ImageButton
android:id="@+id/sort_direction_button"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/ic_baseline_sort_28"/>
</LinearLayout>
<!-- <EditText-->
<!-- android:id="@+id/password"-->
<!-- android:inputType="textPassword"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginTop="4dp"-->
<!-- android:layout_marginLeft="4dp"-->
<!-- android:layout_marginRight="4dp"-->
<!-- android:layout_marginBottom="16dp"-->
<!-- android:fontFamily="sans-serif"-->
<!-- android:hint="Password"/>-->
</LinearLayout>

View File

@ -6,9 +6,4 @@
android:orderInCategory="101" android:orderInCategory="101"
android:title="@string/action_settings" android:title="@string/action_settings"
app:showAsAction="never" /> app:showAsAction="never" />
<item
android:id="@+id/action_settings1"
android:orderInCategory="101"
android:title="@string/action_settings"
app:showAsAction="never" />
</menu> </menu>

View File

@ -15,6 +15,7 @@
<string name="search_hint">Search Test</string> <string name="search_hint">Search Test</string>
<string name="title_activity_search">SearchActivity</string> <string name="title_activity_search">SearchActivity</string>
<string name="item_image_desc">Product Image</string> <string name="item_image_desc">Product Image</string>
<string name="sort_button_desc">Sort Icon</string>
<!-- Strings used for fragments for navigation --> <!-- Strings used for fragments for navigation -->
<string name="first_fragment_label">First Fragment</string> <string name="first_fragment_label">First Fragment</string>