From 4a1934e09ccdfddd0b8bfd7617ce947bbfa4f002 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Fri, 27 Nov 2020 06:14:53 +0200 Subject: [PATCH] UI fixes second part --- .../res/animator/appbar_always_elevated.xml | 10 ++ ...heet_item_with_descr_and_checkbox_56dp.xml | 2 +- OsmAnd/res/layout/fragment_import.xml | 15 ++- .../fragments/BaseSettingsListFragment.java | 59 ++++----- .../fragments/ExportItemsBottomSheet.java | 118 +++++++++++++++--- .../fragments/ExportSettingsAdapter.java | 22 ++-- .../fragments/ExportSettingsFragment.java | 1 + .../fragments/ImportSettingsFragment.java | 1 + 8 files changed, 170 insertions(+), 58 deletions(-) create mode 100644 OsmAnd/res/animator/appbar_always_elevated.xml diff --git a/OsmAnd/res/animator/appbar_always_elevated.xml b/OsmAnd/res/animator/appbar_always_elevated.xml new file mode 100644 index 0000000000..c8378c1c29 --- /dev/null +++ b/OsmAnd/res/animator/appbar_always_elevated.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/bottom_sheet_item_with_descr_and_checkbox_56dp.xml b/OsmAnd/res/layout/bottom_sheet_item_with_descr_and_checkbox_56dp.xml index 34e329d8a3..65fc03610c 100644 --- a/OsmAnd/res/layout/bottom_sheet_item_with_descr_and_checkbox_56dp.xml +++ b/OsmAnd/res/layout/bottom_sheet_item_with_descr_and_checkbox_56dp.xml @@ -33,7 +33,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:ellipsize="end" - android:maxLines="1" + android:maxLines="2" android:textAppearance="@style/TextAppearance.ListItemTitle" tools:text="Some title"/> diff --git a/OsmAnd/res/layout/fragment_import.xml b/OsmAnd/res/layout/fragment_import.xml index 2088d2624a..eb2cbc7f79 100644 --- a/OsmAnd/res/layout/fragment_import.xml +++ b/OsmAnd/res/layout/fragment_import.xml @@ -23,16 +23,22 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" - android:background="?attr/bg_color" - android:gravity="center" - android:minHeight="@dimen/bottom_sheet_title_height" android:orientation="vertical"> + + + android:background="@android:color/transparent" + android:stateListAnimator="@animator/appbar_always_elevated"> = 2) { - onContinueButtonClickAction(); - } else { - expandableList.smoothScrollToPositionFromTop(0, 0, 100); - } - } - }); - - ViewTreeObserver treeObserver = buttonsContainer.getViewTreeObserver(); - treeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - if (buttonsContainer != null) { - ViewTreeObserver vts = buttonsContainer.getViewTreeObserver(); - int height = buttonsContainer.getMeasuredHeight(); - expandableList.setPadding(0, 0, 0, height); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - vts.removeOnGlobalLayoutListener(this); - } else { - vts.removeGlobalOnLayoutListener(this); + if (expandableList.getHeaderViewsCount() <= 1) { + if (hasSelectedData()) { + onContinueButtonClickAction(); } + } else { + expandableList.smoothScrollToPosition(0); } } }); @@ -202,10 +186,10 @@ public abstract class BaseSettingsListFragment extends BaseOsmAndFragment implem toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if (!hasSelectedData()) { - dismissFragment(); - } else { + if (hasSelectedData()) { showExitDialog(); + } else { + dismissFragment(); } } }); @@ -285,13 +269,24 @@ public abstract class BaseSettingsListFragment extends BaseOsmAndFragment implem updateAvailableSpace(); } + protected List getItemsForType(ExportSettingsType type) { + for (SettingsCategoryItems categoryItems : dataList.values()) { + if (categoryItems.getTypes().contains(type)) { + return (List) categoryItems.getItemsForType(type); + } + } + return null; + } + + protected List getSelectedItemsForType(ExportSettingsType type) { + return (List) selectedItemsMap.get(type); + } + @Override - public void onTypeClicked(ExportSettingsCategory category, ExportSettingsType type) { + public void onTypeClicked(ExportSettingsType type) { FragmentManager fragmentManager = getFragmentManager(); if (fragmentManager != null && type != ExportSettingsType.GLOBAL && type != ExportSettingsType.SEARCH_HISTORY) { - List items = (List) dataList.get(category).getItemsForType(type); - List selectedItems = (List) selectedItemsMap.get(type); - ExportItemsBottomSheet.showInstance(type, selectedItems, items, fragmentManager, this); + ExportItemsBottomSheet.showInstance(fragmentManager, type, this, exportMode); } } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportItemsBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportItemsBottomSheet.java index 49dd920841..45b417f6f7 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportItemsBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportItemsBottomSheet.java @@ -14,11 +14,15 @@ import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import net.osmand.AndroidUtils; +import net.osmand.GPXUtilities.GPXTrackAnalysis; import net.osmand.IndexConstants; import net.osmand.PlatformUtil; import net.osmand.map.ITileSource; import net.osmand.map.TileSourceManager.TileSourceTemplate; import net.osmand.plus.FavouritesDbHelper.FavoriteGroup; +import net.osmand.plus.GPXDatabase.GpxDataItem; +import net.osmand.plus.GpxDbHelper.GpxDataItemCallback; +import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.SQLiteTileSource; @@ -28,6 +32,7 @@ import net.osmand.plus.base.MenuBottomSheetDialogFragment; import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton; import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton.Builder; +import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription; import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.SimpleDividerItem; import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo; @@ -47,6 +52,7 @@ import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean; import net.osmand.plus.settings.backend.ExportSettingsType; import net.osmand.plus.settings.backend.backup.FileSettingsItem; +import net.osmand.plus.settings.backend.backup.FileSettingsItem.FileSubtype; import net.osmand.plus.settings.backend.backup.GlobalSettingsItem; import net.osmand.plus.settings.fragments.ExportSettingsAdapter.OnItemSelectedListener; import net.osmand.util.Algorithms; @@ -67,18 +73,43 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment { public static final String TAG = ExportItemsBottomSheet.class.getSimpleName(); private static final Log LOG = PlatformUtil.getLog(ExportItemsBottomSheet.class); + private static final String SETTINGS_TYPE_KEY = "settings_type_key"; + private static final String EXPORT_MODE_KEY = "export_mode_key"; + private OsmandApplication app; private UiUtilities uiUtilities; private ExportSettingsType type; - private List allItems; - private List selectedItems = new ArrayList<>(); + private final List allItems = new ArrayList<>(); + private final List selectedItems = new ArrayList<>(); private TextView selectedSize; private ThreeStateCheckbox checkBox; private int activeColorRes; private int secondaryColorRes; + private boolean exportMode; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (savedInstanceState != null) { + exportMode = savedInstanceState.getBoolean(EXPORT_MODE_KEY); + type = ExportSettingsType.valueOf(savedInstanceState.getString(SETTINGS_TYPE_KEY)); + } + Fragment target = getTargetFragment(); + if (target instanceof BaseSettingsListFragment) { + BaseSettingsListFragment fragment = (BaseSettingsListFragment) target; + List items = fragment.getItemsForType(type); + if (items != null) { + allItems.addAll(items); + } + List selectedItemsForType = fragment.getSelectedItemsForType(type); + if (selectedItemsForType != null) { + selectedItems.addAll(selectedItemsForType); + } + } + } @Override public void createMenuItems(Bundle savedInstanceState) { @@ -111,11 +142,18 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment { }) .setTag(object); setupBottomSheetItem(builder, object); - item[0] = (BottomSheetItemWithCompoundButton) builder.create(); + item[0] = builder.create(); items.add(item[0]); } } + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(EXPORT_MODE_KEY, exportMode); + outState.putString(SETTINGS_TYPE_KEY, type.name()); + } + private BaseBottomSheetItem createTitleItem() { LayoutInflater themedInflater = UiUtilities.getInflater(requireContext(), nightMode); View view = themedInflater.inflate(R.layout.settings_group_title, null); @@ -207,15 +245,13 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment { dismiss(); } - public static void showInstance(@NonNull ExportSettingsType type, List selectedItems, List allItems, @NonNull FragmentManager fm, @Nullable Fragment target) { + public static void showInstance(@NonNull FragmentManager fm, @NonNull ExportSettingsType type, + @NonNull BaseSettingsListFragment target, boolean exportMode) { try { if (!fm.isStateSaved() && fm.findFragmentByTag(TAG) == null) { ExportItemsBottomSheet fragment = new ExportItemsBottomSheet(); fragment.type = type; - fragment.allItems = (List) allItems; - if (selectedItems != null) { - fragment.selectedItems.addAll(selectedItems); - } + fragment.exportMode = exportMode; fragment.setTargetFragment(target, 0); fragment.show(fm, TAG); } @@ -234,7 +270,7 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment { return null; } - private void setupBottomSheetItem(BottomSheetItemWithCompoundButton.Builder builder, Object object) { + private void setupBottomSheetItem(Builder builder, Object object) { if (object instanceof ApplicationModeBean) { ApplicationModeBean modeBean = (ApplicationModeBean) object; String profileName = modeBean.userProfileName; @@ -298,9 +334,8 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment { builder.setTitle(group.getDisplayName(app)); int color = group.getColor() == 0 ? ContextCompat.getColor(app, R.color.color_favorite) : group.getColor(); builder.setIcon(uiUtilities.getPaintedIcon(R.drawable.ic_action_folder, color)); - int points = group.getPoints().size(); - String itemsDescr = app.getString(R.string.shared_string_gpx_points); + String itemsDescr = getString(R.string.shared_string_gpx_points); builder.setDescription(getString(R.string.ltr_or_rtl_combine_via_colon, itemsDescr, points)); } else if (object instanceof GlobalSettingsItem) { GlobalSettingsItem globalSettingsItem = (GlobalSettingsItem) object; @@ -316,7 +351,7 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment { builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_history, activeColorRes)); } int selectedMarkers = markersGroup.getMarkers().size(); - String itemsDescr = app.getString(R.string.shared_string_items); + String itemsDescr = getString(R.string.shared_string_items); builder.setDescription(getString(R.string.ltr_or_rtl_combine_via_colon, itemsDescr, selectedMarkers)); } else if (object instanceof HistoryEntry) { HistoryEntry historyEntry = (HistoryEntry) object; @@ -326,7 +361,7 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment { } private void setupBottomSheetItemForFile(Builder builder, File file) { - FileSettingsItem.FileSubtype fileSubtype = FileSettingsItem.FileSubtype.getSubtypeByPath(app, file.getPath()); + FileSubtype fileSubtype = FileSubtype.getSubtypeByPath(app, file.getPath()); builder.setTitle(file.getName()); if (file.getAbsolutePath().contains(IndexConstants.RENDERERS_DIR)) { builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_map_style, activeColorRes)); @@ -334,8 +369,9 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment { builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_route_distance, activeColorRes)); } else if (file.getAbsolutePath().contains(IndexConstants.GPX_INDEX_DIR)) { builder.setTitle(GpxUiHelper.getGpxTitle(file.getName())); + builder.setTag(file); + builder.setDescription(getTrackDescr(file)); builder.setIcon(uiUtilities.getIcon(R.drawable.ic_action_route_distance, activeColorRes)); - builder.setDescription(file.getParentFile().getName()); } else if (file.getAbsolutePath().contains(IndexConstants.AV_INDEX_DIR)) { int iconId = AudioVideoNotesPlugin.getIconIdForRecordingFile(file); if (iconId == -1) { @@ -360,6 +396,60 @@ public class ExportItemsBottomSheet extends MenuBottomSheetDialogFragment { } } + private final GpxDataItemCallback gpxDataItemCallback = new GpxDataItemCallback() { + @Override + public boolean isCancelled() { + return false; + } + + @Override + public void onGpxDataItemReady(GpxDataItem item) { + for (BaseBottomSheetItem bottomSheetItem : items) { + if (Algorithms.objectEquals(item.getFile(), bottomSheetItem.getTag())) { + ((BottomSheetItemWithDescription) bottomSheetItem).setDescription(getTrackDescrForDataItem(item)); + break; + } + } + } + }; + + private String getTrackDescr(@NonNull File file) { + String folder = ""; + File parent = file.getParentFile(); + if (parent != null) { + folder = Algorithms.capitalizeFirstLetter(parent.getName()); + } + if (exportMode) { + GpxDataItem dataItem = getDataItem(file, gpxDataItemCallback); + if (dataItem != null) { + return getTrackDescrForDataItem(dataItem); + } + } else { + String date = OsmAndFormatter.getFormattedDate(app, file.lastModified()); + String size = AndroidUtils.formatSize(app, file.length()); + String descr = getString(R.string.ltr_or_rtl_combine_via_bold_point, folder, date); + return getString(R.string.ltr_or_rtl_combine_via_comma, descr, size); + } + return null; + } + + private String getTrackDescrForDataItem(@NonNull GpxDataItem dataItem) { + GPXTrackAnalysis analysis = dataItem.getAnalysis(); + if (analysis != null) { + File parent = dataItem.getFile().getParentFile(); + String folder = Algorithms.capitalizeFirstLetter(parent.getName()); + String dist = OsmAndFormatter.getFormattedDistance(analysis.totalDistance, app); + String points = analysis.wptPoints + " " + getString(R.string.shared_string_gpx_points).toLowerCase(); + String descr = getString(R.string.ltr_or_rtl_combine_via_bold_point, folder, dist); + return getString(R.string.ltr_or_rtl_combine_via_comma, descr, points); + } + return null; + } + + private GpxDataItem getDataItem(File file, @Nullable GpxDataItemCallback callback) { + return app.getGpxDbHelper().getItem(file, callback); + } + private String getMapDescription(File file) { if (file.isDirectory() || file.getName().endsWith(IndexConstants.BINARY_WIKIVOYAGE_MAP_INDEX_EXT)) { return getString(R.string.online_map); diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsAdapter.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsAdapter.java index edd6419c74..1eec036171 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsAdapter.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsAdapter.java @@ -55,6 +55,9 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { private final boolean nightMode; private final int activeColorRes; private final int secondaryColorRes; + private final int groupViewHeight; + private final int childViewHeight; + private final int listBottomPadding; ExportSettingsAdapter(OsmandApplication app, OnItemSelectedListener listener, boolean nightMode) { this.app = app; @@ -64,6 +67,9 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { themedInflater = UiUtilities.getInflater(app, nightMode); activeColorRes = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light; secondaryColorRes = nightMode ? R.color.icon_color_secondary_dark : R.color.icon_color_secondary_light; + groupViewHeight = app.getResources().getDimensionPixelSize(R.dimen.setting_list_item_group_height); + childViewHeight = app.getResources().getDimensionPixelSize(R.dimen.setting_list_item_large_height); + listBottomPadding = app.getResources().getDimensionPixelSize(R.dimen.fab_recycler_view_padding_bottom); } @Override @@ -71,8 +77,7 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { View group = convertView; if (group == null) { group = themedInflater.inflate(R.layout.profile_data_list_item_group, parent, false); - int minHeight = app.getResources().getDimensionPixelSize(R.dimen.setting_list_item_group_height); - group.findViewById(R.id.item_container).setMinimumHeight(minHeight); + group.findViewById(R.id.item_container).setMinimumHeight(groupViewHeight); } final ExportSettingsCategory category = itemsTypes.get(groupPosition); final SettingsCategoryItems items = itemsMap.get(category); @@ -111,6 +116,9 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { } }); + boolean addPadding = !isExpanded && groupPosition == getGroupCount() - 1; + group.setPadding(0, 0, 0, addPadding ? listBottomPadding : 0); + adjustIndicator(app, groupPosition, isExpanded, group, nightMode); AndroidUiHelper.updateVisibility(group.findViewById(R.id.divider), isExpanded); AndroidUiHelper.updateVisibility(group.findViewById(R.id.card_top_divider), true); @@ -125,8 +133,7 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { View child = convertView; if (child == null) { child = themedInflater.inflate(R.layout.profile_data_list_item_group, parent, false); - int minHeight = app.getResources().getDimensionPixelSize(R.dimen.setting_list_item_large_height); - child.findViewById(R.id.item_container).setMinimumHeight(minHeight); + child.findViewById(R.id.item_container).setMinimumHeight(childViewHeight); } final ExportSettingsCategory category = itemsTypes.get(groupPosition); final SettingsCategoryItems categoryItems = itemsMap.get(category); @@ -162,7 +169,7 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { @Override public void onClick(View v) { if (listener != null) { - listener.onTypeClicked(category, type); + listener.onTypeClicked(type); } } }); @@ -179,7 +186,8 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { notifyDataSetChanged(); } }); - + boolean addPadding = isLastChild && groupPosition == getGroupCount() - 1; + child.setPadding(0, 0, 0, addPadding ? listBottomPadding : 0); AndroidUiHelper.updateVisibility(child.findViewById(R.id.card_bottom_divider), isLastChild); return child; @@ -337,7 +345,7 @@ public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter { void onCategorySelected(ExportSettingsCategory type, boolean selected); - void onTypeClicked(ExportSettingsCategory category, ExportSettingsType type); + void onTypeClicked(ExportSettingsType type); } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsFragment.java index c46168ec67..af954db7c5 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportSettingsFragment.java @@ -75,6 +75,7 @@ public class ExportSettingsFragment extends BaseSettingsListFragment { progressMax = savedInstanceState.getInt(PROGRESS_MAX_KEY); progressValue = savedInstanceState.getInt(PROGRESS_VALUE_KEY); } + exportMode = true; dataList = app.getSettingsHelper().getAdditionalData(globalExport); } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java index f078d1c34b..18e4f3cec5 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java @@ -100,6 +100,7 @@ public class ImportSettingsFragment extends BaseSettingsListFragment { if (savedInstanceState != null) { duplicateStartTime = savedInstanceState.getLong(DUPLICATES_START_TIME_KEY); } + exportMode = false; settingsHelper = app.getSettingsHelper(); ImportAsyncTask importTask = settingsHelper.getImportTask();