forked from organicmaps/organicmaps
[android] Customized the promo category for search to make it reusable for different promo actions and providers
This commit is contained in:
parent
c294eca849
commit
658a8e26aa
9 changed files with 189 additions and 82 deletions
BIN
android/res/drawable-mdpi/ic_category_taxi.png
Normal file
BIN
android/res/drawable-mdpi/ic_category_taxi.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1 KiB |
|
@ -2,6 +2,7 @@ package com.mapswithme.maps.search;
|
|||
|
||||
import android.content.res.Resources;
|
||||
import android.support.annotation.DrawableRes;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.StringRes;
|
||||
|
@ -16,8 +17,17 @@ import com.mapswithme.maps.R;
|
|||
import com.mapswithme.util.ThemeUtils;
|
||||
import com.mapswithme.util.statistics.Statistics;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
class CategoriesAdapter extends RecyclerView.Adapter<CategoriesAdapter.ViewHolder>
|
||||
{
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({ TYPE_CATEGORY, TYPE_PROMO_CATEGORY })
|
||||
@interface ViewType {}
|
||||
private static final int TYPE_CATEGORY = 0;
|
||||
private static final int TYPE_PROMO_CATEGORY = 1;
|
||||
|
||||
@StringRes
|
||||
private final int mCategoryResIds[];
|
||||
@DrawableRes
|
||||
|
@ -28,18 +38,19 @@ class CategoriesAdapter extends RecyclerView.Adapter<CategoriesAdapter.ViewHolde
|
|||
|
||||
interface OnCategorySelectedListener
|
||||
{
|
||||
void onCategorySelected(@Nullable String category);
|
||||
void onSearchCategorySelected(@Nullable String category);
|
||||
void onPromoCategorySelected(@NonNull PromoCategory promo);
|
||||
}
|
||||
|
||||
private OnCategorySelectedListener mListener;
|
||||
|
||||
CategoriesAdapter(Fragment fragment)
|
||||
CategoriesAdapter(@NonNull Fragment fragment)
|
||||
{
|
||||
final String packageName = fragment.getActivity().getPackageName();
|
||||
final boolean isNightTheme = ThemeUtils.isNightTheme();
|
||||
final Resources resources = fragment.getActivity().getResources();
|
||||
|
||||
final String[] keys = DisplayedCategories.getKeys();
|
||||
final String[] keys = getAllCategories();
|
||||
final int numKeys = keys.length;
|
||||
|
||||
mCategoryResIds = new int[numKeys];
|
||||
|
@ -47,16 +58,7 @@ class CategoriesAdapter extends RecyclerView.Adapter<CategoriesAdapter.ViewHolde
|
|||
for (int i = 0; i < numKeys; i++)
|
||||
{
|
||||
String key = keys[i];
|
||||
|
||||
mCategoryResIds[i] = resources.getIdentifier(key, "string", packageName);
|
||||
PromoCategory promo = PromoCategory.findByKey(key);
|
||||
if (promo != null)
|
||||
{
|
||||
Statistics.INSTANCE.trackSponsoredEventForCustomProvider(
|
||||
Statistics.EventName.SEARCH_SPONSOR_CATEGORY_SHOWN,
|
||||
promo.getStatisticValue());
|
||||
mCategoryResIds[i] = promo.getStringId();
|
||||
}
|
||||
|
||||
if (mCategoryResIds[i] == 0)
|
||||
throw new IllegalStateException("Can't get string resource id for category:" + key);
|
||||
|
@ -75,24 +77,58 @@ class CategoriesAdapter extends RecyclerView.Adapter<CategoriesAdapter.ViewHolde
|
|||
mInflater = LayoutInflater.from(fragment.getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position)
|
||||
@NonNull
|
||||
private static String[] getAllCategories()
|
||||
{
|
||||
return R.layout.item_search_category;
|
||||
String[] searchCategories = DisplayedCategories.getKeys();
|
||||
PromoCategory[] promos = PromoCategory.values();
|
||||
int amountSize = searchCategories.length + promos.length;
|
||||
String[] allCategories = new String[amountSize];
|
||||
for (PromoCategory promo : promos)
|
||||
{
|
||||
if (promo.getPosition() >= amountSize)
|
||||
throw new AssertionError("Promo position must in range: "
|
||||
+ "[0 - " + amountSize + ")");
|
||||
|
||||
allCategories[promo.getPosition()] = promo.getKey();
|
||||
}
|
||||
|
||||
for (int i = 0, j = 0; i < amountSize; i++)
|
||||
{
|
||||
if (allCategories[i] == null)
|
||||
{
|
||||
allCategories[i] = searchCategories[j];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
return allCategories;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
|
||||
@ViewType
|
||||
public int getItemViewType(int position)
|
||||
{
|
||||
PromoCategory promo = PromoCategory.findByStringId(mCategoryResIds[position]);
|
||||
if (promo != null)
|
||||
return TYPE_PROMO_CATEGORY;
|
||||
return TYPE_CATEGORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, @ViewType int viewType)
|
||||
{
|
||||
final View view;
|
||||
if (viewType == R.layout.item_search_category_luggage)
|
||||
{
|
||||
view = mInflater.inflate(R.layout.item_search_category_luggage, parent, false);
|
||||
return new ViewHolder(view, (TextView) view.findViewById(R.id.tv__category));
|
||||
}
|
||||
|
||||
view = mInflater.inflate(R.layout.item_search_category, parent, false);
|
||||
return new ViewHolder(view, (TextView)view);
|
||||
switch (viewType)
|
||||
{
|
||||
case TYPE_CATEGORY:
|
||||
return new ViewHolder(view, (TextView) view);
|
||||
case TYPE_PROMO_CATEGORY:
|
||||
return new PromoViewHolder(view, (TextView) view);
|
||||
default:
|
||||
throw new AssertionError("Unsupported type detected: " + viewType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -107,16 +143,44 @@ class CategoriesAdapter extends RecyclerView.Adapter<CategoriesAdapter.ViewHolde
|
|||
return mCategoryResIds.length;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private String getSuggestionFromCategory(@StringRes int resId)
|
||||
private class PromoViewHolder extends ViewHolder
|
||||
{
|
||||
PromoCategory promoCategory = PromoCategory.findByStringId(resId);
|
||||
if (promoCategory != null)
|
||||
return promoCategory.getKey();
|
||||
return mResources.getString(resId) + ' ';
|
||||
PromoViewHolder(@NonNull View v, @NonNull TextView tv)
|
||||
{
|
||||
super(v, tv);
|
||||
}
|
||||
|
||||
@Override
|
||||
void onItemClicked(int position)
|
||||
{
|
||||
@StringRes
|
||||
int categoryId = mCategoryResIds[position];
|
||||
PromoCategory promo = PromoCategory.findByStringId(categoryId);
|
||||
if (promo != null)
|
||||
{
|
||||
String event = Statistics.EventName.SEARCH_SPONSOR_CATEGORY_SELECTED;
|
||||
Statistics.INSTANCE.trackSearchPromoCategory(event, promo.getProvider());
|
||||
if (mListener != null)
|
||||
mListener.onPromoCategorySelected(promo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void setTextAndIcon(int textResId, int iconResId)
|
||||
{
|
||||
super.setTextAndIcon(textResId, iconResId);
|
||||
@StringRes
|
||||
int categoryId = mCategoryResIds[getAdapterPosition()];
|
||||
PromoCategory promo = PromoCategory.findByStringId(categoryId);
|
||||
if (promo != null)
|
||||
{
|
||||
String event = Statistics.EventName.SEARCH_SPONSOR_CATEGORY_SHOWN;
|
||||
Statistics.INSTANCE.trackSearchPromoCategory(event, promo.getProvider());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
|
||||
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
|
||||
{
|
||||
@NonNull
|
||||
private final TextView mTitle;
|
||||
|
@ -129,12 +193,22 @@ class CategoriesAdapter extends RecyclerView.Adapter<CategoriesAdapter.ViewHolde
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
public final void onClick(View v)
|
||||
{
|
||||
final int position = getAdapterPosition();
|
||||
Statistics.INSTANCE.trackSearchCategoryClicked(mResources.getResourceEntryName(mCategoryResIds[position]));
|
||||
onItemClicked(position);
|
||||
}
|
||||
|
||||
void onItemClicked(int position)
|
||||
{
|
||||
String categoryEntryName = mResources.getResourceEntryName(mCategoryResIds[position]);
|
||||
Statistics.INSTANCE.trackSearchCategoryClicked(categoryEntryName);
|
||||
if (mListener != null)
|
||||
mListener.onCategorySelected(getSuggestionFromCategory(mCategoryResIds[position]));
|
||||
{
|
||||
@StringRes
|
||||
int categoryId = mCategoryResIds[position];
|
||||
mListener.onSearchCategorySelected(mResources.getString(categoryId) + " ");
|
||||
}
|
||||
}
|
||||
|
||||
void setTextAndIcon(@StringRes int textResId, @DrawableRes int iconResId)
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
package com.mapswithme.maps.search;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
class DisplayedCategories
|
||||
{
|
||||
public static String[] getKeys() { return nativeGetKeys(); }
|
||||
@NonNull
|
||||
public static String[] getKeys()
|
||||
{
|
||||
return nativeGetKeys();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static native String[] nativeGetKeys();
|
||||
}
|
||||
|
|
|
@ -1,34 +1,47 @@
|
|||
package com.mapswithme.maps.search;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.mapswithme.util.UiUtils;
|
||||
import com.mapswithme.maps.R;
|
||||
|
||||
public enum PromoCategory
|
||||
{
|
||||
STUB
|
||||
RUTAXI
|
||||
{
|
||||
@NonNull
|
||||
@Override
|
||||
String getKey()
|
||||
{
|
||||
return "";
|
||||
return "taxi";
|
||||
}
|
||||
|
||||
@Override
|
||||
int getStringId()
|
||||
{
|
||||
return UiUtils.NO_ID;
|
||||
return R.string.taxi;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
String getStatisticValue()
|
||||
String getProvider()
|
||||
{
|
||||
return "";
|
||||
return "RuTaxi";
|
||||
}
|
||||
|
||||
@Override
|
||||
int getPosition()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
PromoCategoryProcessor createProcessor(@NonNull Context context)
|
||||
{
|
||||
return new RutaxiPromoProcessor(context);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -39,7 +52,12 @@ public enum PromoCategory
|
|||
abstract int getStringId();
|
||||
|
||||
@NonNull
|
||||
abstract String getStatisticValue();
|
||||
abstract String getProvider();
|
||||
|
||||
abstract int getPosition();
|
||||
|
||||
@NonNull
|
||||
abstract PromoCategoryProcessor createProcessor(@NonNull Context context);
|
||||
|
||||
@Nullable
|
||||
static PromoCategory findByStringId(@StringRes int nameId)
|
||||
|
@ -51,18 +69,4 @@ public enum PromoCategory
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static PromoCategory findByKey(@Nullable String key)
|
||||
{
|
||||
if (TextUtils.isEmpty(key))
|
||||
return null;
|
||||
|
||||
for (PromoCategory cat : values())
|
||||
{
|
||||
if (cat.getKey().equals(key))
|
||||
return cat;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package com.mapswithme.maps.search;
|
||||
|
||||
public interface PromoCategoryProcessor
|
||||
{
|
||||
void process();
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.mapswithme.maps.search;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.mapswithme.util.Utils;
|
||||
|
||||
public class RutaxiPromoProcessor implements PromoCategoryProcessor
|
||||
{
|
||||
@NonNull
|
||||
private final Context mContext;
|
||||
|
||||
RutaxiPromoProcessor(@NonNull Context context)
|
||||
{
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process()
|
||||
{
|
||||
// TODO: added app launch when product desicion is ready.
|
||||
Utils.openUrl(mContext, "https://go.onelink.me/757212956/a81b5d7c");
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@ package com.mapswithme.maps.search;
|
|||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
|
||||
import com.mapswithme.maps.R;
|
||||
import com.mapswithme.maps.base.BaseMwmRecyclerFragment;
|
||||
|
@ -31,18 +30,25 @@ public class SearchCategoriesFragment extends BaseMwmRecyclerFragment<Categories
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onCategorySelected(String category)
|
||||
public void onSearchCategorySelected(String category)
|
||||
{
|
||||
if (!passCategory(getParentFragment(), category))
|
||||
passCategory(getActivity(), category);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPromoCategorySelected(@NonNull PromoCategory promo)
|
||||
{
|
||||
PromoCategoryProcessor processor = promo.createProcessor(getContext().getApplicationContext());
|
||||
processor.process();
|
||||
}
|
||||
|
||||
private static boolean passCategory(Object listener, String category)
|
||||
{
|
||||
if (!(listener instanceof CategoriesAdapter.OnCategorySelectedListener))
|
||||
return false;
|
||||
|
||||
((CategoriesAdapter.OnCategorySelectedListener)listener).onCategorySelected(category);
|
||||
((CategoriesAdapter.OnCategorySelectedListener)listener).onSearchCategorySelected(category);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,9 +129,6 @@ public class SearchFragment extends BaseMwmFragment
|
|||
return;
|
||||
}
|
||||
|
||||
if (mPromoCategorySelected)
|
||||
return;
|
||||
|
||||
if (mAdsLoader != null && !isTabletSearch() && query.length() >= MIN_QUERY_LENGTH_FOR_AD)
|
||||
{
|
||||
mAdsRequested = true;
|
||||
|
@ -211,7 +208,6 @@ public class SearchFragment extends BaseMwmFragment
|
|||
|
||||
private final LastPosition mLastPosition = new LastPosition();
|
||||
private boolean mSearchRunning;
|
||||
private boolean mPromoCategorySelected;
|
||||
private String mInitialQuery;
|
||||
@Nullable
|
||||
private String mInitialLocale;
|
||||
|
@ -710,24 +706,15 @@ public class SearchFragment extends BaseMwmFragment
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onCategorySelected(@Nullable String category)
|
||||
public void onSearchCategorySelected(@Nullable String category)
|
||||
{
|
||||
PromoCategory promoCategory = PromoCategory.findByKey(category);
|
||||
if (promoCategory != null)
|
||||
{
|
||||
mPromoCategorySelected = true;
|
||||
mToolbarController.setQuery(category + " ");
|
||||
mToolbarController.setQuery(category);
|
||||
}
|
||||
|
||||
Statistics.INSTANCE.trackSponsoredEventForCustomProvider(
|
||||
Statistics.EventName.SEARCH_SPONSOR_CATEGORY_SELECTED,
|
||||
promoCategory.getStatisticValue());
|
||||
showAllResultsOnMap();
|
||||
mPromoCategorySelected = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
mToolbarController.setQuery(category);
|
||||
}
|
||||
@Override
|
||||
public void onPromoCategorySelected(@NonNull PromoCategory promo)
|
||||
{
|
||||
// Do nothing by default.
|
||||
}
|
||||
|
||||
private void refreshSearchResults()
|
||||
|
|
|
@ -16,12 +16,12 @@ import com.android.billingclient.api.BillingClient;
|
|||
import com.facebook.ads.AdError;
|
||||
import com.facebook.appevents.AppEventsLogger;
|
||||
import com.mapswithme.maps.BuildConfig;
|
||||
import com.mapswithme.maps.analytics.ExternalLibrariesMediator;
|
||||
import com.mapswithme.maps.Framework;
|
||||
import com.mapswithme.maps.MwmApplication;
|
||||
import com.mapswithme.maps.PrivateVariables;
|
||||
import com.mapswithme.maps.ads.MwmNativeAd;
|
||||
import com.mapswithme.maps.ads.NativeAdError;
|
||||
import com.mapswithme.maps.analytics.ExternalLibrariesMediator;
|
||||
import com.mapswithme.maps.api.ParsedMwmRequest;
|
||||
import com.mapswithme.maps.bookmarks.data.BookmarkManager;
|
||||
import com.mapswithme.maps.bookmarks.data.MapObject;
|
||||
|
@ -955,8 +955,7 @@ public enum Statistics
|
|||
.get());
|
||||
}
|
||||
|
||||
public void trackSponsoredEventForCustomProvider(@NonNull String eventName,
|
||||
@NonNull String provider)
|
||||
public void trackSearchPromoCategory(@NonNull String eventName, @NonNull String provider)
|
||||
{
|
||||
trackEvent(eventName, Statistics.params().add(PROVIDER, provider).get());
|
||||
MyTracker.trackEvent(eventName + "_" + provider);
|
||||
|
|
Loading…
Add table
Reference in a new issue