Implement icon radio toggle

Implement landscape for Plan Route
This commit is contained in:
nazar-kutz 2021-04-19 16:49:03 +03:00
parent aa846ab405
commit ced9a3555e
14 changed files with 349 additions and 133 deletions

View file

@ -53,6 +53,19 @@
android:background="@null"
tools:src="@drawable/ic_action_ruler"/>
<include
layout="@layout/custom_icon_radio_buttons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginEnd="@dimen/content_padding_half"
android:layout_marginLeft="@dimen/bottom_sheet_content_margin"
android:layout_marginRight="@dimen/content_padding_half"
android:layout_marginStart="@dimen/bottom_sheet_content_margin"
android:background="@null" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/up_down_button"
android:layout_width="wrap_content"
@ -65,6 +78,7 @@
android:layout_marginRight="@dimen/bottom_sheet_content_margin"
android:layout_marginStart="@dimen/bottom_sheet_content_margin"
android:background="@null"
android:visibility="gone"
tools:src="@drawable/ic_action_arrow_down"/>
<TextView

View file

@ -659,6 +659,7 @@
<!-- CENTER -->
<FrameLayout
android:id="@+id/top_controls_container"
android:layout_width="fill_parent"
android:layout_height="wrap_content">

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/custom_radio_buttons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/btn_bg_border_inactive"
android:baselineAligned="false"
android:minHeight="@dimen/dialog_button_height"
android:orientation="horizontal">
<include
layout="@layout/custom_radio_btn_icon_item"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<include
layout="@layout/custom_radio_btn_icon_item"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:background="?attr/selectableItemBackground"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="@dimen/content_padding_small_half"
android:paddingBottom="@dimen/content_padding_small_half"
android:paddingLeft="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding_small">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/icon"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="@dimen/standard_icon_size"
android:layout_gravity="center"
tools:src="@drawable/ic_action_info_dark"/>
</FrameLayout>

View file

@ -4,6 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/list_background_color"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView

View file

