This commit is contained in:
Nazar-Kutz 2020-05-07 13:57:07 +03:00
parent 9ba43fe2a9
commit 6539a35a20
9 changed files with 508 additions and 30 deletions

View file

@ -6,10 +6,16 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<LinearLayout
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/bg_color"
android:background="?attr/bg_color">
<LinearLayout
android:id="@+id/saveButtonContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:selectableItemBackground"
android:minHeight="56dp"
android:orientation="horizontal">
@ -29,13 +35,15 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding" />
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding" />
</LinearLayout>
</FrameLayout>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"

View file

@ -35,7 +35,6 @@
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:scaleType="centerInside"
android:tint="?attr/default_icon_color"
android:src="@drawable/ic_map"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp" />

View file

@ -11,6 +11,10 @@
Thx - Hardy
-->
<string name="profiles_for_action_not_found">Profiles selected for this action not found.</string>
<string name="change_application_profile">Change application profile</string>
<string name="shared_string_add_profile">Add profile</string>
<string name="quick_action_switch_profile_descr">Taping action button will switch between selected profiles.</string>
<string name="back_to_editing">Back to editing</string>
<string name="reset_deafult_order">Restore default items order</string>
<string name="shared_string_add_edit">Add / Edit Favorite</string>

View file

@ -4,6 +4,7 @@ package net.osmand.plus.dialogs;
import android.app.Activity;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
@ -22,6 +23,7 @@ import androidx.core.widget.NestedScrollView;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
@ -34,8 +36,6 @@ import net.osmand.plus.quickaction.QuickAction;
import net.osmand.plus.quickaction.QuickActionRegistry;
import net.osmand.plus.quickaction.SwitchableAction;
import net.osmand.plus.quickaction.actions.MapStyleAction;
import net.osmand.plus.render.RendererRegistry;
import net.osmand.render.RenderingRulesStorage;
import java.util.List;
@ -45,12 +45,17 @@ public class SelectMapViewQuickActionsBottomSheet extends MenuBottomSheetDialogF
private static final String SELECTED_ITEM_KEY = "selected_item";
public static final String DIALOG_TYPE_KEY = "dialog_type";
public static final String PROFILE_DIALOG_TYPE = "profile_dialog_type";
public static final String MAP_DIALOG_TYPE = "map_dialog_type";
private LinearLayout itemsContainer;
private View.OnClickListener onClickListener;
private ColorStateList rbColorList;
private String selectedItem;
private QuickAction action;
private String dialogType;
@Override
public void createMenuItems(Bundle savedInstanceState) {
@ -63,6 +68,7 @@ public class SelectMapViewQuickActionsBottomSheet extends MenuBottomSheetDialogF
return;
}
long id = args.getLong(SwitchableAction.KEY_ID);
dialogType = args.getString(DIALOG_TYPE_KEY, MAP_DIALOG_TYPE);
OsmandApplication app = mapActivity.getMyApplication();
QuickActionRegistry quickActionRegistry = app.getQuickActionRegistry();
@ -189,7 +195,19 @@ public class SelectMapViewQuickActionsBottomSheet extends MenuBottomSheetDialogF
rb.setChecked(selected);
CompoundButtonCompat.setButtonTintList(rb, rbColorList);
ImageView imageView = (ImageView) view.findViewById(R.id.icon);
imageView.setImageDrawable(getContentIcon(action.getIconRes()));
imageView.setImageDrawable(getItemIcon(tag));
}
private Drawable getItemIcon(String tag) {
if (PROFILE_DIALOG_TYPE.equals(dialogType)) {
ApplicationMode appMode = ApplicationMode.valueOfStringKey(tag, null);
if (appMode != null) {
int iconId = appMode.getIconRes();
int colorId = appMode.getIconColorInfo().getColor(nightMode);
return getIcon(iconId, colorId);
}
}
return getContentIcon(action.getIconRes());
}
@ColorInt

View file

