mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-10-02 17:43:06 +02:00
Migration to Material Components theme and style.
New night theme mainly white on black. Fixes #1122. Fixes #957.
This commit is contained in:
committed by
Román Martínez
parent
72f7b12da6
commit
79e45f7aea
@@ -120,10 +120,10 @@ public class StatisticsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
|
||||
return;
|
||||
}
|
||||
this.value.setText(statisticData.hasValue() ? statisticData.getValue() : context.getString(R.string.value_unknown));
|
||||
this.value.setTextAppearance(context, statisticData.getField().isPrimary() ? R.style.StatsPrimaryValue : R.style.StatsSecondaryValue);
|
||||
this.value.setTextAppearance(context, statisticData.getField().isPrimary() ? R.style.TextAppearance_OpenTracks_PrimaryValue : R.style.TextAppearance_OpenTracks_SecondaryValue);
|
||||
this.unit.setText(statisticData.getUnit());
|
||||
this.descMain.setText(statisticData.getField().getTitle());
|
||||
this.descMain.setTextAppearance(context, statisticData.getField().isPrimary() ? R.style.StatsPrimaryLabel : R.style.StatsSecondaryLabel);
|
||||
this.descMain.setTextAppearance(context, statisticData.getField().isPrimary() ? R.style.TextAppearance_OpenTracks_PrimaryHeader : R.style.TextAppearance_OpenTracks_SecondaryHeader);
|
||||
if (statisticData.hasDescription()) {
|
||||
this.descSecondary.setVisibility(View.VISIBLE);
|
||||
this.descSecondary.setText(statisticData.getDescription());
|
||||
@@ -147,8 +147,8 @@ public class StatisticsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
|
||||
if (statisticData == null) {
|
||||
return;
|
||||
}
|
||||
this.value.setTextAppearance(context, statisticData.getField().isPrimary() ? R.style.StatsPrimaryValue : R.style.StatsSecondaryValue);
|
||||
this.descMain.setTextAppearance(context, statisticData.getField().isPrimary() ? R.style.StatsPrimaryLabel : R.style.StatsSecondaryLabel);
|
||||
this.value.setTextAppearance(context, statisticData.getField().isPrimary() ? R.style.TextAppearance_OpenTracks_PrimaryValue : R.style.TextAppearance_OpenTracks_SecondaryValue);
|
||||
this.descMain.setTextAppearance(context, statisticData.getField().isPrimary() ? R.style.TextAppearance_OpenTracks_PrimaryHeader : R.style.TextAppearance_OpenTracks_SecondaryHeader);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ class ChooseActivityTypeImageAdapter extends BaseAdapter {
|
||||
}
|
||||
|
||||
if (position == selected) {
|
||||
imageView.setBackgroundColor(ContextCompat.getColor(parent.getContext(), R.color.colorAccent));
|
||||
imageView.setBackgroundColor(ContextCompat.getColor(parent.getContext(), R.color.opentracks_secondary_color));
|
||||
} else {
|
||||
imageView.setBackgroundColor(Color.TRANSPARENT);
|
||||
}
|
||||
|
||||
+8
-16
@@ -2,8 +2,6 @@ package de.dennisguse.opentracks.settings;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -17,6 +15,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import de.dennisguse.opentracks.AbstractActivity;
|
||||
import de.dennisguse.opentracks.ui.util.ArrayAdapterFilterDisabled;
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.databinding.ActivitySettingsCustomLayoutBinding;
|
||||
import de.dennisguse.opentracks.ui.customRecordingLayout.DataField;
|
||||
@@ -80,23 +79,16 @@ public class SettingsCustomLayoutEditActivity extends AbstractActivity implement
|
||||
itemTouchHelper.attachToRecyclerView(recyclerViewVisible);
|
||||
|
||||
// Spinner with items per row.
|
||||
ArrayAdapter<Integer> spinnerAdapter = new ArrayAdapter<>(this,
|
||||
ArrayAdapterFilterDisabled<Integer> 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);
|
||||
|
||||
+9
-8
@@ -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);
|
||||
}
|
||||
|
||||
+2
-2
@@ -43,8 +43,8 @@ public class SettingsCustomLayoutEditAdapter extends RecyclerView.Adapter<Recycl
|
||||
viewHolder.title.setText(field.getTitle());
|
||||
viewHolder.value.setText(StatisticsUtils.emptyValue(context, field.getKey()));
|
||||
|
||||
viewHolder.title.setTextAppearance(context, field.isVisible() ? (field.isPrimary() ? R.style.StatsPrimaryLabel : R.style.StatsSecondaryLabel) : R.style.StatsLabelHidden);
|
||||
viewHolder.value.setTextAppearance(context, field.isVisible() ? (field.isPrimary() ? R.style.StatsPrimaryValue : R.style.StatsSecondaryValue) : R.style.StatsValueHidden);
|
||||
viewHolder.title.setTextAppearance(context, field.isVisible() ? (field.isPrimary() ? R.style.TextAppearance_OpenTracks_PrimaryHeader : R.style.TextAppearance_OpenTracks_SecondaryHeader) : R.style.TextAppearance_OpenTracks_HiddenHeader);
|
||||
viewHolder.value.setTextAppearance(context, field.isVisible() ? (field.isPrimary() ? R.style.TextAppearance_OpenTracks_PrimaryValue : R.style.TextAppearance_OpenTracks_SecondaryValue) : R.style.TextAppearance_OpenTracks_HiddenValue);
|
||||
viewHolder.statusIcon.setVisibility(field.isVisible() ? View.GONE : View.VISIBLE);
|
||||
viewHolder.statusIcon.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.ic_baseline_visibility_off_24));
|
||||
viewHolder.moveIcon.setVisibility(field.isVisible() ? View.VISIBLE : View.GONE);
|
||||
|
||||
@@ -5,7 +5,6 @@ import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
@@ -33,6 +32,7 @@ public class IntervalsFragment extends Fragment {
|
||||
|
||||
private static final String FROM_TOP_TO_BOTTOM_KEY = "fromTopToBottom";
|
||||
private static final String TRACK_ID_KEY = "trackId";
|
||||
private static final String SELECTED_INTERVAL_KEY = "selectedIntervalKey";
|
||||
|
||||
private IntervalStatisticsModel viewModel;
|
||||
protected IntervalStatisticsAdapter.StackMode stackModeListView;
|
||||
@@ -41,7 +41,7 @@ public class IntervalsFragment extends Fragment {
|
||||
private Track.Id trackId;
|
||||
private boolean metricUnits;
|
||||
private IntervalStatisticsAdapter adapter;
|
||||
private ArrayAdapter<IntervalStatisticsModel.IntervalOption> spinnerAdapter;
|
||||
private ArrayAdapter<IntervalStatisticsModel.IntervalOption> 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<List<IntervalStatistics.Interval>> liveData = viewModel.getIntervalStats(trackId, metricUnits, selectedInterval);
|
||||
liveData.observe(getActivity(), intervalList -> adapter.swapData(intervalList, metricUnits, isReportSpeed));
|
||||
|
||||
@@ -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<T> extends ArrayAdapter<T> {
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user