@ -42,9 +42,10 @@ import net.osmand.plus.liveupdates.LiveUpdatesHelper.UpdateFrequency;
import net.osmand.plus.resources.IncrementalChangesManager;
import net.osmand.plus.settings.backend.CommonPreference;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.widgets.MultiStateToggleButton;
import net.osmand.plus.widgets.MultiStateToggleButton.OnRadioItemClickListener;
import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem;
import net.osmand.plus.widgets.multistatetoggle.RadioItem;
import net.osmand.plus.widgets.multistatetoggle.RadioItem.OnRadioItemClickListener;
import net.osmand.plus.widgets.multistatetoggle.TextToggleButton;
import net.osmand.plus.widgets.multistatetoggle.TextToggleButton.TextRadioItem;
import net.osmand.plus.widgets.TextViewEx;
import net.osmand.plus.widgets.style.CustomTypefaceSpan;
import net.osmand.util.Algorithms;
@ -83,8 +84,8 @@ public class LiveUpdatesSettingsBottomSheet extends MenuBottomSheetDialogFragmen
private BaseBottomSheetItem itemFrequencyHelpMessage;
private BaseBottomSheetItem itemClear;
private BaseBottomSheetItem itemViaWiFi;
private MultiStateToggleButton frequencyToggleButton;
private MultiStateToggleButton timeOfDayToggleButton;
private TextToggleButton frequencyToggleButton;
private TextToggleButton timeOfDayToggleButton;
private String fileName;
private OnLiveUpdatesForLocalChange onLiveUpdatesForLocalChange;
@ -195,9 +196,9 @@ public class LiveUpdatesSettingsBottomSheet extends MenuBottomSheetDialogFragmen
String morning = getString(R.string.morning);
String night = getString(R.string.night);
RadioItem morningButton = new RadioItem(morning);
RadioItem nightButton = new RadioItem(night);
timeOfDayToggleButton = new MultiStateToggleButton(app, itemTimeOfDayButtons, nightMode);
TextRadioItem morningButton = new TextRadioItem(morning);
TextRadioItem nightButton = new TextRadioItem(night);
timeOfDayToggleButton = new TextToggleButton(app, itemTimeOfDayButtons, nightMode);
timeOfDayToggleButton.setItems(morningButton, nightButton);
setSelectedRadioItem(timeOfDayToggleButton, timeOfDayPreference.get(), morningButton, nightButton);
timeOfDayToggleButton.updateView(localUpdatePreference.get());
@ -231,10 +232,10 @@ public class LiveUpdatesSettingsBottomSheet extends MenuBottomSheetDialogFragmen
String hourly = getString(R.string.hourly);
String daily = getString(R.string.daily);
String weekly = getString(R.string.weekly);
RadioItem hourlyButton = new RadioItem(hourly);
RadioItem dailyButton = new RadioItem(daily);
RadioItem weeklyButton = new RadioItem(weekly);
frequencyToggleButton = new MultiStateToggleButton(app, itemFrequencyButtons, nightMode);
TextRadioItem hourlyButton = new TextRadioItem(hourly);
TextRadioItem dailyButton = new TextRadioItem(daily);
TextRadioItem weeklyButton = new TextRadioItem(weekly);
frequencyToggleButton = new TextToggleButton(app, itemFrequencyButtons, nightMode);
frequencyToggleButton.setItems(hourlyButton, dailyButton, weeklyButton);
setSelectedRadioItem(frequencyToggleButton, frequencyPreference.get(), hourlyButton, dailyButton, weeklyButton);
frequencyToggleButton.updateView(localUpdatePreference.get());
@ -467,7 +468,7 @@ public class LiveUpdatesSettingsBottomSheet extends MenuBottomSheetDialogFragmen
return dividerItem;
}
private void setSelectedRadioItem(MultiStateToggleButton toggleButton, int position, RadioItem... buttons) {
private void setSelectedRadioItem(TextToggleButton toggleButton, int position, TextRadioItem... buttons) {
toggleButton.setSelectedItem(buttons[position]);
}

View file

@ -24,6 +24,7 @@ import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.LineGraphType;
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter;
@ -109,9 +110,16 @@ public class GraphsCard extends BaseCard implements OnUpdateInfoListener {
GraphAdapterHelper.bindGraphAdapters(commonGraphAdapter, Collections.singletonList((BaseGraphAdapter) customGraphAdapter), (ViewGroup) view);
refreshMapCallback = GraphAdapterHelper.bindToMap(commonGraphAdapter, mapActivity, trackDetailsMenu);
updateTopPadding();
fullUpdate();
}
private void updateTopPadding() {
int topPadding = AndroidUiHelper.isOrientationPortrait(mapActivity) ?
0 : app.getResources().getDimensionPixelSize(R.dimen.content_padding_small);
view.setPadding(0, topPadding, 0, 0);
}
@Override
public int getCardLayoutId() {
return R.layout.measurement_tool_graph_card;

View file

@ -11,6 +11,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
@ -82,9 +83,13 @@ import net.osmand.plus.views.layers.MapControlsLayer.MapControlsThemeInfoProvide
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarControllerType;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarView;
import net.osmand.plus.widgets.MultiStateToggleButton;
import net.osmand.plus.widgets.MultiStateToggleButton.OnRadioItemClickListener;
import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem;
import net.osmand.plus.widgets.multistatetoggle.IconToggleButton;
import net.osmand.plus.widgets.multistatetoggle.IconToggleButton.IconRadioItem;
import net.osmand.plus.widgets.multistatetoggle.MultiStateToggleButton;
import net.osmand.plus.widgets.multistatetoggle.RadioItem;
import net.osmand.plus.widgets.multistatetoggle.RadioItem.OnRadioItemClickListener;
import net.osmand.plus.widgets.multistatetoggle.TextToggleButton;
import net.osmand.plus.widgets.multistatetoggle.TextToggleButton.TextRadioItem;
import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation;
import net.osmand.util.Algorithms;
@ -130,6 +135,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
private RadioItem graphBtn;
private View mainView;
private View bottomMapControls;
private View topMapControls;
private ImageView upDownBtn;
private ImageView undoBtn;
private ImageView redoBtn;
@ -251,7 +257,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
public void showProgressBar() {
MeasurementToolFragment.this.showProgressBar();
updateInfoView();
updateCardContainerSize();
updateInfoViewAppearance();
}
@Override
@ -264,7 +270,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
((ProgressBar) mainView.findViewById(R.id.snap_to_road_progress_bar)).setVisibility(View.GONE);
progressBarVisible = false;
updateInfoView();
updateCardContainerSize();
updateInfoViewAppearance();
}
@Override
@ -289,30 +295,37 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
mainView = view.findViewById(R.id.main_view);
AndroidUtils.setBackground(mapActivity, mainView, nightMode, R.drawable.bg_bottom_menu_light, R.drawable.bg_bottom_menu_dark);
detailsMenu = new GraphDetailsMenu();
LinearLayout infoButtonsContainer = mainView.findViewById(R.id.custom_radio_buttons);
if (portrait) {
cardsContainer = mainView.findViewById(R.id.cards_container);
infoTypeBtn = new TextToggleButton(app, infoButtonsContainer, nightMode);
String pointsBtnTitle = getString(R.string.shared_string_gpx_points);
pointsBtn = new RadioItem(pointsBtnTitle);
pointsBtn.setOnClickListener(getInfoTypeBtnListener(InfoType.POINTS));
pointsBtn = new TextRadioItem(pointsBtnTitle);
String graphBtnTitle = getString(R.string.shared_string_graph);
graphBtn = new RadioItem(graphBtnTitle);
graphBtn.setOnClickListener(getInfoTypeBtnListener(InfoType.GRAPH));
graphBtn = new TextRadioItem(graphBtnTitle);
LinearLayout infoButtonsContainer = mainView.findViewById(R.id.custom_radio_buttons);
infoTypeBtn = new MultiStateToggleButton(app, infoButtonsContainer, nightMode);
infoTypeBtn.setItems(pointsBtn, graphBtn);
} else {
cardsContainer = mapActivity.findViewById(R.id.left_side_menu);
bottomMapControls = mapActivity.findViewById(R.id.bottom_controls_container);
topMapControls = mapActivity.findViewById(R.id.top_controls_container);
infoTypeBtn = new IconToggleButton(app, infoButtonsContainer, nightMode);
pointsBtn = new IconRadioItem(R.drawable.ic_action_plan_route_point_colored, true);
graphBtn = new IconRadioItem(R.drawable.ic_action_analyze_intervals);
ScrollUtils.addOnGlobalLayoutListener(mainView, new Runnable() {
@Override
public void run() {
updateCardContainerSize();
updateInfoViewAppearance();
}
});
}
pointsBtn.setOnClickListener(getInfoTypeBtnListener(InfoType.POINTS));
graphBtn.setOnClickListener(getInfoTypeBtnListener(InfoType.GRAPH));
infoTypeBtn.setItems(pointsBtn, graphBtn);
pointsCard = new PointsCard(mapActivity, this);
graphsCard = new GraphsCard(mapActivity, detailsMenu, this);
@ -348,7 +361,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
public void onClick(View v) {
if (infoExpanded) {
collapseInfoView();
} else if (setInfoType(InfoType.POINTS) && portrait) {
} else if (setInfoType(InfoType.POINTS)) {
infoTypeBtn.setSelectedItem(pointsBtn);
}
}
@ -626,7 +639,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
if (portrait) {
setMapPosition(OsmandSettings.MIDDLE_TOP_CONSTANT);
} else {
shiftBottomMapControls(false);
shiftMapControls(false);
setMapPosition(OsmandSettings.LANDSCAPE_MIDDLE_RIGHT_CONSTANT);
}
cardsContainer.setVisibility(View.VISIBLE);
@ -640,15 +653,14 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
}
private void collapseInfoView() {
cardsContainer.setVisibility(View.GONE);
if (portrait) {
infoTypeBtn.setSelectedItem(null);
} else {
shiftBottomMapControls(true);
}
infoExpanded = false;
currentInfoType = null;
setDefaultMapPosition();
cardsContainer.setVisibility(View.GONE);
if (!portrait) {
shiftMapControls(true);
}
infoTypeBtn.setSelectedItem(null);
moveMapToDefaultPosition();
updateUpDownBtn();
}
@ -676,37 +688,37 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
}
}
private void updateCardContainerSize() {
if (portrait) {
return;
private void updateInfoViewAppearance() {
if (portrait) return;
View toolsPanel = mainView.findViewById(R.id.measure_mode_controls);
View snapToRoadProgress = mainView.findViewById(R.id.snap_to_road_progress_bar);
int infoViewWidth = mainView.getWidth() - toolsPanel.getWidth();
int bottomMargin = toolsPanel.getHeight();
if (progressBarVisible) {
bottomMargin += snapToRoadProgress.getHeight();
}
View measureModeControls = mainView.findViewById(R.id.measure_mode_controls);
int width = mainView.getWidth() - measureModeControls.getWidth();
int bottomMargin = measureModeControls.getHeight();
bottomMargin = progressBarVisible ? bottomMargin + mainView.findViewById(R.id.snap_to_road_progress_bar).getHeight() : bottomMargin;
ViewGroup.MarginLayoutParams params = null;
if (mainView.getParent() instanceof FrameLayout) {
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(width, -1);
params.setMargins(0, 0, 0, bottomMargin);
cardsContainer.setLayoutParams(params);
params = new FrameLayout.LayoutParams(infoViewWidth, -1);
} else if (mainView.getParent() instanceof LinearLayout) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(width, -1);
params.setMargins(0, 0, 0, bottomMargin);
params = new LinearLayout.LayoutParams(infoViewWidth, -1);
}
if (params != null) {
AndroidUtils.setMargins(params, 0, 0, 0, bottomMargin);
cardsContainer.setLayoutParams(params);
}
}
private void shiftBottomMapControls(boolean toInitialPosition) {
if (portrait) {
return;
}
int leftMargin = toInitialPosition ? 0 : cardsContainer.getWidth();
if (bottomMapControls.getParent() instanceof LinearLayout) {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) bottomMapControls.getLayoutParams();
params.setMargins(leftMargin, 0, 0, 0);
} else if (bottomMapControls.getParent() instanceof FrameLayout) {
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) bottomMapControls.getLayoutParams();
params.setMargins(leftMargin, 0, 0, 0);
}
private void shiftMapControls(boolean toInitialPosition) {
boolean isLayoutRtl = AndroidUtils.isLayoutRtl(getContext());
int shiftPosition = toInitialPosition ? 0 : cardsContainer.getWidth();
int start = isLayoutRtl ? 0 : shiftPosition;
int end = isLayoutRtl ? shiftPosition : 0;
AndroidUtils.setMargins((MarginLayoutParams) bottomMapControls.getLayoutParams(), start, 0, end, 0);
AndroidUtils.setMargins((MarginLayoutParams) topMapControls.getLayoutParams(), start, 0, end, 0);
}
public boolean isInEditMode() {
@ -772,7 +784,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
mapActivity.getMapLayers().getMapControlsLayer().addThemeInfoProviderTag(TAG);
mapActivity.getMapLayers().getMapControlsLayer().showMapControlsIfHidden();
cachedMapPosition = mapActivity.getMapView().getMapPosition();
setDefaultMapPosition();
moveMapToDefaultPosition();
addInitialPoint();
}
}
@ -1196,7 +1208,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
@Override
public void onCloseMenu() {
setDefaultMapPosition();
moveMapToDefaultPosition();
}
@Override
@ -1641,7 +1653,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
updateInfoView();
}
private void setDefaultMapPosition() {
private void moveMapToDefaultPosition() {
setMapPosition(OsmandSettings.CENTER_CONSTANT);
}

View file

@ -32,9 +32,10 @@ import net.osmand.plus.settings.fragments.HeaderUiAdapter;
import net.osmand.plus.track.AppearanceViewHolder;
import net.osmand.plus.track.ColorsCard;
import net.osmand.plus.track.CustomColorBottomSheet.ColorPickerListener;
import net.osmand.plus.widgets.MultiStateToggleButton;
import net.osmand.plus.widgets.MultiStateToggleButton.OnRadioItemClickListener;
import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem;
import net.osmand.plus.widgets.multistatetoggle.RadioItem;
import net.osmand.plus.widgets.multistatetoggle.RadioItem.OnRadioItemClickListener;
import net.osmand.plus.widgets.multistatetoggle.TextToggleButton;
import net.osmand.plus.widgets.multistatetoggle.TextToggleButton.TextRadioItem;
import java.util.ArrayList;
import java.util.Arrays;
@ -134,17 +135,17 @@ public class RouteLineColorCard extends BaseCard implements CardListener, ColorP
}
private void setupRadioGroup(LinearLayout buttonsContainer) {
RadioItem day = createMapThemeButton(false);
RadioItem night = createMapThemeButton(true);
TextRadioItem day = createMapThemeButton(false);
TextRadioItem night = createMapThemeButton(true);
MultiStateToggleButton radioGroup = new MultiStateToggleButton(app, buttonsContainer, nightMode);
TextToggleButton radioGroup = new TextToggleButton(app, buttonsContainer, nightMode);
radioGroup.setItems(day, night);
radioGroup.setSelectedItem(!isNightMap() ? day : night);
}
private RadioItem createMapThemeButton(final boolean isNight) {
RadioItem item = new RadioItem(app.getString(!isNight ? DAY_TITLE_ID : NIGHT_TITLE_ID));
private TextRadioItem createMapThemeButton(final boolean isNight) {
TextRadioItem item = new TextRadioItem(app.getString(!isNight ? DAY_TITLE_ID : NIGHT_TITLE_ID));
item.setOnClickListener(new OnRadioItemClickListener() {
@Override
public boolean onRadioItemClick(RadioItem radioItem, View view) {

View file

@ -22,12 +22,12 @@ import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.LongDescriptionItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.widgets.MultiStateToggleButton;
import net.osmand.plus.widgets.MultiStateToggleButton.OnRadioItemClickListener;
import net.osmand.plus.widgets.MultiStateToggleButton.RadioItem;
import net.osmand.plus.widgets.multistatetoggle.RadioItem;
import net.osmand.plus.widgets.multistatetoggle.RadioItem.OnRadioItemClickListener;
import net.osmand.plus.widgets.multistatetoggle.TextToggleButton;
import net.osmand.plus.widgets.multistatetoggle.TextToggleButton.TextRadioItem;
import org.apache.commons.logging.Log;
@ -120,11 +120,11 @@ public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment {
}
private void setupTypeRadioGroup(LinearLayout buttonsContainer) {
RadioItem none = createRadioButton(GpxSplitType.NO_SPLIT, R.string.shared_string_none);
RadioItem time = createRadioButton(GpxSplitType.TIME, R.string.shared_string_time);
RadioItem distance = createRadioButton(GpxSplitType.DISTANCE, R.string.distance);
TextRadioItem none = createRadioButton(GpxSplitType.NO_SPLIT, R.string.shared_string_none);
TextRadioItem time = createRadioButton(GpxSplitType.TIME, R.string.shared_string_time);
TextRadioItem distance = createRadioButton(GpxSplitType.DISTANCE, R.string.distance);
MultiStateToggleButton radioGroup = new MultiStateToggleButton(app, buttonsContainer, nightMode);
TextToggleButton radioGroup = new TextToggleButton(app, buttonsContainer, nightMode);
radioGroup.setItems(none, time, distance);
if (selectedSplitType == GpxSplitType.NO_SPLIT) {
@ -134,9 +134,9 @@ public class SplitIntervalBottomSheet extends MenuBottomSheetDialogFragment {
}
}
private RadioItem createRadioButton(final GpxSplitType splitType, int titleId) {
private TextRadioItem createRadioButton(final GpxSplitType splitType, int titleId) {
String title = app.getString(titleId);
RadioItem item = new RadioItem(title);
TextRadioItem item = new TextRadioItem(title);
item.setOnClickListener(new OnRadioItemClickListener() {
@Override
public boolean onRadioItemClick(RadioItem radioItem, View view) {

View file

@ -0,0 +1,70 @@
package net.osmand.plus.widgets.multistatetoggle;
import android.graphics.drawable.Drawable;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.widgets.multistatetoggle.IconToggleButton.IconRadioItem;
public class IconToggleButton extends MultiStateToggleButton<IconRadioItem> {
public IconToggleButton(@NonNull OsmandApplication app,
@NonNull LinearLayout container,
boolean nightMode) {
super(app, container, nightMode);
}
@Override
protected int getRadioItemLayoutId() {
return R.layout.custom_radio_btn_icon_item;
}
@Override
protected void initItemView(@NonNull ViewGroup view,
@NonNull IconRadioItem item) {
if (item.isUseDefaultColor()) {
ImageView ivIcon = view.findViewById(R.id.icon);
ivIcon.setImageDrawable(uiUtilities.getIcon(item.getIconId()));
}
}
@Override
protected void updateItemView(@NonNull ViewGroup view,
@NonNull IconRadioItem item,
@ColorInt int color) {
if (!item.isUseDefaultColor()) {
ImageView ivIcon = view.findViewById(R.id.icon);
Drawable icon = uiUtilities.getPaintedIcon(item.getIconId(), color);
ivIcon.setImageDrawable(icon);
}
}
public static class IconRadioItem extends RadioItem {
private final int iconId;
private final boolean useDefaultColor;
public IconRadioItem(int iconId) {
this(iconId, false);
}
public IconRadioItem(int iconId, boolean useDefaultColor) {
this.iconId = iconId;
this.useDefaultColor = useDefaultColor;
}
public int getIconId() {
return iconId;
}
public boolean isUseDefaultColor() {
return useDefaultColor;
}
}
}

View file

@ -1,4 +1,4 @@
package net.osmand.plus.widgets;
package net.osmand.plus.widgets.multistatetoggle;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
@ -6,38 +6,49 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import net.osmand.AndroidUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.widgets.multistatetoggle.RadioItem.OnRadioItemClickListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MultiStateToggleButton {
public abstract class MultiStateToggleButton<_Radio extends RadioItem> {
private List<RadioItem> items = new ArrayList<>();
private OsmandApplication app;
private List<ViewGroup> buttons = new ArrayList<>();
private List<View> dividers = new ArrayList<>();
private RadioItem selectedItem;
protected final OsmandApplication app;
protected final UiUtilities uiUtilities;
private LinearLayout container;
private boolean nightMode;
private final LinearLayout container;
private final List<ViewGroup> buttons = new ArrayList<>();
private final List<View> dividers = new ArrayList<>();
public MultiStateToggleButton(OsmandApplication app, LinearLayout container, boolean nightMode) {
protected final List<_Radio> items = new ArrayList<>();
protected final boolean nightMode;
protected boolean isEnabled;
protected RadioItem selectedItem;
public MultiStateToggleButton(@NonNull OsmandApplication app,
@NonNull LinearLayout container,
boolean nightMode) {
this.app = app;
this.uiUtilities = app.getUIUtilities();
this.container = container;
this.nightMode = nightMode;
}
public void setItems(RadioItem firstBtn, RadioItem secondBtn, RadioItem... other) {
@SafeVarargs
public final void setItems(@NonNull _Radio firstBtn,
@NonNull _Radio secondBtn,
@Nullable _Radio... other) {
items.clear();
items.add(firstBtn);
items.add(secondBtn);
@ -47,6 +58,11 @@ public class MultiStateToggleButton {
initView();
}
public final void setSelectedItem(@Nullable RadioItem selectedItem) {
this.selectedItem = selectedItem;
updateView();
}
private void initView() {
buttons.clear();
dividers.clear();
@ -60,16 +76,10 @@ public class MultiStateToggleButton {
updateView();
}
private boolean isLastItem(int index) {
return index == items.size() - 1;
}
private void createBtn(@NonNull final RadioItem item) {
private void createBtn(@NonNull final _Radio item) {
LayoutInflater inflater = UiUtilities.getInflater(app, nightMode);
ViewGroup button = (ViewGroup) inflater.inflate(
R.layout.custom_radio_btn_text_item, container, false);
TextView title = button.findViewById(R.id.title);
title.setText(item.getTitle());
getRadioItemLayoutId(), container, false);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -79,6 +89,7 @@ public class MultiStateToggleButton {
}
}
});
initItemView(button, item);
buttons.add(button);
container.addView(button);
}
@ -95,11 +106,6 @@ public class MultiStateToggleButton {
container.addView(divider);
}
public void setSelectedItem(RadioItem selectedItem) {
this.selectedItem = selectedItem;
updateView();
}
private void updateView() {
updateView(true);
}
@ -123,15 +129,14 @@ public class MultiStateToggleButton {
showAllDividers();
for (int i = 0; i < items.size(); i++) {
RadioItem item = items.get(i);
_Radio item = items.get(i);
ViewGroup container = buttons.get(i);
container.setEnabled(isEnabled);
TextView tvTitle = (TextView) container.findViewById(R.id.title);
if (selectedItem == item) {
if (i == 0) {
background.setCornerRadii(isLayoutRtl ? rightBtnRadii : leftBtnRadii);
hideDividers(0);
} else if (i == items.size() - 1) {
} else if (isLastItem(i)) {
background.setCornerRadii(isLayoutRtl ? leftBtnRadii : rightBtnRadii);
hideDividers(dividers.size() - 1);
} else {
@ -139,14 +144,21 @@ public class MultiStateToggleButton {
hideDividers(i - 1, i);
}
container.setBackgroundDrawable(background);
tvTitle.setTextColor(textColor);
updateItemView(container, item, textColor);
} else {
container.setBackgroundColor(Color.TRANSPARENT);
tvTitle.setTextColor(activeColor);
updateItemView(container, item, activeColor);
}
}
}
protected abstract int getRadioItemLayoutId();
protected abstract void initItemView(@NonNull ViewGroup view, @NonNull _Radio item);
protected abstract void updateItemView(@NonNull ViewGroup view, @NonNull _Radio item,
@ColorInt int color);
private void showAllDividers() {
for (View divider : dividers) {
divider.setVisibility(View.VISIBLE);
@ -161,28 +173,7 @@ public class MultiStateToggleButton {
}
}
public static class RadioItem {
private String title;
private OnRadioItemClickListener listener;
public RadioItem(String title) {
this.title = title;
}
public void setOnClickListener(OnRadioItemClickListener listener) {
this.listener = listener;
}
public String getTitle() {
return title;
}
public OnRadioItemClickListener getListener() {
return listener;
}
}
public interface OnRadioItemClickListener {
boolean onRadioItemClick(RadioItem radioItem, View view);
private boolean isLastItem(int index) {
return index == items.size() - 1;
}
}

View file

@ -0,0 +1,20 @@
package net.osmand.plus.widgets.multistatetoggle;
import android.view.View;
public class RadioItem {
private OnRadioItemClickListener listener;
public void setOnClickListener(OnRadioItemClickListener listener) {
this.listener = listener;
}
public OnRadioItemClickListener getListener() {
return listener;
}
public interface OnRadioItemClickListener {
boolean onRadioItemClick(RadioItem radioItem, View view);
}
}

View file

@ -0,0 +1,54 @@
package net.osmand.plus.widgets.multistatetoggle;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.widgets.multistatetoggle.TextToggleButton.TextRadioItem;
public class TextToggleButton extends MultiStateToggleButton<TextRadioItem> {
public TextToggleButton(@NonNull OsmandApplication app,
@NonNull LinearLayout container,
boolean nightMode) {
super(app, container, nightMode);
}
@Override
protected int getRadioItemLayoutId() {
return R.layout.custom_radio_btn_text_item;
}
@Override
protected void initItemView(@NonNull ViewGroup view, @NonNull TextRadioItem item) {
TextView title = view.findViewById(R.id.title);
title.setText(item.getTitle());
}
@Override
protected void updateItemView(@NonNull ViewGroup view,
@NonNull TextRadioItem item,
@ColorInt int color) {
TextView tvTitle = (TextView) view.findViewById(R.id.title);
tvTitle.setTextColor(color);
}
public static class TextRadioItem extends RadioItem {
private final String title;
public TextRadioItem(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
}
}