diff --git a/.gitignore b/.gitignore index 6654e4ca5..6a84c6d12 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,7 @@ captures/ .idea/dictionaries .idea/libraries .idea/caches +.idea/misc.xml # IntelliJ IDEA diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 55d7f7942..000000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/java/de/dennisguse/opentracks/adapters/StatisticsAdapter.java b/src/main/java/de/dennisguse/opentracks/adapters/StatisticsAdapter.java index 87268e380..fcef8fe5c 100644 --- a/src/main/java/de/dennisguse/opentracks/adapters/StatisticsAdapter.java +++ b/src/main/java/de/dennisguse/opentracks/adapters/StatisticsAdapter.java @@ -120,10 +120,10 @@ public class StatisticsAdapter extends RecyclerView.Adapter spinnerAdapter = new ArrayAdapter<>(this, + ArrayAdapterFilterDisabled rowsOptionAdapter = new ArrayAdapterFilterDisabled<>(this, android.R.layout.simple_spinner_dropdown_item, IntStream.of(getResources().getIntArray(R.array.stats_custom_layout_fields_columns_per_row)).boxed().toArray(Integer[]::new)); - viewBinding.spinnerOptions.setAdapter(spinnerAdapter); - viewBinding.spinnerOptions.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - numColumns = position + 1; - gridLayoutManager.setSpanCount(numColumns); - } - - @Override - public void onNothingSelected(AdapterView parent) { - - } + viewBinding.rowsOptions.setAdapter(rowsOptionAdapter); + viewBinding.rowsOptions.setOnItemClickListener((parent, view, position, id) -> { + numColumns = position + 1; + gridLayoutManager.setSpanCount(numColumns); }); - viewBinding.spinnerOptions.setSelection(numColumns - 1); + + viewBinding.rowsOptions.setText(rowsOptionAdapter.getItem(numColumns - 1).toString(), false); // Recycler view with not visible stats. layoutFieldsHidden = StatisticsUtils.filterVisible(layout, false); diff --git a/src/main/java/de/dennisguse/opentracks/ui/aggregatedStatistics/FilterDialogFragment.java b/src/main/java/de/dennisguse/opentracks/ui/aggregatedStatistics/FilterDialogFragment.java index 86a203a30..3ebbf2da1 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/aggregatedStatistics/FilterDialogFragment.java +++ b/src/main/java/de/dennisguse/opentracks/ui/aggregatedStatistics/FilterDialogFragment.java @@ -5,11 +5,10 @@ import android.content.Context; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; -import android.widget.CheckBox; import android.widget.DatePicker; -import android.widget.GridLayout; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -17,6 +16,8 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.FragmentManager; +import com.google.android.material.button.MaterialButton; +import com.google.android.material.button.MaterialButtonToggleGroup; import com.google.android.material.textfield.TextInputEditText; import java.time.LocalDate; @@ -61,17 +62,17 @@ public class FilterDialogFragment extends DialogFragment { LayoutInflater inflater = LayoutInflater.from(getActivity()); View layout = inflater.inflate(R.layout.fragment_filter_dialog, null, false); - GridLayout itemsLayout = layout.findViewById(R.id.filter_items); + MaterialButtonToggleGroup itemsLayout = layout.findViewById(R.id.filter_items); builder.setView(layout); for (FilterItem item : filterItems) { View view = inflater.inflate(R.layout.fragment_filter_dialog_item, null); - CheckBox checkBox = view.findViewById(R.id.filter_dialog_check_button); - checkBox.setText(item.value); - checkBox.setChecked(item.isChecked); - checkBox.setTag(item.id); - checkBox.setOnClickListener(v -> item.isChecked = !item.isChecked); + MaterialButton button = view.findViewById(R.id.filter_dialog_check_button); + button.setText(item.value); + button.setChecked(item.isChecked); + button.setTag(item.id); + button.setOnClickListener(v -> item.isChecked = !item.isChecked); itemsLayout.addView(view); } diff --git a/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/SettingsCustomLayoutEditAdapter.java b/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/SettingsCustomLayoutEditAdapter.java index 3bb4b2bea..848294e79 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/SettingsCustomLayoutEditAdapter.java +++ b/src/main/java/de/dennisguse/opentracks/ui/customRecordingLayout/SettingsCustomLayoutEditAdapter.java @@ -43,8 +43,8 @@ public class SettingsCustomLayoutEditAdapter extends RecyclerView.Adapter spinnerAdapter; + private ArrayAdapter intervalsAdapter; private boolean isReportSpeed; @@ -50,8 +50,8 @@ public class IntervalsFragment extends Fragment { protected final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (sharedPreferences, key) -> { if (PreferencesUtils.isKey(R.string.stats_units_key, key) || PreferencesUtils.isKey(R.string.stats_rate_key, key)) { updateIntervals(PreferencesUtils.isMetricUnits(), selectedInterval); - if (spinnerAdapter != null) { - spinnerAdapter.notifyDataSetChanged(); + if (intervalsAdapter != null) { + intervalsAdapter.notifyDataSetChanged(); } } }; @@ -76,6 +76,15 @@ public class IntervalsFragment extends Fragment { super.onCreate(savedInstanceState); stackModeListView = getArguments().getBoolean(FROM_TOP_TO_BOTTOM_KEY, true) ? IntervalStatisticsAdapter.StackMode.STACK_FROM_TOP : IntervalStatisticsAdapter.StackMode.STACK_FROM_BOTTOM; trackId = getArguments().getParcelable(TRACK_ID_KEY); + if (savedInstanceState != null) { + selectedInterval = (IntervalStatisticsModel.IntervalOption) savedInstanceState.getSerializable(SELECTED_INTERVAL_KEY); + } + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + outState.putSerializable(SELECTED_INTERVAL_KEY, selectedInterval); } @Override @@ -93,7 +102,7 @@ public class IntervalsFragment extends Fragment { // TODO handle empty view: before we did viewBinding.intervalList.setEmptyView(viewBinding.intervalListEmptyView); viewBinding.intervalList.setAdapter(adapter); - spinnerAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_dropdown_item, IntervalStatisticsModel.IntervalOption.values()) { + intervalsAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_dropdown_item, IntervalStatisticsModel.IntervalOption.values()) { @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { @@ -112,17 +121,13 @@ public class IntervalsFragment extends Fragment { } }; - viewBinding.spinnerIntervals.setAdapter(spinnerAdapter); - viewBinding.spinnerIntervals.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView adapterView, View view, int i, long l) { - updateIntervals(metricUnits, IntervalStatisticsModel.IntervalOption.values()[i]); - } + viewBinding.intervalsDropdown.setAdapter(intervalsAdapter); + viewBinding.intervalsDropdown.setOnItemClickListener((parent, view1, position, id) -> updateIntervals(metricUnits, IntervalStatisticsModel.IntervalOption.values()[position])); - @Override - public void onNothingSelected(AdapterView adapterView) { - } - }); + viewBinding.intervalsDropdown.setText( + getContext().getString(R.string.value_integer_kilometer, Integer.parseInt(selectedInterval != null ? selectedInterval.toString() : IntervalStatisticsModel.IntervalOption.values()[0].toString())), + false + ); } @Override @@ -173,6 +178,7 @@ public class IntervalsFragment extends Fragment { if (viewModel == null) { return; } + viewBinding.intervalRate.setText(isReportSpeed ? getString(R.string.stats_speed) : getString(R.string.stats_pace)); LiveData> liveData = viewModel.getIntervalStats(trackId, metricUnits, selectedInterval); liveData.observe(getActivity(), intervalList -> adapter.swapData(intervalList, metricUnits, isReportSpeed)); diff --git a/src/main/java/de/dennisguse/opentracks/ui/util/ArrayAdapterFilterDisabled.java b/src/main/java/de/dennisguse/opentracks/ui/util/ArrayAdapterFilterDisabled.java new file mode 100644 index 000000000..27db296bb --- /dev/null +++ b/src/main/java/de/dennisguse/opentracks/ui/util/ArrayAdapterFilterDisabled.java @@ -0,0 +1,35 @@ +package de.dennisguse.opentracks.ui.util; + +import android.content.Context; +import android.widget.ArrayAdapter; +import android.widget.Filter; + +import androidx.annotation.NonNull; + +// https://github.com/material-components/material-components-android/issues/1464 +public class ArrayAdapterFilterDisabled extends ArrayAdapter { + + public ArrayAdapterFilterDisabled(@NonNull Context context, int resource, @NonNull T[] objects) { + super(context, resource, objects); + } + + @NonNull + @Override + public Filter getFilter() { + return new NeverFilter(); + } + + private class NeverFilter extends Filter { + protected FilterResults performFiltering(CharSequence prefix) { + return new FilterResults(); + } + + protected void publishResults(CharSequence constraint, FilterResults results) { + if (ArrayAdapterFilterDisabled.this.getCount() > 0) { + notifyDataSetChanged(); + } else { + notifyDataSetInvalidated(); + } + } + } +} diff --git a/src/main/java/de/dennisguse/opentracks/ui/util/AutoCompleteTextViewForDropdown.java b/src/main/java/de/dennisguse/opentracks/ui/util/AutoCompleteTextViewForDropdown.java new file mode 100644 index 000000000..560f7674b --- /dev/null +++ b/src/main/java/de/dennisguse/opentracks/ui/util/AutoCompleteTextViewForDropdown.java @@ -0,0 +1,22 @@ +package de.dennisguse.opentracks.ui.util; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.material.textfield.MaterialAutoCompleteTextView; + +// https://github.com/material-components/material-components-android/issues/1464 +public class AutoCompleteTextViewForDropdown extends MaterialAutoCompleteTextView { + + public AutoCompleteTextViewForDropdown(@NonNull final Context context, @Nullable final AttributeSet attributeSet) { + super(context, attributeSet); + } + + @Override + public boolean getFreezesText() { + return false; + } +} diff --git a/src/main/java/de/dennisguse/opentracks/ui/util/ListItemUtils.java b/src/main/java/de/dennisguse/opentracks/ui/util/ListItemUtils.java index 14f4c0ef0..8d229ac1e 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/util/ListItemUtils.java +++ b/src/main/java/de/dennisguse/opentracks/ui/util/ListItemUtils.java @@ -17,11 +17,9 @@ package de.dennisguse.opentracks.ui.util; import android.content.Context; -import android.view.Gravity; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.TextView; import java.time.OffsetDateTime; @@ -77,11 +75,9 @@ public class ListItemUtils { TextView timeDistanceTextView = view.findViewById(R.id.list_item_time_distance); String timeDistanceText; if (isRecording) { - timeDistanceTextView.setTextColor(context.getResources().getColor(isPaused ? android.R.color.white : R.color.recording_text)); timeDistanceText = context.getString(isPaused ? R.string.generic_paused : R.string.generic_recording); } else { // Match list_item_time_distance in list_item.xml - timeDistanceTextView.setTextAppearance(context, R.style.TextSmall); timeDistanceText = getTimeDistance(totalTime, totalDistance); if (markerCount > 0) { timeDistanceText += " \u2027"; @@ -132,10 +128,6 @@ public class ListItemUtils { timeDistanceTextView.setSingleLine(true); setTextView(context, categoryDescriptionTextView, categoryDescription, hasPhoto); } - - // Adjust iconImageView layout gravity - LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) iconImageView.getLayoutParams(); - params.gravity = timeDistanceTextView.getVisibility() == View.GONE && markerCountIcon.getVisibility() == View.GONE ? Gravity.TOP : Gravity.CENTER_VERTICAL; } /** diff --git a/src/main/java/de/dennisguse/opentracks/ui/util/ThemeUtils.java b/src/main/java/de/dennisguse/opentracks/ui/util/ThemeUtils.java index c45efb606..f0d49c804 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/util/ThemeUtils.java +++ b/src/main/java/de/dennisguse/opentracks/ui/util/ThemeUtils.java @@ -42,14 +42,14 @@ public class ThemeUtils { } public static int getFontSizeSmallInPx(Context context) { - TypedArray typedArray = context.obtainStyledAttributes(R.style.TextSmall, new int[]{android.R.attr.textSize}); + TypedArray typedArray = context.obtainStyledAttributes(R.style.TextAppearance_MaterialComponents_Body2, new int[]{android.R.attr.textSize}); int fontSize = typedArray.getDimensionPixelSize(0, 12); typedArray.recycle(); return fontSize; } public static int getFontSizeMediumInPx(Context context) { - TypedArray typedArray = context.obtainStyledAttributes(R.style.TextMedium, new int[]{android.R.attr.textSize}); + TypedArray typedArray = context.obtainStyledAttributes(R.style.TextAppearance_MaterialComponents_Body1, new int[]{android.R.attr.textSize}); int fontSize = typedArray.getDimensionPixelSize(0, 15); typedArray.recycle(); return fontSize; diff --git a/src/main/res/drawable/activated_background.xml b/src/main/res/drawable/activated_background.xml index e0fe1f23e..bcab68986 100644 --- a/src/main/res/drawable/activated_background.xml +++ b/src/main/res/drawable/activated_background.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/src/main/res/layout-land/controller_fragment.xml b/src/main/res/layout-land/controller_fragment.xml index 62e84afd0..e1d0dc624 100644 --- a/src/main/res/layout-land/controller_fragment.xml +++ b/src/main/res/layout-land/controller_fragment.xml @@ -38,17 +38,17 @@ limitations under the License. diff --git a/src/main/res/layout-land/track_list.xml b/src/main/res/layout-land/track_list.xml index 567f6f599..1db2c980f 100644 --- a/src/main/res/layout-land/track_list.xml +++ b/src/main/res/layout-land/track_list.xml @@ -89,7 +89,7 @@ limitations under the License. android:layout_weight="24"> diff --git a/src/main/res/layout/about.xml b/src/main/res/layout/about.xml index 5e2d538d9..93d24ebc7 100644 --- a/src/main/res/layout/about.xml +++ b/src/main/res/layout/about.xml @@ -32,54 +32,55 @@ - + - + @@ -87,15 +88,17 @@ - + @@ -103,6 +106,7 @@ diff --git a/src/main/res/layout/activity_settings_custom_layout.xml b/src/main/res/layout/activity_settings_custom_layout.xml index 7061a9a61..957a3b74c 100644 --- a/src/main/res/layout/activity_settings_custom_layout.xml +++ b/src/main/res/layout/activity_settings_custom_layout.xml @@ -7,27 +7,20 @@ - + android:hint="@string/settings_recording_customize_layout_select_columns"> - + android:inputType="none" /> - - - + @@ -39,17 +40,22 @@ android:id="@+id/custom_layout_list_bottom_bar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" - android:gravity="center_vertical" + android:layout_margin="16dp" + android:gravity="end" android:orientation="horizontal"> -