From b03899c4ff10aac4d72fdecd7582df4a95b03ce3 Mon Sep 17 00:00:00 2001 From: nazar-kutz Date: Fri, 27 Nov 2020 19:12:46 +0200 Subject: [PATCH] Fix Plan Route Ui bugs, add HorizontalRadioGroup --- .../res/layout/custom_radio_btn_text_item.xml | 20 ++ .../res/layout/fragment_measurement_tool.xml | 35 +- .../fragment_plan_route_half_screen.xml | 2 +- ...ph.xml => measurement_tool_graph_card.xml} | 12 +- ...t.xml => measurement_tool_points_card.xml} | 2 +- OsmAnd/res/values-large/sizes.xml | 2 +- OsmAnd/res/values/sizes.xml | 2 +- .../other/HorizontalSelectionAdapter.java | 2 + .../other/TrackDetailsMenu.java | 8 +- .../plus/measurementtool/GraphsCard.java | 8 +- .../MeasurementToolFragment.java | 315 +++++++++--------- .../plus/measurementtool/PointsCard.java | 8 +- .../plus/widgets/HorizontalRadioGroup.java | 206 ++++++++++++ 13 files changed, 424 insertions(+), 198 deletions(-) create mode 100644 OsmAnd/res/layout/custom_radio_btn_text_item.xml rename OsmAnd/res/layout/{fragment_measurement_tool_graph.xml => measurement_tool_graph_card.xml} (95%) rename OsmAnd/res/layout/{fragment_measurement_tool_points_list.xml => measurement_tool_points_card.xml} (91%) create mode 100644 OsmAnd/src/net/osmand/plus/widgets/HorizontalRadioGroup.java diff --git a/OsmAnd/res/layout/custom_radio_btn_text_item.xml b/OsmAnd/res/layout/custom_radio_btn_text_item.xml new file mode 100644 index 0000000000..3bd1efbfc1 --- /dev/null +++ b/OsmAnd/res/layout/custom_radio_btn_text_item.xml @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/fragment_measurement_tool.xml b/OsmAnd/res/layout/fragment_measurement_tool.xml index 2fe4dc1416..982f0840b3 100644 --- a/OsmAnd/res/layout/fragment_measurement_tool.xml +++ b/OsmAnd/res/layout/fragment_measurement_tool.xml @@ -130,25 +130,32 @@ tools:text="@string/add_point_after"/> - + android:layout_height="wrap_content"> - - - + android:layout_height="@dimen/measurement_tool_button_height" + android:layout_marginStart="@dimen/content_padding" + android:layout_marginEnd="@dimen/content_padding" + android:layout_marginBottom="@dimen/measurement_tool_content_padding_medium" /> - + - + + + + android:visibility="invisible" /> - - \ No newline at end of file diff --git a/OsmAnd/res/layout/fragment_measurement_tool_points_list.xml b/OsmAnd/res/layout/measurement_tool_points_card.xml similarity index 91% rename from OsmAnd/res/layout/fragment_measurement_tool_points_list.xml rename to OsmAnd/res/layout/measurement_tool_points_card.xml index a0684707ea..47e8bd9d4b 100644 --- a/OsmAnd/res/layout/fragment_measurement_tool_points_list.xml +++ b/OsmAnd/res/layout/measurement_tool_points_card.xml @@ -3,7 +3,7 @@ xmlns:osmand="http://schemas.android.com/apk/res-auto" android:id="@+id/points_list_container" android:layout_width="match_parent" - android:layout_height="@dimen/measurement_tool_points_list_container_height" + android:layout_height="wrap_content" android:background="?attr/activity_background_color"> 12dp 18dp 12dp - 330dp + 330dp 48dp 18dp 24dp diff --git a/OsmAnd/res/values/sizes.xml b/OsmAnd/res/values/sizes.xml index f91581adf6..a086849297 100644 --- a/OsmAnd/res/values/sizes.xml +++ b/OsmAnd/res/values/sizes.xml @@ -257,7 +257,7 @@ 12dp 4dp 8dp - 220dp + 220dp 60dp 52dp 8dp diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/HorizontalSelectionAdapter.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/HorizontalSelectionAdapter.java index 06783d6f50..23d7886d55 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/HorizontalSelectionAdapter.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/HorizontalSelectionAdapter.java @@ -63,6 +63,8 @@ public class HorizontalSelectionAdapter extends RecyclerView.Adapter 0 && editingCtx.getSelectedPointPosition() == -1) { - expandAdditionalInfoView(); - } else { - collapseAdditionalInfoView(); + public void onClick(View v) { + if (isPortrait) { + if (infoExpanded) { + collapseInfoView(); + } else if (setInfoType(InfoType.POINTS)) { + infoTypeBtn.setSelectedItem(pointsBtn); + } } } }); View applyMovePointButton = mainView.findViewById(R.id.apply_move_point_button); - UiUtilities.setupDialogButton(nightMode, applyMovePointButton, UiUtilities.DialogButtonType.PRIMARY, - R.string.shared_string_apply); + UiUtilities.setupDialogButton(nightMode, applyMovePointButton, + UiUtilities.DialogButtonType.PRIMARY, R.string.shared_string_apply); + applyMovePointButton.setMinimumWidth(btnWidth); applyMovePointButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { @@ -349,8 +342,9 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route View applyPointBeforeAfterButton = mainView.findViewById(R.id.apply_point_before_after_point_button); - UiUtilities.setupDialogButton(nightMode, applyPointBeforeAfterButton, UiUtilities.DialogButtonType.PRIMARY, - R.string.shared_string_apply); + UiUtilities.setupDialogButton(nightMode, applyPointBeforeAfterButton, + UiUtilities.DialogButtonType.PRIMARY, R.string.shared_string_apply); + applyPointBeforeAfterButton.setMinimumWidth(btnWidth); applyPointBeforeAfterButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { @@ -359,8 +353,9 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route }); View addPointBeforeAfterButton = mainView.findViewById(R.id.add_point_before_after_button); - UiUtilities.setupDialogButton(nightMode, addPointBeforeAfterButton, UiUtilities.DialogButtonType.PRIMARY, - R.string.shared_string_add); + UiUtilities.setupDialogButton(nightMode, addPointBeforeAfterButton, + UiUtilities.DialogButtonType.PRIMARY, R.string.shared_string_add); + addPointBeforeAfterButton.setMinimumWidth(btnWidth); addPointBeforeAfterButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { @@ -408,8 +403,9 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route }); View addPointButton = mainView.findViewById(R.id.add_point_button); - UiUtilities.setupDialogButton(nightMode, addPointButton, UiUtilities.DialogButtonType.PRIMARY, - R.string.shared_string_add); + UiUtilities.setupDialogButton(nightMode, addPointButton, + UiUtilities.DialogButtonType.PRIMARY, R.string.shared_string_add); + addPointButton.setMinimumWidth(btnWidth); addPointButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { @@ -425,9 +421,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route @Override public void onSelectPoint(int selectedPointPos) { - if (additionalInfoExpanded) { - collapseAdditionalInfoView(); - } if (selectedPointPos != -1) { openSelectedPointMenu(mapActivity); } @@ -449,9 +442,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route measurementLayer.setOnEnterMovePointModeListener(new MeasurementToolLayer.OnEnterMovePointModeListener() { @Override public void onEnterMovePointMode() { - if (additionalInfoExpanded) { - collapseAdditionalInfoView(); - } + collapseInfoViewIfExpanded(); switchMovePointMode(true); } }); @@ -529,37 +520,90 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route return view; } - private void changeAdditionalInfoType(@NonNull AdditionalInfoType type) { - if (!additionalInfoExpanded || !isCurrentAdditionalInfoType(type)) { - MapActivity ma = getMapActivity(); - if (ma == null) return; - - OsmandApplication app = ma.getMyApplication(); - if (AdditionalInfoType.POINTS == type) { - visibleCard = pointsCard; - UiUtilities.updateCustomRadioButtons(app, customRadioButton, nightMode, START); - } else if (AdditionalInfoType.GRAPH == type) { - visibleCard = graphsCard; - UiUtilities.updateCustomRadioButtons(app, customRadioButton, nightMode, END); + private OnRadioItemClickListener getInfoTypeBtnListener(@NonNull final InfoType type) { + return new OnRadioItemClickListener() { + @Override + public boolean onRadioItemClick(RadioItem radioItem, View view) { + if (isCurrentInfoType(type)) { + collapseInfoView(); + return false; + } + return setInfoType(type); } - cardsContainer.removeAllViews(); - View cardView = visibleCard.getView() != null ? visibleCard.getView() : visibleCard.build(ma); - cardsContainer.addView(cardView); + }; + } - currentAdditionalInfoType = type; - additionalInfoExpanded = true; + private boolean setInfoType(@NonNull InfoType type) { + OsmandApplication app = getMyApplication(); + if ((!infoExpanded || !isCurrentInfoType(type)) && app != null) { + if (editingCtx.getPointsCount() > 0 && editingCtx.getSelectedPointPosition() == -1) { + expandInfoView(); + currentInfoType = type; + if (InfoType.POINTS == type) { + visibleCard = pointsCard; + } else if (InfoType.GRAPH == type) { + visibleCard = graphsCard; + } + cardsContainer.removeAllViews(); + View cardView = visibleCard.getView() != null ? visibleCard.getView() : visibleCard.build(app); + cardsContainer.addView(cardView); + return true; + } else { + collapseInfoView(); + } + } + return false; + } + + private void expandInfoView() { + if (isPortrait) { + infoExpanded = true; + cardsContainer.setVisibility(View.VISIBLE); + setMapPosition(isPortrait + ? OsmandSettings.MIDDLE_TOP_CONSTANT + : OsmandSettings.LANDSCAPE_MIDDLE_RIGHT_CONSTANT); updateUpDownBtn(); } } - private void updateAdditionalInfoView() { - updateAdditionalInfoView(pointsCard); - updateAdditionalInfoView(graphsCard); + private void collapseInfoViewIfExpanded() { + if (infoExpanded) { + collapseInfoView(); + } } - private void updateAdditionalInfoView(OnUpdateAdditionalInfoListener listener) { + private void collapseInfoView() { + if (isPortrait) { + infoExpanded = false; + currentInfoType = null; + infoTypeBtn.setSelectedItem(null); + cardsContainer.setVisibility(View.GONE); + setDefaultMapPosition(); + updateUpDownBtn(); + } + } + + private void collapseInfoIfNotEnoughPoints() { + MeasurementToolLayer measurementLayer = getMeasurementLayer(); + if (measurementLayer != null) { + int pointsCount = editingCtx.getPointsCount(); + if (isCurrentInfoType(InfoType.GRAPH) && pointsCount < 2) { + collapseInfoView(); + } else if (pointsCount < 1) { + disable(upDownBtn); + collapseInfoViewIfExpanded(); + } + } + } + + private void updateInfoView() { + updateInfoView(pointsCard); + updateInfoView(graphsCard); + } + + private void updateInfoView(OnUpdateInfoListener listener) { if (listener != null) { - listener.onUpdateAdditionalInfo(); + listener.onUpdateInfo(); } } @@ -576,11 +620,11 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } private void updateUndoRedoCommonStuff() { - collapseAdditionalInfoIfNoPointsEnough(); + collapseInfoIfNotEnoughPoints(); if (editingCtx.getPointsCount() > 0) { enable(upDownBtn); } - updateAdditionalInfoView(); + updateInfoView(); updateDistancePointsText(); updateSnapToRoadControls(); } @@ -638,9 +682,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route super.onDestroyView(); cancelModes(); exitMeasurementMode(); - if (additionalInfoExpanded) { - collapseAdditionalInfoView(); - } + collapseInfoViewIfExpanded(); MeasurementToolLayer layer = getMeasurementLayer(); if (layer != null) { layer.setOnSingleTapListener(null); @@ -891,9 +933,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route MeasurementToolLayer measurementLayer = getMeasurementLayer(); editingCtx.getCommandManager().execute(new ClearPointsCommand(measurementLayer, ALL)); editingCtx.cancelSnapToRoad(); - if (additionalInfoExpanded) { - collapseAdditionalInfoView(); - } + collapseInfoViewIfExpanded(); updateUndoRedoButton(false, redoBtn); disable(upDownBtn); updateDistancePointsText(); @@ -907,9 +947,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route if (points.size() > 1) { MeasurementToolLayer measurementLayer = getMeasurementLayer(); editingCtx.getCommandManager().execute(new ReversePointsCommand(measurementLayer)); - if (additionalInfoExpanded) { - collapseAdditionalInfoView(); - } + collapseInfoViewIfExpanded(); updateUndoRedoButton(false, redoBtn); updateUndoRedoButton(true, undoBtn); updateDistancePointsText(); @@ -976,9 +1014,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route private void trimRoute(ClearCommandMode before) { MeasurementToolLayer measurementLayer = getMeasurementLayer(); editingCtx.getCommandManager().execute(new ClearPointsCommand(measurementLayer, before)); - if (additionalInfoExpanded) { - collapseAdditionalInfoView(); - } + collapseInfoViewIfExpanded(); editingCtx.setSelectedPointPosition(-1); editingCtx.splitSegments(editingCtx.getBeforePoints().size() + editingCtx.getAfterPoints().size()); updateUndoRedoButton(false, redoBtn); @@ -1130,11 +1166,11 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route private void removePoint(MeasurementToolLayer measurementLayer, int position) { if (measurementLayer != null) { editingCtx.getCommandManager().execute(new RemovePointCommand(measurementLayer, position)); - updateAdditionalInfoView(); + updateInfoView(); updateUndoRedoButton(true, undoBtn); updateUndoRedoButton(false, redoBtn); updateDistancePointsText(); - collapseAdditionalInfoIfNoPointsEnough(); + collapseInfoIfNotEnoughPoints(); } } @@ -1159,10 +1195,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route @Override public void onItemClick(int position) { if (mapActivity != null && measurementLayer != null) { - if (additionalInfoExpanded) { - collapseAdditionalInfoView(); - } - if (portrait) { + collapseInfoViewIfExpanded(); + if (isPortrait) { setMapPosition(OsmandSettings.MIDDLE_TOP_CONSTANT); } measurementLayer.moveMapToPoint(position); @@ -1182,7 +1216,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route toPosition = holder.getAdapterPosition(); if (toPosition >= 0 && fromPosition >= 0 && toPosition != fromPosition) { editingCtx.getCommandManager().execute(new ReorderPointCommand(measurementLayer, fromPosition, toPosition)); - updateAdditionalInfoView(); + updateInfoView(); updateUndoRedoButton(false, redoBtn); updateDistancePointsText(); mapActivity.refreshMap(); @@ -1248,7 +1282,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route if (!isUndoMode()) { editingCtx.addPoints(); } - updateAdditionalInfoView(); + updateInfoView(); updateDistancePointsText(); } } @@ -1406,7 +1440,9 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route R.id.measurement_points_text_view, R.id.distance_to_center_text_view, R.id.up_down_button, - R.id.measure_mode_controls); + R.id.measure_mode_controls, + R.id.info_type_buttons_container, + R.id.bottom_panel_divider); } } @@ -1444,46 +1480,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route updateUndoRedoButton(true, undoBtn); updateUndoRedoButton(false, redoBtn); updateDistancePointsText(); - updateAdditionalInfoView(); - } - - private void expandAdditionalInfoView() { - if (portrait) { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - additionalInfoContainer.setVisibility(View.VISIBLE); - AdditionalInfoType typeToShow = currentAdditionalInfoType == null - ? AdditionalInfoType.POINTS : currentAdditionalInfoType; - changeAdditionalInfoType(typeToShow); - setMapPosition(portrait - ? OsmandSettings.MIDDLE_TOP_CONSTANT - : OsmandSettings.LANDSCAPE_MIDDLE_RIGHT_CONSTANT); - } - } - } - - private void collapseAdditionalInfoView() { - if (portrait) { - additionalInfoExpanded = false; - updateUpDownBtn(); - additionalInfoContainer.setVisibility(View.GONE); - setDefaultMapPosition(); - } - } - - private void collapseAdditionalInfoIfNoPointsEnough() { - MeasurementToolLayer measurementLayer = getMeasurementLayer(); - if (measurementLayer != null) { - int pointsCount = editingCtx.getPointsCount(); - if (isCurrentAdditionalInfoType(AdditionalInfoType.GRAPH) && pointsCount < 2) { - collapseAdditionalInfoView(); - } else if (pointsCount < 1) { - disable(upDownBtn); - if (additionalInfoExpanded) { - collapseAdditionalInfoView(); - } - } - } + updateInfoView(); } private void setDefaultMapPosition() { @@ -1510,13 +1507,13 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } private void updateUpDownBtn() { - Drawable icon = getContentIcon(additionalInfoExpanded + Drawable icon = getContentIcon(infoExpanded ? R.drawable.ic_action_arrow_down : R.drawable.ic_action_arrow_up); upDownBtn.setImageDrawable(icon); } - private boolean isCurrentAdditionalInfoType(@NonNull AdditionalInfoType type) { - return type.equals(currentAdditionalInfoType); + private boolean isCurrentInfoType(@NonNull InfoType type) { + return Algorithms.objectEquals(currentInfoType, type); } public boolean hasVisibleGraph() { @@ -1600,7 +1597,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route switch (finalSaveAction) { case SHOW_SNACK_BAR_AND_CLOSE: final WeakReference mapActivityRef = new WeakReference<>(mapActivity); - snackbar = Snackbar.make(mapActivity.getLayout(), + Snackbar snackbar = Snackbar.make(mapActivity.getLayout(), MessageFormat.format(getString(R.string.gpx_saved_sucessfully), outFile.getName()), Snackbar.LENGTH_LONG) .setAction(R.string.shared_string_undo, new OnClickListener() { @@ -1693,7 +1690,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route if (measurementLayer != null) { String distanceStr = OsmAndFormatter.getFormattedDistance((float) editingCtx.getRouteDistance(), requireMyApplication()); distanceTv.setText(distanceStr + ","); - pointsTv.setText((portrait ? pointsSt + ": " : "") + editingCtx.getPointsCount()); + pointsTv.setText((isPortrait ? pointsSt + ": " : "") + editingCtx.getPointsCount()); } updateToolbar(); } @@ -1724,7 +1721,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route mapActivity.refreshMap(); mapActivity.disableDrawer(); - AndroidUiHelper.setVisibility(mapActivity, portrait ? View.INVISIBLE : View.GONE, + AndroidUiHelper.setVisibility(mapActivity, isPortrait ? View.INVISIBLE : View.GONE, R.id.map_left_widgets_panel, R.id.map_right_widgets_panel, R.id.map_center_info); @@ -1778,7 +1775,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } } - public void quit(boolean hidePointsListFirst) { + public void quit(boolean hideInfoViewFirst) { if (editingCtx.getOriginalPointToMove() != null) { cancelMovePointMode(); return; @@ -1793,16 +1790,16 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route dismiss(mapActivity); } } else { - showQuitDialog(hidePointsListFirst); + showQuitDialog(hideInfoViewFirst); } } - private void showQuitDialog(boolean hidePointsListFirst) { + private void showQuitDialog(boolean hideInfoViewFirst) { final MapActivity mapActivity = getMapActivity(); MeasurementToolLayer measurementLayer = getMeasurementLayer(); if (mapActivity != null && measurementLayer != null) { - if (additionalInfoExpanded && hidePointsListFirst) { - collapseAdditionalInfoView(); + if (infoExpanded && hideInfoViewFirst) { + collapseInfoView(); return; } if (!editingCtx.hasChanges()) { @@ -1822,9 +1819,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route if (clearContext) { editingCtx.clearSegments(); } - if (additionalInfoExpanded) { - collapseAdditionalInfoView(); - } + collapseInfoViewIfExpanded(); resetAppMode(); hideSnapToRoadIcon(); if (isInEditMode()) { @@ -1961,9 +1956,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route if (!approximationMode || !editingCtx.getCommandManager().update(command)) { editingCtx.getCommandManager().execute(command); } - if (additionalInfoExpanded) { - collapseAdditionalInfoView(); - } + collapseInfoViewIfExpanded(); updateSnapToRoadControls(); } } @@ -2036,7 +2029,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route return nightMode; } - public interface OnUpdateAdditionalInfoListener { - void onUpdateAdditionalInfo(); + public interface OnUpdateInfoListener { + void onUpdateInfo(); } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/PointsCard.java b/OsmAnd/src/net/osmand/plus/measurementtool/PointsCard.java index f3b55473bc..4507fe5270 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/PointsCard.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/PointsCard.java @@ -7,12 +7,12 @@ import androidx.recyclerview.widget.RecyclerView; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.measurementtool.MeasurementToolFragment.OnUpdateAdditionalInfoListener; +import net.osmand.plus.measurementtool.MeasurementToolFragment.OnUpdateInfoListener; import net.osmand.plus.measurementtool.adapter.MeasurementToolAdapter; import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.views.controls.ReorderItemTouchHelperCallback; -public class PointsCard extends BaseCard implements OnUpdateAdditionalInfoListener { +public class PointsCard extends BaseCard implements OnUpdateInfoListener { private MeasurementToolAdapter adapter; private MeasurementToolFragment fragment; @@ -23,7 +23,7 @@ public class PointsCard extends BaseCard implements OnUpdateAdditionalInfoListen } @Override - public void onUpdateAdditionalInfo() { + public void onUpdateInfo() { if (adapter != null) { adapter.notifyDataSetChanged(); } @@ -31,7 +31,7 @@ public class PointsCard extends BaseCard implements OnUpdateAdditionalInfoListen @Override public int getCardLayoutId() { - return R.layout.fragment_measurement_tool_points_list; + return R.layout.measurement_tool_points_card; } @Override diff --git a/OsmAnd/src/net/osmand/plus/widgets/HorizontalRadioGroup.java b/OsmAnd/src/net/osmand/plus/widgets/HorizontalRadioGroup.java new file mode 100644 index 0000000000..edd54c9d16 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/widgets/HorizontalRadioGroup.java @@ -0,0 +1,206 @@ +package net.osmand.plus.widgets; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.GradientDrawable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +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 java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class HorizontalRadioGroup { + + private List items = new ArrayList<>(); + private List buttons = new ArrayList<>(); + private List dividers = new ArrayList<>(); + private RadioItem selectedItem; + + private LinearLayout container; + private boolean nightMode; + + public HorizontalRadioGroup(LinearLayout container, boolean nightMode) { + this.container = container; + this.nightMode = nightMode; + } + + public void setItems(RadioItem firstBtn, RadioItem secondBtn, RadioItem ... other) { + items.clear(); + items.add(firstBtn); + items.add(secondBtn); + if (other != null && other.length > 0) { + items.addAll(Arrays.asList(other)); + } + initView(); + } + + private void initView() { + buttons.clear(); + dividers.clear(); + container.removeAllViews(); + for (int i = 0; i < items.size(); i++) { + RadioItem item = items.get(i); + + ViewGroup button = createBtn(); + TextView title = button.findViewById(R.id.title); + title.setText(item.getTitle()); + button.setOnClickListener(getSelectClickListener(item)); + buttons.add(button); + container.addView(button); + + boolean lastItem = i == items.size() - 1; + if (!lastItem) { + View divider = createDivider(); + dividers.add(divider); + container.addView(divider); + } + } + updateView(); + } + + private View.OnClickListener getSelectClickListener(final RadioItem item) { + return new View.OnClickListener() { + @Override + public void onClick(View v) { + OnRadioItemClickListener l = item.getListener(); + if (l != null && l.onRadioItemClick(item, container)) { + setSelectedItem(item); + } + } + }; + } + + @NonNull + private ViewGroup createBtn() { + Context ctx = getThemedCtx(); + LayoutInflater inflater = LayoutInflater.from(ctx); + return (ViewGroup) inflater.inflate(R.layout.custom_radio_btn_text_item, container, false); + } + + @NonNull + private View createDivider() { + Context ctx = getThemedCtx(); + int dividerColor = nightMode ? + R.color.stroked_buttons_and_links_outline_dark : + R.color.stroked_buttons_and_links_outline_light; + int width = AndroidUtils.dpToPx(ctx, 1.0f); + View divider = new View(ctx); + divider.setLayoutParams(new ViewGroup.LayoutParams(width, ViewGroup.LayoutParams.MATCH_PARENT)); + divider.setBackgroundColor(ContextCompat.getColor(ctx, dividerColor)); + return divider; + } + + public void setSelectedItem(RadioItem selectedItem) { + this.selectedItem = selectedItem; + updateView(); + } + + private void updateView() { + OsmandApplication app = getMyApplication(); + if (app == null) { + return; + } + int activeColor = ContextCompat.getColor(app, nightMode + ? R.color.active_color_primary_dark + : R.color.active_color_primary_light); + int textColor = ContextCompat.getColor(app, nightMode + ? R.color.text_color_primary_dark + : R.color.text_color_primary_light); + int radius = AndroidUtils.dpToPx(app, 4); + float[] leftBtnRadii = new float[]{radius, radius, 0, 0, 0, 0, radius, radius}; + float[] rightBtnRadii = new float[]{0, 0, radius, radius, radius, radius, 0, 0}; + float[] centerBtnRadii = new float[]{0, 0, 0, 0, 0, 0, 0, 0}; + boolean isLayoutRtl = AndroidUtils.isLayoutRtl(app); + + GradientDrawable background = new GradientDrawable(); + background.setColor(UiUtilities.getColorWithAlpha(activeColor, 0.1f)); + background.setStroke(AndroidUtils.dpToPx(app, 1), UiUtilities.getColorWithAlpha(activeColor, 0.5f)); + + showAllDividers(); + for (int i = 0; i < items.size(); i++) { + RadioItem item = items.get(i); + ViewGroup container = buttons.get(i); + 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) { + background.setCornerRadii(isLayoutRtl ? leftBtnRadii : rightBtnRadii); + hideDividers(dividers.size() - 1); + } else { + background.setCornerRadii(centerBtnRadii); + hideDividers(i - 1, i); + } + container.setBackgroundDrawable(background); + tvTitle.setTextColor(textColor); + } else { + container.setBackgroundColor(Color.TRANSPARENT); + tvTitle.setTextColor(activeColor); + } + } + } + + private void showAllDividers() { + for (View divider : dividers) { + divider.setVisibility(View.VISIBLE); + } + } + + private void hideDividers(int ... dividerIndexes) { + for (int dividerIndex : dividerIndexes) { + if (dividerIndex >= 0 && dividerIndex < dividers.size()) { + dividers.get(dividerIndex).setVisibility(View.GONE); + } + } + } + + private Context getThemedCtx() { + Context ctx = container.getContext(); + return UiUtilities.getThemedContext(ctx, nightMode); + } + + private OsmandApplication getMyApplication() { + if (container != null) { + return (OsmandApplication) container.getContext().getApplicationContext(); + } + return null; + } + + 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); + } +}