@ -10,6 +10,7 @@ public class ProfileDataObject implements Comparable<ProfileDataObject> {
private int iconRes;
private String stringKey;
private boolean isSelected;
private boolean isEnabled;
private ProfileIconColors iconColor;
public ProfileDataObject(String name, String description, String stringKey, int iconRes, boolean isSelected, ProfileIconColors iconColor) {
@ -41,6 +42,14 @@ public class ProfileDataObject implements Comparable<ProfileDataObject> {
isSelected = selected;
}
public boolean isEnabled() {
return isEnabled;
}
public void setEnabled(boolean enabled) {
isEnabled = enabled;
}
public String getStringKey() {
return stringKey;
}

View file

@ -0,0 +1,161 @@
package net.osmand.plus.profiles;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import net.osmand.CallbackWithObject;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
import net.osmand.plus.settings.NavigationFragment;
import net.osmand.plus.settings.bottomsheets.BasePreferenceBottomSheet;
import java.util.ArrayList;
import java.util.List;
public class SelectMultipleProfileBottomSheet extends BasePreferenceBottomSheet {
public static final String TAG = SelectMultipleProfileBottomSheet.class.getSimpleName();
public static final String SELECTED_KEYS = "selected_keys";
public static final String DISABLED_KEYS = "disabled_keys";
private List<ProfileDataObject> profiles = new ArrayList<>();
private CallbackWithObject<List<String>> callback;
private List<String> selectedProfiles;
private List<String> disabledProfiles;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args != null) {
selectedProfiles = args.getStringArrayList(SELECTED_KEYS);
disabledProfiles = args.getStringArrayList(DISABLED_KEYS);
refreshProfiles(getMyApplication());
}
}
private void refreshProfiles(OsmandApplication app) {
profiles.clear();
profiles.addAll(NavigationFragment.getBaseProfiles(app));
for (ProfileDataObject profile : profiles) {
String key = profile.getStringKey();
profile.setSelected(selectedProfiles.contains(key));
profile.setEnabled(!disabledProfiles.contains(key));
}
}
@Override
public void createMenuItems(Bundle savedInstanceState) {
items.add(new TitleItem(getString(R.string.application_profiles)));
for (int i = 0; i < profiles.size(); i++) {
addProfileItem(profiles.get(i));
}
}
private void addProfileItem(final ProfileDataObject profile) {
OsmandApplication app = requiredMyApplication();
View itemView = UiUtilities.getInflater(app, nightMode)
.inflate(R.layout.bottom_sheet_item_with_descr_and_checkbox_56dp, null);
int profileColorId = profile.getIconColor(nightMode);
int activeColorId = nightMode ?
R.color.active_color_primary_dark : R.color.active_color_primary_light;
int disableColorId = nightMode ?
R.color.icon_color_default_dark : R.color.icon_color_default_light;
boolean enable = profile.isEnabled();
TextView tvTitle = itemView.findViewById(R.id.title);
TextView tvDescription = itemView.findViewById(R.id.description);
ImageView ivIcon = itemView.findViewById(R.id.icon);
final CompoundButton compoundButton = itemView.findViewById(R.id.compound_button);
tvTitle.setText(profile.getName());
tvDescription.setText(profile.getDescription());
if (!enable) {
tvTitle.setTextColor(ContextCompat.getColor(app, disableColorId));
tvDescription.setTextColor(ContextCompat.getColor(app, disableColorId));
}
Drawable drawableIcon = app.getUIUtilities().getIcon(
profile.getIconRes(), enable ? profileColorId : disableColorId);
ivIcon.setImageDrawable(drawableIcon);
UiUtilities.setupCompoundButton(nightMode, ContextCompat.getColor(app,
enable ? activeColorId : disableColorId), compoundButton);
compoundButton.setChecked(profile.isSelected());
View.OnClickListener l = !enable ? null : new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean selected = !profile.isSelected();
profile.setSelected(selected);
compoundButton.setChecked(selected);
}
};
items.add(new BaseBottomSheetItem.Builder()
.setCustomView(itemView)
.setOnClickListener(l)
.create());
}
@Override
protected void onDismissButtonClickAction() {
super.onDismissButtonClickAction();
dismiss();
}
@Override
protected int getRightBottomButtonTextId() {
return R.string.shared_string_apply;
}
@Override
protected void onRightBottomButtonClick() {
if (callback != null) {
List<String> selectedProfileKeys = new ArrayList<>();
for (ProfileDataObject profile : profiles) {
if (profile.isSelected() && profile.isEnabled()) {
selectedProfileKeys.add(profile.getStringKey());
}
}
callback.processResult(selectedProfileKeys);
}
dismiss();
}
public void setCallback(CallbackWithObject<List<String>> callback) {
this.callback = callback;
}
public static void showInstance(@NonNull MapActivity mapActivity,
@Nullable List<String> selectedProfiles,
@Nullable List<String> disabledProfiles,
boolean usedOnMap,
CallbackWithObject<List<String>> callback) {
SelectMultipleProfileBottomSheet fragment = new SelectMultipleProfileBottomSheet();
Bundle args = new Bundle();
args.putStringArrayList(SELECTED_KEYS, selectedProfiles != null ?
new ArrayList<>(selectedProfiles) : new ArrayList<String>());
args.putStringArrayList(DISABLED_KEYS, disabledProfiles != null ?
new ArrayList<>(disabledProfiles) : new ArrayList<String>());
fragment.setArguments(args);
fragment.setUsedOnMap(usedOnMap);
fragment.setCallback(callback);
fragment.show(mapActivity.getSupportFragmentManager(), SelectMultipleProfileBottomSheet.TAG);
}
}

