diff --git a/app/src/main/java/it/danieleverducci/nextcloudmaps/activity/detail/CategoriesAdapter.java b/app/src/main/java/it/danieleverducci/nextcloudmaps/activity/detail/CategoriesAdapter.java new file mode 100644 index 0000000..d3cb49e --- /dev/null +++ b/app/src/main/java/it/danieleverducci/nextcloudmaps/activity/detail/CategoriesAdapter.java @@ -0,0 +1,47 @@ +package it.danieleverducci.nextcloudmaps.activity.detail; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.graphics.drawable.DrawableCompat; + +import java.util.ArrayList; +import java.util.HashSet; + +import it.danieleverducci.nextcloudmaps.R; +import it.danieleverducci.nextcloudmaps.model.Geofavorite; + +public class CategoriesAdapter extends ArrayAdapter { + + public CategoriesAdapter(@NonNull Context context) { + super(context, R.layout.category_listitem, R.id.category_name, new ArrayList<>()); + } + + @NonNull + @Override + public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { + View v = super.getView(position, convertView, parent); + TextView categoryName = v.findViewById(R.id.category_name); + Drawable backgroundDrawable = categoryName.getBackground(); + DrawableCompat.setTint( + backgroundDrawable, + Geofavorite.categoryColorFromName(categoryName.getText().toString()) == 0 + ? v.getContext().getColor(R.color.defaultBrand) + : Geofavorite.categoryColorFromName(categoryName.getText().toString()) + ); + return v; + } + + public void setCategoriesList(HashSet categories) { + clear(); + addAll(categories); + notifyDataSetChanged(); + } + +} diff --git a/app/src/main/java/it/danieleverducci/nextcloudmaps/activity/detail/CategoriesSpinnerAdapter.java b/app/src/main/java/it/danieleverducci/nextcloudmaps/activity/detail/CategoriesSpinnerAdapter.java deleted file mode 100644 index 01a86fa..0000000 --- a/app/src/main/java/it/danieleverducci/nextcloudmaps/activity/detail/CategoriesSpinnerAdapter.java +++ /dev/null @@ -1,24 +0,0 @@ -package it.danieleverducci.nextcloudmaps.activity.detail; - -import android.content.Context; -import android.widget.ArrayAdapter; - -import androidx.annotation.NonNull; - -import java.util.HashSet; - -public class CategoriesSpinnerAdapter extends ArrayAdapter { - - public CategoriesSpinnerAdapter(@NonNull Context context) { - super(context, android.R.layout.simple_dropdown_item_1line); - } - - // TODO: implement colors - - public void setCategoriesList(HashSet categories) { - clear(); - addAll(categories); - notifyDataSetChanged(); - } - -} diff --git a/app/src/main/java/it/danieleverducci/nextcloudmaps/activity/detail/GeofavoriteDetailActivity.java b/app/src/main/java/it/danieleverducci/nextcloudmaps/activity/detail/GeofavoriteDetailActivity.java index 714219b..3de1f63 100644 --- a/app/src/main/java/it/danieleverducci/nextcloudmaps/activity/detail/GeofavoriteDetailActivity.java +++ b/app/src/main/java/it/danieleverducci/nextcloudmaps/activity/detail/GeofavoriteDetailActivity.java @@ -21,11 +21,9 @@ import android.Manifest; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; -import android.graphics.Color; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; -import android.os.Build; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; @@ -34,7 +32,6 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.content.res.AppCompatResources; import androidx.core.app.ActivityCompat; import androidx.lifecycle.Observer; @@ -43,7 +40,6 @@ import androidx.preference.PreferenceManager; import org.osmdroid.api.IMapController; import org.osmdroid.config.Configuration; -import org.osmdroid.config.IConfigurationProvider; import org.osmdroid.util.GeoPoint; import org.osmdroid.views.CustomZoomButtonsController; import org.osmdroid.views.overlay.Marker; @@ -52,10 +48,8 @@ import org.threeten.bp.format.FormatStyle; import java.util.HashSet; -import it.danieleverducci.nextcloudmaps.BuildConfig; import it.danieleverducci.nextcloudmaps.R; import it.danieleverducci.nextcloudmaps.activity.NextcloudMapsStyledActivity; -import it.danieleverducci.nextcloudmaps.activity.mappicker.MapPickerActivity; import it.danieleverducci.nextcloudmaps.databinding.ActivityGeofavoriteDetailBinding; import it.danieleverducci.nextcloudmaps.model.Geofavorite; import it.danieleverducci.nextcloudmaps.utils.GeoUriParser; @@ -313,7 +307,7 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple this.binding.actionIconNav.setOnClickListener(this); // Set categories adapter - CategoriesSpinnerAdapter categoriesAdapter = new CategoriesSpinnerAdapter(binding.root.getContext()); + CategoriesAdapter categoriesAdapter = new CategoriesAdapter(binding.root.getContext()); this.binding.categoryAt.setAdapter(categoriesAdapter); this.binding.categoryAt.setText(Geofavorite.DEFAULT_CATEGORY); @@ -378,7 +372,7 @@ public class GeofavoriteDetailActivity extends NextcloudMapsStyledActivity imple } public void setCategories(HashSet categories) { - ((CategoriesSpinnerAdapter)binding.categoryAt.getAdapter()).setCategoriesList(categories); + ((CategoriesAdapter)binding.categoryAt.getAdapter()).setCategoriesList(categories); } public void hideAccuracy() { diff --git a/app/src/main/java/it/danieleverducci/nextcloudmaps/fragments/GeofavoritesFragment.java b/app/src/main/java/it/danieleverducci/nextcloudmaps/fragments/GeofavoritesFragment.java index e8c72f8..1663cdb 100644 --- a/app/src/main/java/it/danieleverducci/nextcloudmaps/fragments/GeofavoritesFragment.java +++ b/app/src/main/java/it/danieleverducci/nextcloudmaps/fragments/GeofavoritesFragment.java @@ -5,6 +5,7 @@ import static android.view.View.VISIBLE; import android.content.DialogInterface; import android.content.Intent; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.text.TextUtils; @@ -19,25 +20,20 @@ import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.AppCompatImageButton; import androidx.appcompat.widget.AppCompatImageView; import androidx.appcompat.widget.SearchView; -import androidx.appcompat.widget.Toolbar; +import androidx.core.graphics.drawable.DrawableCompat; import androidx.fragment.app.Fragment; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; - -import com.google.android.material.card.MaterialCardView; -import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException; -import com.nextcloud.android.sso.exceptions.NoCurrentAccountSelectedException; import com.nextcloud.android.sso.helper.SingleAccountHelper; import com.nextcloud.android.sso.model.SingleSignOnAccount; import com.squareup.picasso.Picasso; -import java.io.File; import java.util.ArrayList; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import it.danieleverducci.nextcloudmaps.R; +import it.danieleverducci.nextcloudmaps.activity.detail.CategoriesAdapter; import it.danieleverducci.nextcloudmaps.activity.detail.GeofavoriteDetailActivity; import it.danieleverducci.nextcloudmaps.activity.main.GeofavoritesFragmentViewModel; import it.danieleverducci.nextcloudmaps.activity.main.MainActivity; @@ -154,6 +150,8 @@ public abstract class GeofavoritesFragment extends Fragment { public void onStart() { super.onStart(); + // Reset filter and update data + filterButton.setImageResource(R.drawable.ic_filter_off); mGeofavoritesFragmentViewModel.updateGeofavorites(); } @@ -226,14 +224,30 @@ public abstract class GeofavoritesFragment extends Fragment { AlertDialog.Builder builder = new AlertDialog.Builder(requireContext()); builder.setTitle(R.string.filtering_dialog_title); - String[] categoryNames = categories.toArray(new String[categories.size()]); - builder.setItems(categoryNames, new DialogInterface.OnClickListener() { + CategoriesAdapter ca = new CategoriesAdapter(requireContext()); + ca.setCategoriesList(categories); + builder.setAdapter(ca, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - String category = categoryNames[which]; - Log.d(TAG, "Selected category " + category); + // Set filter button enabled icon and color + String categoryName = ca.getItem(which); + filterButton.setImageResource(R.drawable.ic_filter); + Drawable d = filterButton.getDrawable(); + DrawableCompat.setTint( + d, + Geofavorite.categoryColorFromName(categoryName) == 0 + ? requireContext().getColor(R.color.defaultBrand) + : Geofavorite.categoryColorFromName(categoryName) + ); + filterByCategory(categoryName); } }); + + builder.setPositiveButton(R.string.filtering_dialog_cancel, (dialog, id) -> { + dialog.dismiss(); + filterButton.setImageResource(R.drawable.ic_filter_off); + filterByCategory(null); + }); AlertDialog dialog = builder.create(); dialog.show(); } @@ -247,4 +261,10 @@ public abstract class GeofavoritesFragment extends Fragment { searchView.setIconified(disableSearch); } + private void filterByCategory(String category) { + onDatasetChange( + (new GeofavoritesFilter(geofavorites)).byCategory(category) + ); + } + } diff --git a/app/src/main/java/it/danieleverducci/nextcloudmaps/model/Geofavorite.java b/app/src/main/java/it/danieleverducci/nextcloudmaps/model/Geofavorite.java index 2d4dc88..aa8f6c8 100644 --- a/app/src/main/java/it/danieleverducci/nextcloudmaps/model/Geofavorite.java +++ b/app/src/main/java/it/danieleverducci/nextcloudmaps/model/Geofavorite.java @@ -204,17 +204,7 @@ public class Geofavorite implements Serializable { * @return the generated color or null for the default category */ public int categoryColor() { - // If category is default, return null: will be used Nextcloud's accent - if (this.category == null || this.category.equals(DEFAULT_CATEGORY) || this.category.length() == 0) - return 0; - - float letter1Index = this.category.toLowerCase().charAt(0); - float letter2Index = this.category.toLowerCase().charAt(1); - float letterCoef = ((letter1Index * letter2Index) % 100) / 100; - float h = letterCoef * 360; - float s = 75 + letterCoef * 10; - float l = 50 + letterCoef * 10; - return Color.HSVToColor( new float[]{ Math.round(h), Math.round(s), Math.round(l) }); + return categoryColorFromName(this.category); } public String categoryLetter() { @@ -229,4 +219,27 @@ public class Geofavorite implements Serializable { return "[" + getName() + " (" + getLat() + "," + getLng() + ")]"; } + + + /** + * Based on Nextcloud Maps's getLetterColor util. + * Assigns a color to a category based on its two first letters. + * + * @see "https://github.com/nextcloud/maps/blob/master/src/utils.js" + * @return the generated color or null for the default category + */ + public static int categoryColorFromName(String category) { + // If category is default, return null: will be used Nextcloud's accent + if (category == null || category.equals(DEFAULT_CATEGORY) || category.length() == 0) + return 0; + + float letter1Index = category.toLowerCase().charAt(0); + float letter2Index = category.toLowerCase().charAt(1); + float letterCoef = ((letter1Index * letter2Index) % 100) / 100; + float h = letterCoef * 360; + float s = 75 + letterCoef * 10; + float l = 50 + letterCoef * 10; + return Color.HSVToColor( new float[]{ Math.round(h), Math.round(s), Math.round(l) }); + } + } diff --git a/app/src/main/java/it/danieleverducci/nextcloudmaps/utils/GeofavoritesFilter.java b/app/src/main/java/it/danieleverducci/nextcloudmaps/utils/GeofavoritesFilter.java index bf3f5b8..f1fb7f5 100644 --- a/app/src/main/java/it/danieleverducci/nextcloudmaps/utils/GeofavoritesFilter.java +++ b/app/src/main/java/it/danieleverducci/nextcloudmaps/utils/GeofavoritesFilter.java @@ -32,7 +32,7 @@ public class GeofavoritesFilter { public List byCategory(String category) { List filteredGeofavorites = new ArrayList<>(); - if (category.isEmpty()) { + if (category == null) { return items; } else { for (Geofavorite geofavorite : items) { diff --git a/app/src/main/res/layout/category_listitem.xml b/app/src/main/res/layout/category_listitem.xml new file mode 100644 index 0000000..0886847 --- /dev/null +++ b/app/src/main/res/layout/category_listitem.xml @@ -0,0 +1,27 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index cf973ab..f353c8c 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -45,6 +45,7 @@ Impossibile ottenere la lista dei geosegnalibri Il filtro per categoria non รจ disponibile al momento Filtra per categoria + Mostra tutti Ordina per diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 52191dd..8d70915 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -44,6 +44,7 @@ Unable to obtain geofavorites list Category filtering is unavailable at the moment Filter by category + Show all Sort by