diff --git a/app/src/googleplay/java/org/tasks/location/GooglePlacesSearchProvider.java b/app/src/googleplay/java/org/tasks/location/GooglePlacesSearchProvider.java index ee50f4357..f52cd4709 100644 --- a/app/src/googleplay/java/org/tasks/location/GooglePlacesSearchProvider.java +++ b/app/src/googleplay/java/org/tasks/location/GooglePlacesSearchProvider.java @@ -43,6 +43,13 @@ public class GooglePlacesSearchProvider implements PlaceSearchProvider { @Override public void saveState(Bundle outState) {} + @Override + public int getAttributionRes(boolean dark) { + return dark + ? R.drawable.places_powered_by_google_dark + : R.drawable.places_powered_by_google_light; + } + @Override public void search( String query, diff --git a/app/src/main/java/org/tasks/location/LocationPickerActivity.java b/app/src/main/java/org/tasks/location/LocationPickerActivity.java index 248971891..57566e746 100644 --- a/app/src/main/java/org/tasks/location/LocationPickerActivity.java +++ b/app/src/main/java/org/tasks/location/LocationPickerActivity.java @@ -122,7 +122,7 @@ public class LocationPickerActivity extends InjectingAppCompatActivity private CompositeDisposable disposables; private MapPosition mapPosition; private LocationPickerAdapter recentsAdapter = new LocationPickerAdapter(this); - private LocationSearchAdapter searchAdapter = new LocationSearchAdapter(this); + private LocationSearchAdapter searchAdapter; private List places = Collections.emptyList(); private int offset; private MenuItem search; @@ -202,7 +202,8 @@ public class LocationPickerActivity extends InjectingAppCompatActivity themeColor.applyToStatusBarIcons(this); themeColor.applyToNavigationBar(this); - map.init(getSupportFragmentManager(), this, theme.getThemeBase().isDarkTheme(this)); + boolean dark = theme.getThemeBase().isDarkTheme(this); + map.init(getSupportFragmentManager(), this, dark); CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams(); @@ -244,6 +245,7 @@ public class LocationPickerActivity extends InjectingAppCompatActivity findViewById(map.getMarkerId()).setVisibility(View.VISIBLE); + searchAdapter = new LocationSearchAdapter(searchProvider.getAttributionRes(dark), this); recentsAdapter.setHasStableIds(true); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(search.isActionViewExpanded() ? searchAdapter : recentsAdapter); diff --git a/app/src/main/java/org/tasks/location/LocationSearchAdapter.java b/app/src/main/java/org/tasks/location/LocationSearchAdapter.java index 530f11d95..62e9033b2 100644 --- a/app/src/main/java/org/tasks/location/LocationSearchAdapter.java +++ b/app/src/main/java/org/tasks/location/LocationSearchAdapter.java @@ -3,36 +3,95 @@ package org.tasks.location; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; import android.widget.TextView; +import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.AsyncDifferConfig; +import androidx.recyclerview.widget.AsyncListDiffer; import androidx.recyclerview.widget.DiffUtil.ItemCallback; -import androidx.recyclerview.widget.ListAdapter; +import androidx.recyclerview.widget.ListUpdateCallback; import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerView.ViewHolder; import com.google.common.base.Strings; +import java.util.List; import org.tasks.R; -import org.tasks.location.LocationSearchAdapter.SearchViewHolder; -public class LocationSearchAdapter extends ListAdapter { +public class LocationSearchAdapter extends RecyclerView.Adapter + implements ListUpdateCallback { + private final int attributionRes; private final OnPredictionPicked callback; + private final AsyncListDiffer differ; - LocationSearchAdapter(OnPredictionPicked callback) { - super(new DiffCallback()); - + LocationSearchAdapter(@DrawableRes int attributionRes, OnPredictionPicked callback) { + this.attributionRes = attributionRes; this.callback = callback; + differ = + new AsyncListDiffer<>(this, new AsyncDifferConfig.Builder<>(new DiffCallback()).build()); } @NonNull @Override - public SearchViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - return new SearchViewHolder( - LayoutInflater.from(parent.getContext()).inflate(R.layout.row_place, parent, false), - callback); + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return viewType == 0 + ? new SearchViewHolder( + LayoutInflater.from(parent.getContext()).inflate(R.layout.row_place, parent, false), + callback) + : new FooterViewHolder( + LayoutInflater.from(parent.getContext()) + .inflate(R.layout.row_place_footer, parent, false), + attributionRes); + } + + void submitList(@Nullable List list) { + differ.submitList(list); } @Override - public void onBindViewHolder(@NonNull SearchViewHolder holder, int position) { - holder.bind(getItem(position)); + public int getItemCount() { + return differ.getCurrentList().size() + 1; + } + + @Override + public int getItemViewType(int position) { + return position < getItemCount() - 1 ? 0 : 1; + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + if (getItemViewType(position) == 0) { + ((SearchViewHolder) holder).bind(differ.getCurrentList().get(position)); + } else { + ((FooterViewHolder) holder).bind(position); + } + } + + @Override + public void onInserted(int position, int count) { + notifyItemRangeInserted(position, count); + updateFooter(); + } + + @Override + public void onRemoved(int position, int count) { + notifyItemRangeRemoved(position, count); + updateFooter(); + } + + @Override + public void onMoved(int fromPosition, int toPosition) { + notifyItemMoved(fromPosition, toPosition); + } + + @Override + public void onChanged(int position, int count, Object payload) { + notifyItemRangeChanged(position, count, payload); + } + + private void updateFooter() { + notifyItemChanged(getItemCount() - 1); } public interface OnPredictionPicked { @@ -57,7 +116,9 @@ public class LocationSearchAdapter extends ListAdapter { @Override diff --git a/app/src/main/java/org/tasks/location/MapboxSearchProvider.java b/app/src/main/java/org/tasks/location/MapboxSearchProvider.java index 5b65ae9f3..db2b23e1e 100644 --- a/app/src/main/java/org/tasks/location/MapboxSearchProvider.java +++ b/app/src/main/java/org/tasks/location/MapboxSearchProvider.java @@ -33,6 +33,11 @@ public class MapboxSearchProvider implements PlaceSearchProvider { @Override public void saveState(Bundle outState) {} + @Override + public int getAttributionRes(boolean dark) { + return R.drawable.mapbox_logo_icon; + } + @Override public void search( String query, diff --git a/app/src/main/java/org/tasks/location/PlaceSearchProvider.java b/app/src/main/java/org/tasks/location/PlaceSearchProvider.java index eaa25af58..2c913c410 100644 --- a/app/src/main/java/org/tasks/location/PlaceSearchProvider.java +++ b/app/src/main/java/org/tasks/location/PlaceSearchProvider.java @@ -1,6 +1,7 @@ package org.tasks.location; import android.os.Bundle; +import androidx.annotation.DrawableRes; import java.util.List; import org.tasks.Callback; import org.tasks.data.Place; @@ -10,6 +11,8 @@ public interface PlaceSearchProvider { void saveState(Bundle outState); + @DrawableRes int getAttributionRes(boolean dark); + void search( String query, MapPosition bias, diff --git a/app/src/main/res/layout/row_place_footer.xml b/app/src/main/res/layout/row_place_footer.xml new file mode 100644 index 000000000..95e057ff0 --- /dev/null +++ b/app/src/main/res/layout/row_place_footer.xml @@ -0,0 +1,22 @@ + + + + + + + +