View file

@ -35,6 +35,7 @@ import net.osmand.plus.quickaction.actions.ShowHideFavoritesAction;
import net.osmand.plus.quickaction.actions.ShowHideGpxTracksAction;
import net.osmand.plus.quickaction.actions.ShowHidePoiAction;
import net.osmand.plus.quickaction.actions.ShowHideTransportLinesAction;
import net.osmand.plus.quickaction.actions.SwitchProfileAction;
import net.osmand.util.Algorithms;
import java.lang.reflect.Type;
@ -234,6 +235,7 @@ public class QuickActionRegistry {
quickActionTypes.add(NavAutoZoomMapAction.TYPE);
quickActionTypes.add(NavStartStopAction.TYPE);
quickActionTypes.add(NavResumePauseAction.TYPE);
quickActionTypes.add(SwitchProfileAction.TYPE);
OsmandPlugin.registerQuickActionTypesPlugins(quickActionTypes);
Map<Integer, QuickActionType> quickActionTypesInt = new TreeMap<>();

View file

@ -1,6 +1,7 @@
package net.osmand.plus.quickaction;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@ -11,6 +12,8 @@ import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.ColorRes;
import androidx.annotation.DrawableRes;
import androidx.annotation.StringRes;
import androidx.appcompat.widget.SwitchCompat;
import androidx.core.view.MotionEventCompat;
@ -28,6 +31,9 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static net.osmand.plus.dialogs.SelectMapViewQuickActionsBottomSheet.DIALOG_TYPE_KEY;
import static net.osmand.plus.dialogs.SelectMapViewQuickActionsBottomSheet.MAP_DIALOG_TYPE;
public abstract class SwitchableAction<T> extends QuickAction {
public static final String KEY_ID = "id";
@ -57,10 +63,17 @@ public abstract class SwitchableAction<T> extends QuickAction {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.quick_action_switchable_action, parent, false);
SwitchCompat showDialog = (SwitchCompat) view.findViewById(R.id.saveButton);
final SwitchCompat showDialog = (SwitchCompat) view.findViewById(R.id.saveButton);
if (!getParams().isEmpty()) {
showDialog.setChecked(Boolean.valueOf(getParams().get(KEY_DIALOG)));
}
view.findViewById(R.id.saveButtonContainer).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean selected = showDialog.isChecked();
showDialog.setChecked(!selected);
}
});
RecyclerView list = (RecyclerView) view.findViewById(R.id.list);
Adapter adapter = new Adapter(activity, new QuickActionListFragment.OnStartDragListener() {
@ -112,9 +125,14 @@ public abstract class SwitchableAction<T> extends QuickAction {
public abstract String getTranslatedItemName(Context context, String item);
protected void showChooseDialog(FragmentManager fm) {
showChooseDialog(fm, MAP_DIALOG_TYPE);
}
protected void showChooseDialog(FragmentManager fm, String dialogType) {
SelectMapViewQuickActionsBottomSheet fragment = new SelectMapViewQuickActionsBottomSheet();
Bundle args = new Bundle();
args.putLong(KEY_ID, id);
args.putString(DIALOG_TYPE_KEY, dialogType);
fragment.setArguments(args);
fragment.show(fm, SelectMapViewQuickActionsBottomSheet.TAG);
}
@ -145,6 +163,12 @@ public abstract class SwitchableAction<T> extends QuickAction {
public void onBindViewHolder(final Adapter.ItemHolder holder, final int position) {
final T item = itemsList.get(position);
OsmandApplication app = (OsmandApplication) context.getApplicationContext();
Drawable icon = app.getUIUtilities().getIcon(
getItemIconRes(app, item), getItemIconColorRes(app, item));
holder.icon.setImageDrawable(icon);
holder.title.setText(getItemName(context, item));
holder.handleView.setOnTouchListener(new View.OnTouchListener() {
@ -181,6 +205,10 @@ public abstract class SwitchableAction<T> extends QuickAction {
return itemsList.size();
}
public List<T> getItemsList() {
return itemsList;
}
public void deleteItem(int position) {
if (position == -1) {
@ -262,6 +290,7 @@ public abstract class SwitchableAction<T> extends QuickAction {
public TextView title;
public ImageView handleView;
public ImageView closeBtn;
public ImageView icon;
public ItemHolder(View itemView) {
super(itemView);
@ -269,6 +298,7 @@ public abstract class SwitchableAction<T> extends QuickAction {
title = (TextView) itemView.findViewById(R.id.title);
handleView = (ImageView) itemView.findViewById(R.id.handle_view);
closeBtn = (ImageView) itemView.findViewById(R.id.closeImageButton);
icon = (ImageView) itemView.findViewById(R.id.imageView);
}
}
}
@ -279,6 +309,17 @@ public abstract class SwitchableAction<T> extends QuickAction {
protected abstract String getItemName(Context context, T item);
@DrawableRes
protected int getItemIconRes(Context context, T item) {
return R.drawable.ic_map;
}
@ColorRes
protected int getItemIconColorRes(OsmandApplication app, T item) {
boolean nightMode = !app.getSettings().isLightContent();
return nightMode ? R.color.icon_color_default_dark : R.color.icon_color_default_light;
}
protected abstract
@StringRes
int getAddBtnText();

View file

@ -0,0 +1,236 @@
package net.osmand.plus.quickaction.actions;
import android.content.Context;
import android.text.TextUtils;
import android.view.View;
import android.widget.Toast;
import androidx.appcompat.widget.SwitchCompat;
import androidx.core.util.Pair;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import net.osmand.CallbackWithObject;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.profiles.SelectMultipleProfileBottomSheet;
import net.osmand.plus.quickaction.QuickAction;
import net.osmand.plus.quickaction.QuickActionType;
import net.osmand.plus.quickaction.SwitchableAction;
import net.osmand.plus.views.MapQuickActionLayer;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import static net.osmand.plus.dialogs.SelectMapViewQuickActionsBottomSheet.PROFILE_DIALOG_TYPE;
public class SwitchProfileAction extends SwitchableAction<Pair<String, String>> {
private final static String KEY_PROFILES = "profiles";
public static final QuickActionType TYPE = new QuickActionType(32,
"profile.change", SwitchProfileAction.class)
.nameRes(R.string.change_application_profile)
.iconRes(R.drawable.ic_action_manage_profiles)
.category(QuickActionType.NAVIGATION);
public SwitchProfileAction() {
super(TYPE);
}
public SwitchProfileAction(QuickAction quickAction) {
super(quickAction);
}
@Override
protected String getTitle(List<Pair<String, String>> filters) {
List<String> profileNames = new ArrayList<>();
for (Pair<String, String> p : filters) {
profileNames.add(p.second);
}
return TextUtils.join(", ", profileNames);
}
@Override
protected void saveListToParams(List<Pair<String, String>> list) {
getParams().put(getListKey(), new Gson().toJson(list));
}
@Override
public List<Pair<String, String>> loadListFromParams() {
String json = getParams().get(getListKey());
if (json == null || json.isEmpty()) return new ArrayList<>();
Type listType = new TypeToken<ArrayList<Pair<String, String>>>() {
}.getType();
List<Pair<String, String>> list = new Gson().fromJson(json, listType);
Iterator<Pair<String, String>> it = list.iterator();
while (it.hasNext()) {
ApplicationMode appMode = getModeForKey(it.next().first);
if (appMode == null) {
it.remove();
}
}
return list;
}
@Override
public void execute(MapActivity activity) {
OsmandSettings settings = activity.getMyApplication().getSettings();
List<Pair<String, String>> profiles = loadListFromParams();
if (profiles.size() == 0) {
Toast.makeText(activity, activity.getString(R.string.profiles_for_action_not_found),
Toast.LENGTH_SHORT).show();
return;
}
boolean showDialog = Boolean.valueOf(getParams().get(KEY_DIALOG));
if (showDialog) {
showChooseDialog(activity.getSupportFragmentManager(), PROFILE_DIALOG_TYPE);
return;
}
int index = -1;
final String currentSource = settings.getApplicationMode().getStringKey();
for (int idx = 0; idx < profiles.size(); idx++) {
if (currentSource.equals(profiles.get(idx).first)) {
index = idx;
break;
}
}
String nextSource = profiles.get(0).first;
if (index >= 0 && index + 1 < profiles.size()) {
nextSource = profiles.get(index + 1).first;
}
executeWithParams(activity, nextSource);
super.execute(activity);
}
@Override
public void executeWithParams(MapActivity activity, String params) {
OsmandApplication app = activity.getMyApplication();
OsmandSettings settings = app.getSettings();
ApplicationMode appMode = getModeForKey(params);
if (appMode != null) {
settings.APPLICATION_MODE.set(appMode);
app.getQuickActionRegistry().setQuickActionFabState(true);
MapQuickActionLayer mil = activity.getMapLayers().getMapQuickActionLayer();
if (mil != null) {
mil.refreshLayer();
}
String message = String.format(activity.getString(
R.string.application_profile_changed), appMode.toHumanString());
Toast.makeText(activity, message, Toast.LENGTH_SHORT).show();
}
}
@Override
public String getTranslatedItemName(Context context, String item) {
return getModeForKey(item).toHumanString();
}
@Override
protected String getItemName(Context context, Pair<String, String> item) {
return item.second;
}
@Override
protected int getAddBtnText() {
return R.string.shared_string_add_profile;
}
@Override
protected int getDiscrHint() {
return R.string.quick_action_switch_profile_descr;
}
@Override
protected int getDiscrTitle() {
return R.string.application_profiles;
}
@Override
protected String getListKey() {
return KEY_PROFILES;
}
@Override
protected int getItemIconRes(Context context, Pair<String, String> item) {
ApplicationMode appMode = getModeForKey(item.first);
if (appMode != null) {
return appMode.getIconRes();
}
return super.getItemIconRes(context, item);
}
@Override
protected int getItemIconColorRes(OsmandApplication app, Pair<String, String> item) {
ApplicationMode appMode = getModeForKey(item.first);
if (appMode != null) {
boolean nightMode = !app.getSettings().isLightContent();
return appMode.getIconColorInfo().getColor(nightMode);
}
return super.getItemIconColorRes(app, item);
}
@Override
protected View.OnClickListener getOnAddBtnClickListener(final MapActivity activity, final Adapter adapter) {
return new View.OnClickListener() {
@Override
public void onClick(View v) {
List<String> selectedProfilesKeys = new ArrayList<>();
for (Pair<String, String> item : adapter.getItemsList()) {
selectedProfilesKeys.add(item.first);
}
SelectMultipleProfileBottomSheet.showInstance(activity, selectedProfilesKeys,
selectedProfilesKeys, false, new CallbackWithObject<List<String>>() {
@Override
public boolean processResult(List<String> result) {
if (result == null || result.size() == 0) {
return false;
}
for (String item : result) {
ApplicationMode appMode = getModeForKey(item);
if (appMode != null) {
Pair<String, String> profile = new Pair<>(
appMode.getStringKey(), appMode.toHumanString());
adapter.addItem(profile, activity);
}
}
return true;
}
});
}
};
}
private ApplicationMode getModeForKey(String key) {
return ApplicationMode.valueOfStringKey(key, null);
}
@Override
public boolean fillParams(View root, MapActivity activity) {
getParams().put(KEY_DIALOG, Boolean.toString(((SwitchCompat) root.findViewById(R.id.saveButton)).isChecked()));
return super.fillParams(root, activity);
}
}