mirror of
https://github.com/ClaytonWWilson/Listify.git
synced 2025-12-16 02:38:47 +00:00
Merge pull request #95 from ClaytonWWilson/revamped-search-filter
Revamped search filter
This commit is contained in:
commit
90a09d9d53
@ -0,0 +1,113 @@
|
|||||||
|
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.ListView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.fragment.app.DialogFragment;
|
||||||
|
import com.crystal.crystalrangeseekbar.interfaces.OnRangeSeekbarChangeListener;
|
||||||
|
import com.crystal.crystalrangeseekbar.widgets.CrystalRangeSeekbar;
|
||||||
|
import com.example.listify.adapter.CheckBoxListViewAdapter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
|
||||||
|
public class FilterDialogFragment extends DialogFragment {
|
||||||
|
|
||||||
|
public interface OnFilterListener {
|
||||||
|
void sendFilter(ArrayList<String> selectedStores, double minPrice, double maxPrice);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OnFilterListener onFilterListener;
|
||||||
|
|
||||||
|
CrystalRangeSeekbar priceSeekbar;
|
||||||
|
CheckBoxListViewAdapter checkBoxAdapter;
|
||||||
|
|
||||||
|
private ArrayList<String> selectedStores;
|
||||||
|
private ArrayList<String> stores;
|
||||||
|
private double maxProductPrice; // The highest price on the slider
|
||||||
|
private double minPrice; // The selected min price
|
||||||
|
private double maxPrice; // The selected max price
|
||||||
|
|
||||||
|
public FilterDialogFragment(ArrayList<String> selectedStores, ArrayList<String> stores, double maxProductPrice, double minPrice, double maxPrice) {
|
||||||
|
this.selectedStores = selectedStores;
|
||||||
|
this.stores = stores;
|
||||||
|
this.maxProductPrice = maxProductPrice;
|
||||||
|
this.minPrice = minPrice;
|
||||||
|
this.maxPrice = maxPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@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_filter, null);
|
||||||
|
builder.setView(root)
|
||||||
|
// Add action buttons
|
||||||
|
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
selectedStores = checkBoxAdapter.getChecked();
|
||||||
|
onFilterListener.sendFilter(selectedStores, priceSeekbar.getSelectedMinValue().doubleValue(), priceSeekbar.getSelectedMaxValue().doubleValue());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
FilterDialogFragment.this.getDialog().cancel();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ListView storesList = root.findViewById(R.id.store_name_list);
|
||||||
|
|
||||||
|
// Create arraylist of stores from search results
|
||||||
|
ArrayList<String> storeChoices = new ArrayList<>(stores);
|
||||||
|
|
||||||
|
// Create adapter and send stores and selected stores
|
||||||
|
checkBoxAdapter = new CheckBoxListViewAdapter(getActivity(), storeChoices, this.selectedStores);
|
||||||
|
|
||||||
|
storesList.setAdapter(checkBoxAdapter);
|
||||||
|
|
||||||
|
// Set up the seekbar for price
|
||||||
|
priceSeekbar = (CrystalRangeSeekbar) root.findViewById(R.id.price_range_seekbar);
|
||||||
|
final TextView tvMin = (TextView) root.findViewById(R.id.tv_min_price);
|
||||||
|
final TextView tvMax = (TextView) root.findViewById(R.id.tv_max_price);
|
||||||
|
|
||||||
|
priceSeekbar.setMaxValue((float) this.maxProductPrice);
|
||||||
|
priceSeekbar.setMinStartValue((float) this.minPrice);
|
||||||
|
priceSeekbar.setMaxStartValue((float) this.maxPrice);
|
||||||
|
priceSeekbar.apply();
|
||||||
|
|
||||||
|
// Update price display
|
||||||
|
priceSeekbar.setOnRangeSeekbarChangeListener(new OnRangeSeekbarChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void valueChanged(Number minValue, Number maxValue) {
|
||||||
|
tvMin.setText(String.format("$%.2f", minValue.doubleValue()));
|
||||||
|
tvMax.setText(String.format("$%.2f", maxValue.doubleValue()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return builder.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required to extend DialogFragment
|
||||||
|
@Override
|
||||||
|
public void onAttach(@NonNull Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
try {
|
||||||
|
onFilterListener = (OnFilterListener) getActivity();
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
Log.e("FilterDialogFragment", "onAttach: ClassCastException: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -225,6 +225,7 @@ public class ListPage extends AppCompatActivity implements Requestor.Receiver {
|
|||||||
ArrayList<String> pQuantity;
|
ArrayList<String> pQuantity;
|
||||||
ArrayList<String> pImages;
|
ArrayList<String> pImages;
|
||||||
|
|
||||||
|
|
||||||
MyAdapter (Context c, ArrayList<String> names, ArrayList<String> stores, ArrayList<String> prices, ArrayList<String> quantity, ArrayList<String> images) {
|
MyAdapter (Context c, ArrayList<String> names, ArrayList<String> stores, ArrayList<String> prices, ArrayList<String> quantity, ArrayList<String> images) {
|
||||||
super(c, R.layout.activity_listproductentry, R.id.productView, names);
|
super(c, R.layout.activity_listproductentry, R.id.productView, names);
|
||||||
context = c;
|
context = c;
|
||||||
|
|||||||
@ -190,18 +190,6 @@ public class MainActivity extends AppCompatActivity implements CreateListDialogF
|
|||||||
return NavigationUI.navigateUp(navController, mAppBarConfiguration) || super.onSupportNavigateUp();
|
return NavigationUI.navigateUp(navController, mAppBarConfiguration) || super.onSupportNavigateUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function only exists for the create new list option in hamburger menu
|
|
||||||
public void onClickCreateList(MenuItem m) {
|
|
||||||
m.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onMenuItemClick(MenuItem item) {
|
|
||||||
CreateListDialogFragment createListDialogFragment = new CreateListDialogFragment();
|
|
||||||
createListDialogFragment.show(getSupportFragmentManager(), "Create New List");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onClickSignout(MenuItem m) {
|
public void onClickSignout(MenuItem m) {
|
||||||
m.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
m.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import android.content.Intent;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
@ -23,28 +25,35 @@ import java.util.Properties;
|
|||||||
|
|
||||||
import static com.example.listify.MainActivity.am;
|
import static com.example.listify.MainActivity.am;
|
||||||
|
|
||||||
public class SearchResults extends AppCompatActivity implements SortDialogFragment.OnSortingListener, Requestor.Receiver {
|
public class SearchResults extends AppCompatActivity implements FilterDialogFragment.OnFilterListener, SortDialogFragment.OnSortListener, Requestor.Receiver {
|
||||||
|
private ListView listView;
|
||||||
|
private MenuItem filterItem;
|
||||||
private ProgressBar loadingSearch;
|
private ProgressBar loadingSearch;
|
||||||
private SearchResultsListAdapter searchResultsListAdapter;
|
private SearchResultsListAdapter searchResultsListAdapter;
|
||||||
private List<Product> resultsProductList = new ArrayList<>();
|
private List<Product> resultsProductList = new ArrayList<>();
|
||||||
private List<Product> resultsProductListSorted = new ArrayList<>();
|
private List<Product> resultsProductListSorted = new ArrayList<>();
|
||||||
private ArrayList<String> stores = new ArrayList<>();
|
private ArrayList<String> stores = new ArrayList<>();
|
||||||
private int storeSelection;
|
private ArrayList<String> selectedStores = new ArrayList<>();
|
||||||
private int sortMode;
|
private SortModes sortMode = SortModes.NONE;
|
||||||
private boolean descending;
|
private boolean descending;
|
||||||
private double minPrice = 0;
|
private double minPrice = 0;
|
||||||
private double maxPrice = -1;
|
private double maxPrice = -1;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendSort(int storeSelection, int sortMode, boolean descending, double minPrice, double maxPrice) {
|
public void sendFilter(ArrayList<String> selectedStores, double minPrice, double maxPrice) {
|
||||||
this.storeSelection = storeSelection;
|
this.selectedStores = selectedStores;
|
||||||
this.sortMode = sortMode;
|
|
||||||
this.descending = descending;
|
|
||||||
this.minPrice = minPrice;
|
this.minPrice = minPrice;
|
||||||
this.maxPrice = maxPrice;
|
this.maxPrice = maxPrice;
|
||||||
sortResults();
|
sortResults();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendSort(SortModes sortMode, boolean descending) {
|
||||||
|
this.sortMode = sortMode;
|
||||||
|
this.descending = descending;
|
||||||
|
sortResults();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
@ -120,22 +129,27 @@ public class SearchResults extends AppCompatActivity implements SortDialogFragme
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Change this to a menu in which sort and filter are two different options
|
@Override
|
||||||
// TODO: Sort should be disabled until a search is made
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
// Create a dialog for filtering and sorting search results
|
//Inflate the menu; this adds items to the action bar if it is present.
|
||||||
ImageButton sortButton = (ImageButton) findViewById(R.id.results_sort_button);
|
getMenuInflater().inflate(R.menu.search, menu);
|
||||||
sortButton.setOnClickListener(new View.OnClickListener() {
|
MenuItem sortItem = menu.findItem(R.id.action_sort);
|
||||||
|
sortItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
// Sort the store list
|
SortDialogFragment sortDialog = new SortDialogFragment(sortMode, descending);
|
||||||
stores.sort(new Comparator<String>() {
|
sortDialog.show(getSupportFragmentManager(), "Sort Dialog");
|
||||||
@Override
|
return false;
|
||||||
public int compare(String o1, String o2) {
|
}
|
||||||
return o1.compareTo(o2);
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
// TODO: Reset upper and lower limits on price filter when a new search is made
|
||||||
|
filterItem = menu.findItem(R.id.action_filter);
|
||||||
|
filterItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
// Determine the max price for the price slider
|
// Determine the max price for the price slider
|
||||||
double maxProductPrice;
|
double maxProductPrice;
|
||||||
if (resultsProductList.isEmpty()) {
|
if (resultsProductList.isEmpty()) {
|
||||||
@ -159,10 +173,18 @@ public class SearchResults extends AppCompatActivity implements SortDialogFragme
|
|||||||
// Round up to nearest whole number for display on price seekbar
|
// Round up to nearest whole number for display on price seekbar
|
||||||
maxProductPrice = Math.ceil(maxProductPrice);
|
maxProductPrice = Math.ceil(maxProductPrice);
|
||||||
|
|
||||||
SortDialogFragment sortDialog = new SortDialogFragment(storeSelection, stores, sortMode, descending, maxProductPrice, minPrice, maxPrice);
|
FilterDialogFragment sortDialog = new FilterDialogFragment(selectedStores, stores, maxProductPrice, minPrice, maxPrice);
|
||||||
sortDialog.show(getSupportFragmentManager(), "Sort");
|
sortDialog.show(getSupportFragmentManager(), "Filter Dialog");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Disable filtering by default until a search is made
|
||||||
|
if (resultsProductList.isEmpty()) {
|
||||||
|
filterItem.setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override default phone back button to add animation
|
// Override default phone back button to add animation
|
||||||
@ -200,10 +222,11 @@ public class SearchResults extends AppCompatActivity implements SortDialogFragme
|
|||||||
|
|
||||||
// Sort based on mode
|
// Sort based on mode
|
||||||
switch (this.sortMode) {
|
switch (this.sortMode) {
|
||||||
case 0:
|
case NONE:
|
||||||
// Do nothing
|
// Do nothing
|
||||||
break;
|
break;
|
||||||
case 1:
|
|
||||||
|
case NAME:
|
||||||
resultsProductListSorted.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) {
|
||||||
@ -211,8 +234,8 @@ public class SearchResults extends AppCompatActivity implements SortDialogFragme
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case PRICE:
|
||||||
resultsProductListSorted.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) {
|
||||||
@ -227,7 +250,7 @@ public class SearchResults extends AppCompatActivity implements SortDialogFragme
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case STORE:
|
||||||
resultsProductListSorted.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) {
|
||||||
@ -236,7 +259,7 @@ public class SearchResults extends AppCompatActivity implements SortDialogFragme
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case UPC:
|
||||||
resultsProductListSorted.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) {
|
||||||
@ -247,7 +270,7 @@ public class SearchResults extends AppCompatActivity implements SortDialogFragme
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Flip the list if descending is selected
|
// Flip the list if descending is selected
|
||||||
if (this.sortMode != 0 & this.descending) {
|
if (this.descending) {
|
||||||
for (int i = 0; i < resultsProductListSorted.size() / 2; i++) {
|
for (int i = 0; i < resultsProductListSorted.size() / 2; i++) {
|
||||||
Product temp = resultsProductListSorted.get(i);
|
Product temp = resultsProductListSorted.get(i);
|
||||||
resultsProductListSorted.set(i, resultsProductListSorted.get(resultsProductListSorted.size() - i - 1));
|
resultsProductListSorted.set(i, resultsProductListSorted.get(resultsProductListSorted.size() - i - 1));
|
||||||
@ -256,10 +279,10 @@ public class SearchResults extends AppCompatActivity implements SortDialogFragme
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only keep results that match the current store selection
|
// Only keep results that match the current store selection
|
||||||
if (this.storeSelection != 0) {
|
if (!this.selectedStores.equals(this.stores)) {
|
||||||
ArrayList<Product> temp = new ArrayList<>();
|
ArrayList<Product> temp = new ArrayList<>();
|
||||||
resultsProductListSorted.forEach(product -> {
|
resultsProductListSorted.forEach(product -> {
|
||||||
if (product.getChainName().equals(this.stores.get(this.storeSelection - 1))) {
|
if (this.selectedStores.contains(product.getChainName())) {
|
||||||
temp.add(product);
|
temp.add(product);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -317,8 +340,24 @@ public class SearchResults extends AppCompatActivity implements SortDialogFragme
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset selected stores on search so that every store is selected
|
||||||
|
this.selectedStores.clear();
|
||||||
|
this.selectedStores.addAll(stores);
|
||||||
|
|
||||||
// Add all results to the sorted list
|
// Add all results to the sorted list
|
||||||
resultsProductListSorted.addAll(resultsProductList);
|
resultsProductListSorted.addAll(resultsProductList);
|
||||||
|
|
||||||
|
// Filtering should only be allowed if there are items in the results
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (resultsProductList.isEmpty()) {
|
||||||
|
filterItem.setEnabled(false);
|
||||||
|
} else {
|
||||||
|
filterItem.setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Apply selected sorting to the list
|
// Apply selected sorting to the list
|
||||||
sortResults();
|
sortResults();
|
||||||
|
|||||||
@ -1,56 +1,41 @@
|
|||||||
package com.example.listify;
|
package com.example.listify;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.AdapterView;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.Spinner;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.widget.SwitchCompat;
|
||||||
import androidx.fragment.app.DialogFragment;
|
import androidx.fragment.app.DialogFragment;
|
||||||
|
|
||||||
import com.crystal.crystalrangeseekbar.interfaces.OnRangeSeekbarChangeListener;
|
|
||||||
import com.crystal.crystalrangeseekbar.widgets.CrystalRangeSeekbar;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
|
|
||||||
public class SortDialogFragment extends DialogFragment {
|
public class SortDialogFragment extends DialogFragment {
|
||||||
|
|
||||||
public interface OnSortingListener {
|
public interface OnSortListener {
|
||||||
void sendSort(int storeSelection, int sortMode, boolean descending, double minPrice, double maxPrice);
|
void sendSort(SortModes sortMode, boolean descending);
|
||||||
}
|
}
|
||||||
|
|
||||||
public OnSortingListener onSortingListener;
|
public OnSortListener onSortListener;
|
||||||
|
|
||||||
CrystalRangeSeekbar priceSeekbar;
|
private SortModes sortMode;
|
||||||
|
|
||||||
private int storeSelection;
|
|
||||||
private int sortMode;
|
|
||||||
private boolean descending;
|
private boolean descending;
|
||||||
private ArrayList<String> stores;
|
|
||||||
private double maxProductPrice; // The highest price on the slider
|
|
||||||
private double minPrice; // The selected min price
|
|
||||||
private double maxPrice; // The selected max price
|
|
||||||
|
|
||||||
public SortDialogFragment(int storeSelection, ArrayList<String> stores, int sortMode, boolean descending, double maxProductPrice, double minPrice, double maxPrice) {
|
TextView tvSortNone;
|
||||||
this.storeSelection = storeSelection;
|
TextView tvSortName;
|
||||||
this.stores = stores;
|
TextView tvSortPrice;
|
||||||
|
TextView tvSortStore;
|
||||||
|
SwitchCompat swDescending;
|
||||||
|
|
||||||
|
public SortDialogFragment(SortModes sortMode, boolean descending) {
|
||||||
this.sortMode = sortMode;
|
this.sortMode = sortMode;
|
||||||
this.descending = descending;
|
this.descending = descending;
|
||||||
this.maxProductPrice = maxProductPrice;
|
|
||||||
this.minPrice = minPrice;
|
|
||||||
this.maxPrice = maxPrice;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Sorting should scroll the user back to the top of the page
|
||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||||
@ -60,122 +45,105 @@ public class SortDialogFragment extends DialogFragment {
|
|||||||
// Inflate and set the layout for the dialog
|
// Inflate and set the layout for the dialog
|
||||||
// Pass null as the parent view because its going in the dialog layout
|
// Pass null as the parent view because its going in the dialog layout
|
||||||
View root = inflater.inflate(R.layout.dialog_sort, null);
|
View root = inflater.inflate(R.layout.dialog_sort, null);
|
||||||
builder.setView(root)
|
builder.setView(root);
|
||||||
// Add action buttons
|
|
||||||
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int id) {
|
|
||||||
onSortingListener.sendSort(storeSelection, sortMode, descending, priceSeekbar.getSelectedMinValue().doubleValue(), priceSeekbar.getSelectedMaxValue().doubleValue());
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.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);
|
tvSortNone = (TextView) root.findViewById(R.id.sort_none);
|
||||||
String[] storeChoices = new String[stores.size() + 1];
|
tvSortName = (TextView) root.findViewById(R.id.sort_name);
|
||||||
storeChoices[0] = "All";
|
tvSortPrice = (TextView) root.findViewById(R.id.sort_price);
|
||||||
for (int i = 1; i < stores.size() + 1; i++) {
|
tvSortStore = (TextView) root.findViewById(R.id.sort_store);
|
||||||
storeChoices[i] = stores.get(i - 1);
|
LinearLayout llDescendingContainer = (LinearLayout) root.findViewById(R.id.descending_container);
|
||||||
|
swDescending = (SwitchCompat) root.findViewById(R.id.switch_descending);
|
||||||
|
|
||||||
|
switch (this.sortMode) {
|
||||||
|
case NONE:
|
||||||
|
tvSortNone.setBackgroundColor(getResources().getColor(R.color.colorAccent));
|
||||||
|
break;
|
||||||
|
case NAME:
|
||||||
|
tvSortName.setBackgroundColor(getResources().getColor(R.color.colorAccent));
|
||||||
|
break;
|
||||||
|
case PRICE:
|
||||||
|
tvSortPrice.setBackgroundColor(getResources().getColor(R.color.colorAccent));
|
||||||
|
break;
|
||||||
|
case STORE:
|
||||||
|
tvSortStore.setBackgroundColor(getResources().getColor(R.color.colorAccent));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the store selection dropdown
|
if (this.descending) {
|
||||||
ArrayAdapter<String> storeAdapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_dropdown_item, storeChoices);
|
swDescending.setChecked(true);
|
||||||
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) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Change the sort arrow to be pointing up or down based on ascending or descending
|
|
||||||
final ImageButton sortDirectionButton = root.findViewById(R.id.sort_direction_button);
|
|
||||||
if (descending) {
|
|
||||||
sortDirectionButton.setImageResource(R.drawable.ic_baseline_arrow_downward_50);
|
|
||||||
} else {
|
|
||||||
sortDirectionButton.setImageResource(R.drawable.ic_baseline_arrow_upward_50);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change arrow pointing direction whenever the user clicks the button
|
tvSortNone.setOnClickListener(new View.OnClickListener() {
|
||||||
sortDirectionButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
if (descending) {
|
handleClicked(tvSortNone, SortModes.NONE, swDescending.isChecked());
|
||||||
descending = false;
|
|
||||||
sortDirectionButton.setImageResource(R.drawable.ic_baseline_arrow_upward_50);
|
|
||||||
} else {
|
|
||||||
descending = true;
|
|
||||||
sortDirectionButton.setImageResource(R.drawable.ic_baseline_arrow_downward_50);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create the sort mode selection dropdown
|
tvSortName.setOnClickListener(new View.OnClickListener() {
|
||||||
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
|
@Override
|
||||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
public void onClick(View v) {
|
||||||
sortMode = position;
|
handleClicked(tvSortName, SortModes.NAME, swDescending.isChecked());
|
||||||
|
|
||||||
// Update the sort direction button
|
|
||||||
if (position == 0) {
|
|
||||||
sortDirectionButton.setEnabled(false);
|
|
||||||
} else {
|
|
||||||
sortDirectionButton.setEnabled(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNothingSelected(AdapterView<?> parent) {}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Disable the direction button if they have the default sorting mode selected
|
tvSortPrice.setOnClickListener(new View.OnClickListener() {
|
||||||
// Ascending and Descending are mostly irrelevant in the default sort mode
|
|
||||||
if (sortDropdown.getSelectedItemPosition() == 0) {
|
|
||||||
sortDirectionButton.setEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up the seekbar for price
|
|
||||||
priceSeekbar = (CrystalRangeSeekbar) root.findViewById(R.id.price_range_seekbar);
|
|
||||||
final TextView tvMin = (TextView) root.findViewById(R.id.tv_min_price);
|
|
||||||
final TextView tvMax = (TextView) root.findViewById(R.id.tv_max_price);
|
|
||||||
|
|
||||||
priceSeekbar.setMaxValue((float) this.maxProductPrice);
|
|
||||||
priceSeekbar.setMinStartValue((float) this.minPrice);
|
|
||||||
priceSeekbar.setMaxStartValue((float) this.maxPrice);
|
|
||||||
priceSeekbar.apply();
|
|
||||||
|
|
||||||
// Update price display
|
|
||||||
priceSeekbar.setOnRangeSeekbarChangeListener(new OnRangeSeekbarChangeListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void valueChanged(Number minValue, Number maxValue) {
|
public void onClick(View v) {
|
||||||
tvMin.setText(String.format("$%.2f", minValue.doubleValue()));
|
handleClicked(tvSortPrice, SortModes.PRICE, swDescending.isChecked());
|
||||||
tvMax.setText(String.format("$%.2f", maxValue.doubleValue()));
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tvSortStore.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
handleClicked(tvSortStore, SortModes.STORE, swDescending.isChecked());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: set onclick listener for descending switch
|
||||||
|
llDescendingContainer.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
System.out.println("linear");
|
||||||
|
swDescending.performClick();
|
||||||
|
// handleClicked(sortMode, swDescending.isChecked());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
swDescending.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
System.out.println("switch");
|
||||||
|
descending = swDescending.isChecked();
|
||||||
|
onSortListener.sendSort(sortMode, swDescending.isChecked());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return builder.create();
|
return builder.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleClicked(TextView tvSelected, SortModes sortMode, boolean descending) {
|
||||||
|
this.sortMode = sortMode;
|
||||||
|
this.descending = descending;
|
||||||
|
|
||||||
|
tvSortNone.setBackgroundColor(getResources().getColor(R.color.white));
|
||||||
|
tvSortName.setBackgroundColor(getResources().getColor(R.color.white));
|
||||||
|
tvSortPrice.setBackgroundColor(getResources().getColor(R.color.white));
|
||||||
|
tvSortStore.setBackgroundColor(getResources().getColor(R.color.white));
|
||||||
|
|
||||||
|
tvSelected.setBackgroundColor(getResources().getColor(R.color.colorAccent));
|
||||||
|
onSortListener.sendSort(sortMode, descending);
|
||||||
|
|
||||||
|
// SortDialogFragment.this.getDialog().cancel();
|
||||||
|
}
|
||||||
|
|
||||||
// Required to extend DialogFragment
|
// Required to extend DialogFragment
|
||||||
@Override
|
@Override
|
||||||
public void onAttach(@NonNull Context context) {
|
public void onAttach(@NonNull Context context) {
|
||||||
super.onAttach(context);
|
super.onAttach(context);
|
||||||
try {
|
try {
|
||||||
onSortingListener = (OnSortingListener) getActivity();
|
onSortListener = (OnSortListener) getActivity();
|
||||||
} catch (ClassCastException e) {
|
} catch (ClassCastException e) {
|
||||||
Log.e("SortDialogFragment", "onAttach: ClassCastException: " + e.getMessage());
|
Log.e("SortDialogFragment", "onAttach: ClassCastException: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,9 @@
|
|||||||
|
package com.example.listify;
|
||||||
|
|
||||||
|
public enum SortModes {
|
||||||
|
NONE,
|
||||||
|
NAME,
|
||||||
|
PRICE,
|
||||||
|
STORE,
|
||||||
|
UPC
|
||||||
|
}
|
||||||
@ -0,0 +1,94 @@
|
|||||||
|
package com.example.listify.adapter;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.BaseAdapter;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.CompoundButton;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import com.example.listify.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class CheckBoxListViewAdapter extends BaseAdapter {
|
||||||
|
private Activity activity;
|
||||||
|
ArrayList<String> list = new ArrayList<>();
|
||||||
|
ArrayList<String> checkedList = new ArrayList<>();
|
||||||
|
|
||||||
|
public CheckBoxListViewAdapter(Activity activity, ArrayList<String> list, ArrayList<String> checkedList) {
|
||||||
|
super();
|
||||||
|
this.activity = activity;
|
||||||
|
this.list = list;
|
||||||
|
this.checkedList = checkedList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return list.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getItem(int position) {
|
||||||
|
return list.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ViewHolder {
|
||||||
|
public TextView label;
|
||||||
|
public CheckBox checkBox;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public View getView(final int position, View convertView, ViewGroup parent) {
|
||||||
|
ViewHolder holder;
|
||||||
|
LayoutInflater inflator = ((Activity) activity).getLayoutInflater();
|
||||||
|
|
||||||
|
if (convertView == null) {
|
||||||
|
convertView = inflator.inflate(R.layout.filter_store_item, null);
|
||||||
|
|
||||||
|
convertView.setSoundEffectsEnabled(false);
|
||||||
|
|
||||||
|
holder = new ViewHolder();
|
||||||
|
holder.label = (TextView) convertView.findViewById(R.id.store_name);
|
||||||
|
holder.checkBox = (CheckBox)convertView.findViewById(R.id.store_check_box);
|
||||||
|
|
||||||
|
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||||
|
int getPosition = (Integer) buttonView.getTag();
|
||||||
|
|
||||||
|
if (isChecked) {
|
||||||
|
checkedList.add(list.get(getPosition));
|
||||||
|
} else {
|
||||||
|
checkedList.remove(list.get(getPosition));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
convertView.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
System.out.println("clicked");
|
||||||
|
holder.checkBox.performClick();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
convertView.setTag(holder);
|
||||||
|
} else {
|
||||||
|
holder = (ViewHolder) convertView.getTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.checkBox.setTag(position);
|
||||||
|
holder.label.setText("" + list.get(position));
|
||||||
|
holder.checkBox.setChecked(checkedList.contains(list.get(position)));
|
||||||
|
return convertView;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<String> getChecked() {
|
||||||
|
return this.checkedList;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -23,10 +23,12 @@
|
|||||||
android:id="@+id/backToHomeButton"
|
android:id="@+id/backToHomeButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:translationX="-10dp"
|
||||||
|
android:padding="10dp"
|
||||||
app:srcCompat="@drawable/abc_vector_test"
|
app:srcCompat="@drawable/abc_vector_test"
|
||||||
android:background="@null"
|
android:background="@null"
|
||||||
android:contentDescription="@string/backButton"/>
|
android:contentDescription="@string/backButton"
|
||||||
|
android:foreground="?android:attr/selectableItemBackgroundBorderless"/>
|
||||||
|
|
||||||
<SearchView
|
<SearchView
|
||||||
android:id="@+id/searchBar"
|
android:id="@+id/searchBar"
|
||||||
@ -36,14 +38,6 @@
|
|||||||
>
|
>
|
||||||
</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>
|
||||||
|
|||||||
@ -19,13 +19,15 @@
|
|||||||
app:popupTheme="@style/AppTheme.PopupOverlay" >
|
app:popupTheme="@style/AppTheme.PopupOverlay" >
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/searchButton"
|
android:id="@+id/searchButton"
|
||||||
android:layout_width="30dp"
|
android:layout_width="wrap_content"
|
||||||
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"
|
||||||
|
android:padding="10dp"
|
||||||
app:srcCompat="@drawable/ic_baseline_search_28"
|
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"
|
||||||
|
android:foreground="?android:attr/selectableItemBackgroundBorderless"/>
|
||||||
</androidx.appcompat.widget.Toolbar>
|
</androidx.appcompat.widget.Toolbar>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
62
Listify/app/src/main/res/layout/dialog_filter.xml
Normal file
62
Listify/app/src/main/res/layout/dialog_filter.xml
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_store_selection"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="15dp"
|
||||||
|
android:layout_marginStart="15dp"
|
||||||
|
android:text="@string/store_selection"
|
||||||
|
android:textSize="20sp"/>
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:id="@+id/store_name_list"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:layout_marginBottom="10dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_price_label"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:layout_marginStart="15dp"
|
||||||
|
android:text="Price"
|
||||||
|
android:textSize="20sp"/>
|
||||||
|
|
||||||
|
<com.crystal.crystalrangeseekbar.widgets.CrystalRangeSeekbar
|
||||||
|
android:id="@+id/price_range_seekbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="10dp"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_min_price"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:layout_marginStart="15dp"
|
||||||
|
android:text="$00.00" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_max_price"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:layout_marginEnd="15dp"
|
||||||
|
android:gravity="end"
|
||||||
|
android:text="$00.00" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@ -1,93 +1,104 @@
|
|||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="30dp">
|
||||||
|
|
||||||
|
<!-- I would've use a ListView here, but it doesn't offer enough customization -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/sort_none"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:text="None"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textColor="@android:color/black"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:foreground="?attr/selectableItemBackgroundBorderless" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="@color/list_divider" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tv_store_selection"
|
android:id="@+id/sort_name"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="50dp"
|
||||||
android:layout_weight="1"
|
android:text="Name"
|
||||||
android:layout_marginTop="15dp"
|
android:textSize="16sp"
|
||||||
android:layout_marginStart="15dp"
|
android:textColor="@android:color/black"
|
||||||
android:text="@string/store_selection" />
|
android:paddingStart="16dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:foreground="?attr/selectableItemBackgroundBorderless"/>
|
||||||
|
|
||||||
<Spinner
|
<View
|
||||||
android:id="@+id/sort_store_dropdown"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="265dp"
|
android:layout_height="1dp"
|
||||||
android:layout_marginStart="15dp"
|
android:background="@color/list_divider" />
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@android:drawable/spinner_dropdown_background"
|
|
||||||
android:spinnerMode="dropdown"/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tv_sort_by"
|
android:id="@+id/sort_price"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="50dp"
|
||||||
android:layout_weight="1"
|
android:text="Price"
|
||||||
android:layout_marginTop="20dp"
|
android:textSize="16sp"
|
||||||
android:layout_marginStart="15dp"
|
android:textColor="@android:color/black"
|
||||||
android:text="Sort by" />
|
android:paddingStart="16dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:foreground="?attr/selectableItemBackgroundBorderless"/>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="@color/list_divider" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/sort_store"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:text="Store"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textColor="@android:color/black"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:foreground="?attr/selectableItemBackgroundBorderless"/>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="@color/list_divider" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/descending_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="50dp"
|
||||||
android:paddingStart="15dp">
|
android:gravity="center_vertical"
|
||||||
|
android:clickable="true"
|
||||||
<Spinner
|
android:focusable="true"
|
||||||
android:id="@+id/sort_mode_dropdown"
|
android:foreground="?attr/selectableItemBackgroundBorderless"
|
||||||
android:layout_width="265dp"
|
android:soundEffectsEnabled="false">
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@android:drawable/spinner_dropdown_background"
|
|
||||||
android:spinnerMode="dropdown"/>
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/sort_direction_button"
|
|
||||||
android:layout_marginTop="-6dp"
|
|
||||||
android:layout_width="57dp"
|
|
||||||
android:layout_height="70dp"
|
|
||||||
android:background="@null"
|
|
||||||
android:src="@drawable/ic_baseline_arrow_upward_50"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_price_label"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:layout_marginStart="15dp"
|
|
||||||
android:text="Price" />
|
|
||||||
|
|
||||||
<com.crystal.crystalrangeseekbar.widgets.CrystalRangeSeekbar
|
|
||||||
android:id="@+id/price_range_seekbar"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="10dp"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tv_min_price"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:text="Descending"
|
||||||
android:layout_marginTop="20dp"
|
android:textSize="16sp"
|
||||||
android:layout_marginStart="15dp"
|
android:textColor="@android:color/black"
|
||||||
android:text="$00.00" />
|
android:paddingStart="16dp"/>
|
||||||
<TextView
|
|
||||||
android:id="@+id/tv_max_price"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:layout_marginEnd="15dp"
|
|
||||||
android:gravity="end"
|
|
||||||
android:text="$00.00" />
|
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.SwitchCompat
|
||||||
|
android:id="@+id/switch_descending"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
28
Listify/app/src/main/res/layout/filter_store_item.xml
Normal file
28
Listify/app/src/main/res/layout/filter_store_item.xml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?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">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/store_name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="New Text"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:layout_marginStart="25dp"/>
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/store_check_box"
|
||||||
|
android:checked="true"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text=""
|
||||||
|
android:focusable="false"
|
||||||
|
android:gravity="end"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:layout_marginBottom="-5dp"
|
||||||
|
android:layout_alignParentEnd="true" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
@ -5,7 +5,7 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:dragEdge="right"
|
app:dragEdge="left"
|
||||||
app:mode="same_level">
|
app:mode="same_level">
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
|
|||||||
@ -20,6 +20,11 @@
|
|||||||
android:id="@+id/nav_lists"
|
android:id="@+id/nav_lists"
|
||||||
android:icon="@drawable/ic_baseline_list_alt_28"
|
android:icon="@drawable/ic_baseline_list_alt_28"
|
||||||
android:title="@string/menu_lists" />
|
android:title="@string/menu_lists" />
|
||||||
|
<!-- <item-->
|
||||||
|
<!-- android:id="@+id/nav_create_list"-->
|
||||||
|
<!-- android:icon="@drawable/ic_baseline_add_28"-->
|
||||||
|
<!-- android:title="Create New List"-->
|
||||||
|
<!-- android:onClick="onClickCreateList" />-->
|
||||||
<item
|
<item
|
||||||
android:id="@+id/nav_logout"
|
android:id="@+id/nav_logout"
|
||||||
android:title="Sign out"
|
android:title="Sign out"
|
||||||
|
|||||||
14
Listify/app/src/main/res/menu/search.xml
Normal file
14
Listify/app/src/main/res/menu/search.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_sort"
|
||||||
|
android:orderInCategory="101"
|
||||||
|
android:title="Sort"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_filter"
|
||||||
|
android:orderInCategory="101"
|
||||||
|
android:title="Filter"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
</menu>
|
||||||
@ -11,4 +11,5 @@
|
|||||||
<color name="list_row_hover_start_color">#ebeef0</color>
|
<color name="list_row_hover_start_color">#ebeef0</color>
|
||||||
<color name="list_row_hover_end_color">#1c9ef4</color>
|
<color name="list_row_hover_end_color">#1c9ef4</color>
|
||||||
<color name="light_gray">#e6e6e6</color>
|
<color name="light_gray">#e6e6e6</color>
|
||||||
|
<color name="white">#ffffffff</color>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Reference in New Issue
Block a user