diff --git a/build.gradle b/build.gradle index c2a28ee1f..941d25f12 100644 --- a/build.gradle +++ b/build.gradle @@ -45,6 +45,10 @@ android { compileSdkVersion 30 + buildFeatures { + viewBinding = true + } + defaultConfig { applicationId "de.dennisguse.opentracks" versionCode 3661 diff --git a/src/main/java/de/dennisguse/opentracks/fragments/ChartFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/ChartFragment.java index 29efb2442..f3049dbf3 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/ChartFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/ChartFragment.java @@ -40,6 +40,7 @@ import de.dennisguse.opentracks.content.TrackDataListener; import de.dennisguse.opentracks.content.data.Marker; import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.TrackPoint; +import de.dennisguse.opentracks.databinding.ChartBinding; import de.dennisguse.opentracks.stats.TrackStatistics; import de.dennisguse.opentracks.stats.TrackStatisticsUpdater; import de.dennisguse.opentracks.util.LocationUtils; @@ -73,6 +74,8 @@ public class ChartFragment extends Fragment implements TrackDataListener { private TrackStatisticsUpdater trackStatisticsUpdater; private long startTime; + private ChartBinding viewBinding; + //TODO Why is this needed? private int recordingDistanceInterval; private String category = ""; @@ -147,15 +150,16 @@ public class ChartFragment extends Fragment implements TrackDataListener { @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.chart, container, false); + viewBinding = ChartBinding.inflate(inflater, container, false); + return viewBinding.getRoot(); } @Override public void onStart() { super.onStart(); - ViewGroup layout = getView().findViewById(R.id.chart_view_layout); + LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); - layout.addView(chartView, layoutParams); + viewBinding.chartViewLayout.addView(chartView, layoutParams); } @Override @@ -183,6 +187,12 @@ public class ChartFragment extends Fragment implements TrackDataListener { layout.removeView(chartView); } + @Override + public void onDestroyView() { + super.onDestroyView(); + viewBinding = null; + } + @Override public void onTrackUpdated(Track track) { if (isResumed()) { diff --git a/src/main/java/de/dennisguse/opentracks/fragments/ChooseActivityTypeDialogFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/ChooseActivityTypeDialogFragment.java index 6b578473e..b03b94f12 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/ChooseActivityTypeDialogFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/ChooseActivityTypeDialogFragment.java @@ -7,7 +7,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; -import android.widget.GridView; import androidx.annotation.NonNull; import androidx.fragment.app.DialogFragment; @@ -17,6 +16,7 @@ import java.util.ArrayList; import java.util.List; import de.dennisguse.opentracks.R; +import de.dennisguse.opentracks.databinding.ChooseActivityTypeBinding; import de.dennisguse.opentracks.util.TrackIconUtils; /** @@ -39,6 +39,8 @@ public class ChooseActivityTypeDialogFragment extends DialogFragment implements return TrackIconUtils.getAllIconValues().indexOf(iconValue); } + private ChooseActivityTypeBinding viewBinding; + private final String preselectedCategory; private ChooseActivityTypeCaller chooseActivityTypeCaller; @@ -57,8 +59,7 @@ public class ChooseActivityTypeDialogFragment extends DialogFragment implements @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.choose_activity_type, container); - GridView gridView = view.findViewById(R.id.choose_activity_type_grid_view); + viewBinding = ChooseActivityTypeBinding.inflate(inflater, container, false); List imageIds = new ArrayList<>(); for (String iconValue : TrackIconUtils.getAllIconValues()) { @@ -66,15 +67,14 @@ public class ChooseActivityTypeDialogFragment extends DialogFragment implements } final ChooseActivityTypeImageAdapter imageAdapter = new ChooseActivityTypeImageAdapter(imageIds); - gridView.setAdapter(imageAdapter); - int position = getPosition(getContext(), preselectedCategory); if (position != -1) { imageAdapter.setSelected(position); } - gridView.setOnItemClickListener(this); - return view; + viewBinding.chooseActivityTypeGridView.setAdapter(imageAdapter); + viewBinding.chooseActivityTypeGridView.setOnItemClickListener(this); + return viewBinding.getRoot(); } public void onAttach(@NonNull Context context) { @@ -86,6 +86,11 @@ public class ChooseActivityTypeDialogFragment extends DialogFragment implements } } + @Override + public void onDestroyView() { + super.onDestroyView(); + viewBinding = null; + } @Override public void onItemClick(AdapterView adapterView, View view, int position, long id) { diff --git a/src/main/java/de/dennisguse/opentracks/fragments/IntervalsFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/IntervalsFragment.java index d7663831f..9ef4e0414 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/IntervalsFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/IntervalsFragment.java @@ -8,7 +8,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; -import android.widget.ListView; import android.widget.Spinner; import android.widget.TextView; @@ -25,6 +24,7 @@ import de.dennisguse.opentracks.content.TrackDataListener; import de.dennisguse.opentracks.content.data.Marker; import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.TrackPoint; +import de.dennisguse.opentracks.databinding.IntervalListViewBinding; import de.dennisguse.opentracks.util.PreferencesUtils; import de.dennisguse.opentracks.util.UnitConversions; import de.dennisguse.opentracks.viewmodels.IntervalStatistics; @@ -38,7 +38,6 @@ public class IntervalsFragment extends Fragment implements TrackDataListener { private static final String TAG = IntervalsFragment.class.getSimpleName(); private IntervalStatisticsModel viewModel; - private ListView intervalListView; protected IntervalStatisticsAdapter.StackMode stackModeListView; private IntervalStatisticsModel.IntervalOption selectedInterval; @@ -47,11 +46,11 @@ public class IntervalsFragment extends Fragment implements TrackDataListener { protected Spinner spinnerIntervals; private ArrayAdapter spinnerAdapter; - private TextView rateLabel; - private TrackDataHub trackDataHub; private String category; + private IntervalListViewBinding viewBinding; + protected final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (preferences, key) -> { if (PreferencesUtils.isKey(getContext(), R.string.stats_units_key, key) || PreferencesUtils.isKey(getContext(), R.string.stats_rate_key, key)) { intervalUnit = PreferencesUtils.isMetricUnits(getContext()) ? getContext().getString(R.string.unit_kilometer) : getContext().getString(R.string.unit_mile); @@ -68,7 +67,8 @@ public class IntervalsFragment extends Fragment implements TrackDataListener { @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.interval_list_view, container, false); + viewBinding = IntervalListViewBinding.inflate(inflater, container, false); + return viewBinding.getRoot(); } @Override @@ -78,10 +78,7 @@ public class IntervalsFragment extends Fragment implements TrackDataListener { PreferencesUtils.register(getContext(), sharedPreferenceChangeListener); intervalUnit = PreferencesUtils.isMetricUnits(getContext()) ? getContext().getString(R.string.unit_kilometer) : getContext().getString(R.string.unit_mile); - rateLabel = view.findViewById(R.id.interval_rate); - - intervalListView = view.findViewById(R.id.interval_list); - intervalListView.setEmptyView(view.findViewById(R.id.interval_list_empty_view)); + viewBinding.intervalList.setEmptyView(view.findViewById(R.id.interval_list_empty_view)); stackModeListView = IntervalStatisticsAdapter.StackMode.STACK_FROM_TOP; @@ -133,13 +130,18 @@ public class IntervalsFragment extends Fragment implements TrackDataListener { pauseTrackDataHub(); } + @Override + public void onDestroyView() { + super.onDestroyView(); + viewBinding = null; + } + @Override public void onDestroy() { super.onDestroy(); PreferencesUtils.unregister(getContext(), sharedPreferenceChangeListener); - intervalListView = null; adapter = null; spinnerIntervals = null; viewModel = null; @@ -149,14 +151,14 @@ public class IntervalsFragment extends Fragment implements TrackDataListener { * Update intervals through {@link IntervalStatisticsModel} view model. */ protected synchronized void loadIntervals() { - if (viewModel == null || intervalListView == null) { + if (viewModel == null) { return; } - boolean metricUnits = PreferencesUtils.isMetricUnits(getContext()) ? true : false; + boolean metricUnits = PreferencesUtils.isMetricUnits(getContext()); IntervalStatistics intervalStatistics = viewModel.getIntervalStats(metricUnits, selectedInterval); adapter = new IntervalStatisticsAdapter(getContext(), intervalStatistics.getIntervalList(), category, stackModeListView); - intervalListView.setAdapter(adapter); + viewBinding.intervalList.setAdapter(adapter); } /** @@ -184,10 +186,8 @@ public class IntervalsFragment extends Fragment implements TrackDataListener { category = track != null ? track.getCategory() : ""; // Set rate label. - if (rateLabel != null) { - boolean reportSpeed = PreferencesUtils.isReportSpeed(getContext(), category); - rateLabel.setText(reportSpeed ? R.string.stats_speed : R.string.stats_pace); - } + boolean reportSpeed = PreferencesUtils.isReportSpeed(getContext(), category); + viewBinding.intervalRate.setText(reportSpeed ? R.string.stats_speed : R.string.stats_pace); } } diff --git a/src/main/java/de/dennisguse/opentracks/fragments/MarkerDetailFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/MarkerDetailFragment.java index c2c717fd4..3b1435ff5 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/MarkerDetailFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/MarkerDetailFragment.java @@ -30,8 +30,6 @@ import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.AnimationUtils; -import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.NonNull; @@ -42,6 +40,7 @@ import de.dennisguse.opentracks.MarkerEditActivity; import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.content.data.Marker; import de.dennisguse.opentracks.content.provider.ContentProviderUtils; +import de.dennisguse.opentracks.databinding.MarkerDetailFragmentBinding; import de.dennisguse.opentracks.util.IntentUtils; import de.dennisguse.opentracks.util.ListItemUtils; import de.dennisguse.opentracks.util.MarkerUtils; @@ -64,10 +63,10 @@ public class MarkerDetailFragment extends Fragment { private ContentProviderUtils contentProviderUtils; private Handler handler; - private ImageView photoView; - private ImageView textGradient; - private LinearLayout markerInfo; private Marker marker; + + private MarkerDetailFragmentBinding viewBinding; + private final Runnable hideText = new Runnable() { @Override public void run() { @@ -84,12 +83,12 @@ public class MarkerDetailFragment extends Fragment { @Override public void onAnimationEnd(Animation anim) { - textGradient.setVisibility(View.GONE); - markerInfo.setVisibility(View.GONE); + viewBinding.markerDetailMarkerTextGradient.setVisibility(View.GONE); + viewBinding.markerDetailMarkerInfo.setVisibility(View.GONE); } }); - textGradient.startAnimation(animation); - markerInfo.startAnimation(animation); + viewBinding.markerDetailMarkerTextGradient.startAnimation(animation); + viewBinding.markerDetailMarkerInfo.startAnimation(animation); } }; @@ -119,22 +118,18 @@ public class MarkerDetailFragment extends Fragment { @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.marker_detail_fragment, container, false); + viewBinding = MarkerDetailFragmentBinding.inflate(inflater, container, false); - photoView = view.findViewById(R.id.marker_detail_marker_photo); - textGradient = view.findViewById(R.id.marker_detail_marker_text_gradient); - markerInfo = view.findViewById(R.id.marker_detail_marker_info); - - photoView.setOnClickListener(v -> { + viewBinding.markerDetailMarkerPhoto.setOnClickListener(v -> { handler.removeCallbacks(hideText); - int visibility = markerInfo.getVisibility() == View.GONE ? View.VISIBLE : View.GONE; - textGradient.setVisibility(visibility); - markerInfo.setVisibility(visibility); + int visibility = viewBinding.markerDetailMarkerInfo.getVisibility() == View.GONE ? View.VISIBLE : View.GONE; + viewBinding.markerDetailMarkerTextGradient.setVisibility(visibility); + viewBinding.markerDetailMarkerInfo.setVisibility(visibility); if (visibility == View.VISIBLE) { handler.postDelayed(hideText, HIDE_TEXT_DELAY); } }); - return view; + return viewBinding.getRoot(); } @Override @@ -153,6 +148,12 @@ public class MarkerDetailFragment extends Fragment { handler.removeCallbacks(hideText); } + @Override + public void onDestroyView() { + super.onDestroyView(); + viewBinding = null; + } + @Override public void setMenuVisibility(boolean menuVisible) { super.setMenuVisibility(menuVisible); @@ -223,10 +224,10 @@ public class MarkerDetailFragment extends Fragment { boolean hasPhoto = marker.hasPhoto(); if (hasPhoto) { handler.removeCallbacks(hideText); - photoView.setImageURI(marker.getPhotoURI()); + viewBinding.markerDetailMarkerPhoto.setImageURI(marker.getPhotoURI()); handler.postDelayed(hideText, HIDE_TEXT_DELAY); } else { - photoView.setImageResource(MarkerUtils.ICON_ID); + viewBinding.markerDetailMarkerPhoto.setImageResource(MarkerUtils.ICON_ID); } setName(hasPhoto); diff --git a/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordedFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordedFragment.java index 27f77676c..27c111c73 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordedFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordedFragment.java @@ -22,29 +22,28 @@ import android.util.Pair; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.constraintlayout.widget.Group; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.provider.ContentProviderUtils; +import de.dennisguse.opentracks.databinding.StatisticsRecordedBinding; import de.dennisguse.opentracks.stats.TrackStatistics; import de.dennisguse.opentracks.util.PreferencesUtils; import de.dennisguse.opentracks.util.StringUtils; import de.dennisguse.opentracks.util.TrackIconUtils; /** - * A fragment to display track statistics to the user. + * A fragment to display track statistics to the user for a recorded {@link Track}. * * @author Sandor Dornbush * @author Rodrigo Damazio */ +//TODO During updateUI(): do not call PreferenceUtils (it is slow) rather use sharedPreferenceChangeListener. public class StatisticsRecordedFragment extends Fragment { private static final String TRACK_ID_KEY = "trackId"; @@ -54,6 +53,8 @@ public class StatisticsRecordedFragment extends Fragment { private Track.Id trackId; private ContentProviderUtils contentProviderUtils; + private StatisticsRecordedBinding viewBinding; + private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = (preferences, key) -> { if (PreferencesUtils.isKey(getContext(), R.string.stats_units_key, key) || PreferencesUtils.isKey(getContext(), R.string.stats_rate_key, key)) { if (isResumed()) { @@ -68,29 +69,10 @@ public class StatisticsRecordedFragment extends Fragment { @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.statistics_recorded, container, false); + viewBinding = StatisticsRecordedBinding.inflate(inflater, container, false); + return viewBinding.getRoot(); } - private TextView totalTimeValueView; - private TextView distanceValue; - private TextView distanceUnit; - private View activityLabel; - private ImageView activitySpinner; - private TextView movingTimeValue; - private TextView speedAvgLabel; - private TextView speedAvgValue; - private TextView speedAvgUnit; - private TextView speedMaxLabel; - private TextView speedMaxValue; - private TextView speedMaxUnit; - private TextView speedMovingLabel; - private TextView speedMovingValue; - private TextView speedMovingUnit; - - private Group elevationGroup; - private TextView elevationTotalGainValue; - private TextView elevationTotalGainUnit; - public static StatisticsRecordedFragment newInstance(Track.Id trackId) { Bundle bundle = new Bundle(); bundle.putParcelable(TRACK_ID_KEY, trackId); @@ -108,37 +90,6 @@ public class StatisticsRecordedFragment extends Fragment { contentProviderUtils = new ContentProviderUtils(getContext()); } - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - totalTimeValueView = view.findViewById(R.id.stats_total_time_value); - - distanceValue = view.findViewById(R.id.stats_distance_value); - distanceUnit = view.findViewById(R.id.stats_distance_unit); - - activityLabel = view.findViewById(R.id.stats_activity_type_label); - activitySpinner = view.findViewById(R.id.stats_activity_type_icon); - - movingTimeValue = view.findViewById(R.id.stats_moving_time_value); - - speedAvgLabel = view.findViewById(R.id.stats_average_speed_label); - speedAvgValue = view.findViewById(R.id.stats_average_speed_value); - speedAvgUnit = view.findViewById(R.id.stats_average_speed_unit); - - speedMaxLabel = view.findViewById(R.id.stats_max_speed_label); - speedMaxValue = view.findViewById(R.id.stats_max_speed_value); - speedMaxUnit = view.findViewById(R.id.stats_max_speed_unit); - - speedMovingLabel = view.findViewById(R.id.stats_moving_speed_label); - speedMovingValue = view.findViewById(R.id.stats_moving_speed_value); - speedMovingUnit = view.findViewById(R.id.stats_moving_speed_unit); - - elevationGroup = view.findViewById(R.id.stats_elevation_group); - elevationTotalGainValue = view.findViewById(R.id.stats_elevation_gain_value); - elevationTotalGainUnit = view.findViewById(R.id.stats_elevation_gain_unit); - } - @Override public void onResume() { super.onResume(); @@ -150,34 +101,9 @@ public class StatisticsRecordedFragment extends Fragment { @Override public void onDestroyView() { super.onDestroyView(); + viewBinding = null; PreferencesUtils.unregister(getContext(), sharedPreferenceChangeListener); - - totalTimeValueView = null; - - distanceValue = null; - distanceUnit = null; - - activityLabel = null; - activitySpinner = null; - - movingTimeValue = null; - - speedAvgLabel = null; - speedAvgValue = null; - speedAvgUnit = null; - - speedMaxLabel = null; - speedMaxValue = null; - speedMaxUnit = null; - - speedMovingLabel = null; - speedMovingValue = null; - speedMovingUnit = null; - - elevationGroup = null; - elevationTotalGainValue = null; - elevationTotalGainUnit = null; } public void loadStatistics() { @@ -202,72 +128,66 @@ public class StatisticsRecordedFragment extends Fragment { double totalDistance = trackStatistics == null ? Double.NaN : trackStatistics.getTotalDistance(); Pair parts = StringUtils.getDistanceParts(getContext(), totalDistance, metricUnits); - distanceValue.setText(parts.first); - distanceUnit.setText(parts.second); + viewBinding.statsDistanceValue.setText(parts.first); + viewBinding.statsDistanceUnit.setText(parts.second); } // Set activity type { String trackIconValue = TrackIconUtils.getIconValue(getContext(), category); - - activityLabel.setVisibility(trackIconValue != null ? View.VISIBLE : View.GONE); - - activitySpinner.setVisibility(trackIconValue != null ? View.VISIBLE : View.GONE); - activitySpinner.setEnabled(false); - if (trackIconValue != null) { - activitySpinner.setImageDrawable(ContextCompat.getDrawable(getContext(), TrackIconUtils.getIconDrawable(trackIconValue))); - } + viewBinding.statsActivityTypeIcon.setEnabled(false); + viewBinding.statsActivityTypeIcon.setImageDrawable(ContextCompat.getDrawable(getContext(), TrackIconUtils.getIconDrawable(trackIconValue))); } // Set time and start datetime if (trackStatistics != null) { - movingTimeValue.setText(StringUtils.formatElapsedTime(trackStatistics.getMovingTime())); - totalTimeValueView.setText(StringUtils.formatElapsedTime(trackStatistics.getTotalTime())); + viewBinding.statsMovingTimeValue.setText(StringUtils.formatElapsedTime(trackStatistics.getMovingTime())); + viewBinding.statsTotalTimeValue.setText(StringUtils.formatElapsedTime(trackStatistics.getTotalTime())); } // Set average speed/pace { double speed = trackStatistics != null ? trackStatistics.getAverageSpeed() : Double.NaN; - speedAvgLabel.setText(reportSpeed ? R.string.stats_average_speed : R.string.stats_average_pace); + viewBinding.statsAverageSpeedLabel.setText(reportSpeed ? R.string.stats_average_speed : R.string.stats_average_pace); Pair parts = StringUtils.getSpeedParts(getContext(), speed, metricUnits, reportSpeed); - speedAvgValue.setText(parts.first); - speedAvgUnit.setText(parts.second); + viewBinding.statsAverageSpeedValue.setText(parts.first); + viewBinding.statsAverageSpeedUnit.setText(parts.second); } // Set max speed/pace { double speed = trackStatistics == null ? Double.NaN : trackStatistics.getMaxSpeed(); - speedMaxLabel.setText(reportSpeed ? R.string.stats_max_speed : R.string.stats_fastest_pace); + viewBinding.statsMaxSpeedLabel.setText(reportSpeed ? R.string.stats_max_speed : R.string.stats_fastest_pace); Pair parts = StringUtils.getSpeedParts(getContext(), speed, metricUnits, reportSpeed); - speedMaxValue.setText(parts.first); - speedMaxUnit.setText(parts.second); + viewBinding.statsMaxSpeedValue.setText(parts.first); + viewBinding.statsMaxSpeedUnit.setText(parts.second); } // Set moving speed/pace { double speed = trackStatistics != null ? trackStatistics.getAverageMovingSpeed() : Double.NaN; - speedMovingLabel.setText(reportSpeed ? R.string.stats_average_moving_speed : R.string.stats_average_moving_pace); + viewBinding.statsMovingSpeedLabel.setText(reportSpeed ? R.string.stats_average_moving_speed : R.string.stats_average_moving_pace); Pair parts = StringUtils.getSpeedParts(getContext(), speed, metricUnits, reportSpeed); - speedMovingValue.setText(parts.first); - speedMovingUnit.setText(parts.second); + viewBinding.statsMovingSpeedValue.setText(parts.first); + viewBinding.statsMovingSpeedUnit.setText(parts.second); } // Set elevation gain { // Make elevation visible? boolean showElevation = PreferencesUtils.isShowStatsElevation(getContext()); - elevationGroup.setVisibility(showElevation ? View.VISIBLE : View.GONE); + viewBinding.statsElevationGroup.setVisibility(showElevation ? View.VISIBLE : View.GONE); Float elevationGain_m = trackStatistics != null ? trackStatistics.getTotalElevationGain() : null; Pair parts = StringUtils.formatElevation(getContext(), elevationGain_m, metricUnits); - elevationTotalGainValue.setText(parts.first); - elevationTotalGainUnit.setText(parts.second); + viewBinding.statsElevationGainValue.setText(parts.first); + viewBinding.statsElevationGainUnit.setText(parts.second); } } } diff --git a/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordingFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordingFragment.java index 431161f1a..583fa69f1 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordingFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordingFragment.java @@ -11,11 +11,8 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.Spinner; -import android.widget.TextView; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.constraintlayout.widget.Group; import androidx.fragment.app.Fragment; import de.dennisguse.opentracks.R; @@ -28,6 +25,7 @@ import de.dennisguse.opentracks.content.data.TrackPoint; import de.dennisguse.opentracks.content.sensor.SensorDataCycling; import de.dennisguse.opentracks.content.sensor.SensorDataHeartRate; import de.dennisguse.opentracks.content.sensor.SensorDataSet; +import de.dennisguse.opentracks.databinding.StatisticsRecordingBinding; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.services.TrackRecordingServiceInterface; import de.dennisguse.opentracks.stats.TrackStatistics; @@ -38,11 +36,13 @@ import de.dennisguse.opentracks.util.TrackIconUtils; import de.dennisguse.opentracks.util.UnitConversions; /** - * A fragment to display track statistics to the user. + * A fragment to display track statistics to the user for a currently recording {@link Track}. * * @author Sandor Dornbush * @author Rodrigo Damazio */ +//TODO isRecording should not be relevant anymore as we now have StatisticRecordedFragment. +//TODO During updateUI(): do not call PreferenceUtils (it is slow) rather use sharedPreferenceChangeListener. public class StatisticsRecordingFragment extends Fragment implements TrackDataListener { private static final String TAG = StatisticsRecordingFragment.class.getSimpleName(); @@ -59,6 +59,8 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi private String category = ""; + private StatisticsRecordingBinding viewBinding; + public static Fragment newInstance() { return new StatisticsRecordingFragment(); } @@ -80,19 +82,10 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.statistics_recording, container, false); + viewBinding = StatisticsRecordingBinding.inflate(inflater, container, false); + return viewBinding.getRoot(); } - /* Views */ - private View sensorHorizontalLine; - private Group heartRateGroup; - private TextView heartRateValueView; - private TextView heartRateSensorView; - private Group cadenceGroup; - private TextView cadenceValueView; - private TextView cadenceSensorView; - - private TextView totalTimeValueView; private final Runnable updateUIeachSecond = new Runnable() { public void run() { if (isResumed() && isSelectedTrackRecording()) { @@ -105,84 +98,6 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi } } }; - private TextView distanceValue; - private TextView distanceUnit; - private View activityLabel; - private Spinner activitySpinner; - private TextView movingTimeValue; - private TextView speedAvgLabel; - private TextView speedAvgValue; - private TextView speedAvgUnit; - private TextView speedMaxLabel; - private TextView speedMaxValue; - private TextView speedMaxUnit; - private TextView speedMovingLabel; - private TextView speedMovingValue; - private TextView speedMovingUnit; - private TextView speedLabel; - private TextView speedValue; - private TextView speedUnit; - private Group elevationGroup; - private TextView elevationCurrentValue; - private TextView elevationCurrentUnit; - private TextView elevationTotalGainValue; - private TextView elevationTotalGainUnit; - private Group coordinateGroup; - private TextView latitudeValue; - private TextView longitudeValue; - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - sensorHorizontalLine = view.findViewById(R.id.stats_sensor_horizontal_line); - - heartRateGroup = view.findViewById(R.id.stats_sensor_heart_rate_group); - heartRateValueView = view.findViewById(R.id.stats_sensor_heart_rate_value); - heartRateSensorView = view.findViewById(R.id.stats_sensor_heart_rate_sensor_value); - - cadenceGroup = view.findViewById(R.id.stats_sensor_cadence_group); - cadenceValueView = view.findViewById(R.id.stats_sensor_cadence_value); - cadenceSensorView = view.findViewById(R.id.stats_sensor_cadence_sensor_value); - - totalTimeValueView = view.findViewById(R.id.stats_total_time_value); - - distanceValue = view.findViewById(R.id.stats_distance_value); - distanceUnit = view.findViewById(R.id.stats_distance_unit); - - activityLabel = view.findViewById(R.id.stats_activity_type_label); - activitySpinner = view.findViewById(R.id.stats_activity_type_icon); - - movingTimeValue = view.findViewById(R.id.stats_moving_time_value); - - speedAvgLabel = view.findViewById(R.id.stats_average_speed_label); - speedAvgValue = view.findViewById(R.id.stats_average_speed_value); - speedAvgUnit = view.findViewById(R.id.stats_average_speed_unit); - - speedMaxLabel = view.findViewById(R.id.stats_max_speed_label); - speedMaxValue = view.findViewById(R.id.stats_max_speed_value); - speedMaxUnit = view.findViewById(R.id.stats_max_speed_unit); - - speedMovingLabel = view.findViewById(R.id.stats_moving_speed_label); - speedMovingValue = view.findViewById(R.id.stats_moving_speed_value); - speedMovingUnit = view.findViewById(R.id.stats_moving_speed_unit); - - speedLabel = view.findViewById(R.id.stats_speed_label); - speedValue = view.findViewById(R.id.stats_speed_value); - speedUnit = view.findViewById(R.id.stats_speed_unit); - - elevationGroup = view.findViewById(R.id.stats_elevation_group); - elevationCurrentValue = view.findViewById(R.id.stats_elevation_current_value); - elevationCurrentUnit = view.findViewById(R.id.stats_elevation_current_unit); - - elevationTotalGainValue = view.findViewById(R.id.stats_elevation_gain_value); - elevationTotalGainUnit = view.findViewById(R.id.stats_elevation_gain_unit); - - coordinateGroup = view.findViewById(R.id.stats_coordinate_group); - - latitudeValue = view.findViewById(R.id.stats_latitude_value); - longitudeValue = view.findViewById(R.id.stats_longitude_value); - } @Override public void onActivityCreated(Bundle savedInstanceState) { @@ -234,52 +149,7 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi @Override public void onDestroyView() { super.onDestroyView(); - sensorHorizontalLine = null; - - heartRateGroup = null; - heartRateValueView = null; - heartRateSensorView = null; - cadenceGroup = null; - cadenceValueView = null; - cadenceSensorView = null; - - totalTimeValueView = null; - - distanceValue = null; - distanceUnit = null; - - activityLabel = null; - activitySpinner = null; - - movingTimeValue = null; - - speedAvgLabel = null; - speedAvgValue = null; - speedAvgUnit = null; - - speedMaxLabel = null; - speedMaxValue = null; - speedMaxUnit = null; - - speedMovingLabel = null; - speedMovingValue = null; - speedMovingUnit = null; - - speedLabel = null; - speedValue = null; - speedUnit = null; - - elevationGroup = null; - elevationCurrentValue = null; - elevationCurrentUnit = null; - - elevationTotalGainValue = null; - elevationTotalGainUnit = null; - - coordinateGroup = null; - - latitudeValue = null; - longitudeValue = null; + viewBinding = null; } @Override @@ -419,7 +289,7 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi private void setHeartRateSensorData(SensorDataSet sensorDataSet) { int isVisible = sensorDataSet != null ? View.VISIBLE : View.GONE; - heartRateGroup.setVisibility(isVisible); + viewBinding.statsSensorHeartRateGroup.setVisibility(isVisible); setVisibilitySensorHorizontalLine(); String sensorValue = getContext().getString(R.string.value_unknown); @@ -433,13 +303,13 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi } } - heartRateSensorView.setText(sensorName); - heartRateValueView.setText(sensorValue); + viewBinding.statsSensorHeartRateSensorValue.setText(sensorName); + viewBinding.statsSensorHeartRateValue.setText(sensorValue); } private void setCadenceSensorData(SensorDataSet sensorDataSet) { int isVisible = sensorDataSet != null ? View.VISIBLE : View.GONE; - cadenceGroup.setVisibility(isVisible); + viewBinding.statsSensorCadenceGroup.setVisibility(isVisible); setVisibilitySensorHorizontalLine(); String sensorValue = getContext().getString(R.string.value_unknown); @@ -453,8 +323,8 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi } } - cadenceSensorView.setText(sensorName); - cadenceValueView.setText(sensorValue); + viewBinding.statsSensorCadenceSensorValue.setText(sensorName); + viewBinding.statsSensorCadenceValue.setText(sensorValue); } // Set elevation gain @@ -473,16 +343,16 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi } Pair parts = StringUtils.formatElevation(getContext(), totalElevationGain, metricUnits); - elevationTotalGainValue.setText(parts.first); - elevationTotalGainUnit.setText(parts.second); + viewBinding.statsElevationGainValue.setText(parts.first); + viewBinding.statsElevationGainUnit.setText(parts.second); } /** * If cadence and hear rate groups are invisible then sensor horizontal line hast to be invisible too. */ private void setVisibilitySensorHorizontalLine() { - if (cadenceGroup.getVisibility() != View.VISIBLE && heartRateGroup.getVisibility() != View.VISIBLE) { - sensorHorizontalLine.setVisibility(View.GONE); + if (viewBinding.statsSensorCadenceGroup.getVisibility() != View.VISIBLE && viewBinding.statsSensorHeartRateGroup.getVisibility() != View.VISIBLE) { + viewBinding.statsSensorHorizontalLine.setVisibility(View.GONE); } } @@ -510,59 +380,59 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi double totalDistance = lastTrackStatistics == null ? Double.NaN : lastTrackStatistics.getTotalDistance(); Pair parts = StringUtils.getDistanceParts(getContext(), totalDistance, metricUnits); - distanceValue.setText(parts.first); - distanceUnit.setText(parts.second); + viewBinding.statsDistanceValue.setText(parts.first); + viewBinding.statsDistanceUnit.setText(parts.second); } // Set activity type { - activitySpinner.setEnabled(isRecording); - TrackIconUtils.setIconSpinner(activitySpinner, trackIconValue); + viewBinding.statsActivityTypeIcon.setEnabled(isRecording); + TrackIconUtils.setIconSpinner(viewBinding.statsActivityTypeIcon, trackIconValue); } // Set time if (lastTrackStatistics != null) { - movingTimeValue.setText(StringUtils.formatElapsedTime(lastTrackStatistics.getMovingTime())); + viewBinding.statsMovingTimeValue.setText(StringUtils.formatElapsedTime(lastTrackStatistics.getMovingTime())); updateTotalTime(); } // Set average speed/pace { double speed = lastTrackStatistics != null ? lastTrackStatistics.getAverageSpeed() : Double.NaN; - speedAvgLabel.setText(reportSpeed ? R.string.stats_average_speed : R.string.stats_average_pace); + viewBinding.statsAverageSpeedLabel.setText(reportSpeed ? R.string.stats_average_speed : R.string.stats_average_pace); Pair parts = StringUtils.getSpeedParts(getContext(), speed, metricUnits, reportSpeed); - speedAvgValue.setText(parts.first); - speedAvgUnit.setText(parts.second); + viewBinding.statsAverageSpeedValue.setText(parts.first); + viewBinding.statsAverageSpeedUnit.setText(parts.second); } // Set max speed/pace { double speed = lastTrackStatistics == null ? Double.NaN : lastTrackStatistics.getMaxSpeed(); - speedMaxLabel.setText(reportSpeed ? R.string.stats_max_speed : R.string.stats_fastest_pace); + viewBinding.statsMaxSpeedLabel.setText(reportSpeed ? R.string.stats_max_speed : R.string.stats_fastest_pace); Pair parts = StringUtils.getSpeedParts(getContext(), speed, metricUnits, reportSpeed); - speedMaxValue.setText(parts.first); - speedMaxUnit.setText(parts.second); + viewBinding.statsMaxSpeedValue.setText(parts.first); + viewBinding.statsMaxSpeedUnit.setText(parts.second); } // Set moving speed/pace { double speed = lastTrackStatistics != null ? lastTrackStatistics.getAverageMovingSpeed() : Double.NaN; - speedMovingLabel.setText(reportSpeed ? R.string.stats_average_moving_speed : R.string.stats_average_moving_pace); + viewBinding.statsMovingSpeedLabel.setText(reportSpeed ? R.string.stats_average_moving_speed : R.string.stats_average_moving_pace); Pair parts = StringUtils.getSpeedParts(getContext(), speed, metricUnits, reportSpeed); - speedMovingValue.setText(parts.first); - speedMovingUnit.setText(parts.second); + viewBinding.statsMovingSpeedValue.setText(parts.first); + viewBinding.statsMovingSpeedUnit.setText(parts.second); } // Set elevation (gain) { // Make elevation visible? boolean showElevation = PreferencesUtils.isShowStatsElevation(getContext()); - elevationGroup.setVisibility(showElevation ? View.VISIBLE : View.GONE); + viewBinding.statsElevationGroup.setVisibility(showElevation ? View.VISIBLE : View.GONE); } } @@ -573,7 +443,7 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi } else { totalTime = lastTrackStatistics.getTotalTime(); } - totalTimeValueView.setText(StringUtils.formatElapsedTime(totalTime)); + viewBinding.statsTotalTimeValue.setText(StringUtils.formatElapsedTime(totalTime)); } /** @@ -598,28 +468,28 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi // Set elevation boolean showElevation = PreferencesUtils.isShowStatsElevation(getContext()); - elevationGroup.setVisibility(showElevation ? View.VISIBLE : View.GONE); + viewBinding.statsElevationGroup.setVisibility(showElevation ? View.VISIBLE : View.GONE); if (showElevation) { // Current elevation Float altitude = lastTrackPoint != null && lastTrackPoint.hasAltitude() ? (float) lastTrackPoint.getAltitude() : null; Pair parts = StringUtils.formatElevation(getContext(), altitude, metricUnits); - elevationCurrentValue.setText(parts.first); - elevationCurrentUnit.setText(parts.second); + viewBinding.statsElevationCurrentValue.setText(parts.first); + viewBinding.statsElevationCurrentUnit.setText(parts.second); } // Set coordinate boolean showCoordinate = PreferencesUtils.isStatsShowCoordinate(getContext()); - coordinateGroup.setVisibility(showCoordinate ? View.VISIBLE : View.GONE); + viewBinding.statsCoordinateGroup.setVisibility(showCoordinate ? View.VISIBLE : View.GONE); if (showCoordinate) { double latitude = lastTrackPoint != null ? lastTrackPoint.getLatitude() : Double.NaN; String latitudeText = Double.isNaN(latitude) || Double.isInfinite(latitude) ? getContext().getString(R.string.value_unknown) : StringUtils.formatCoordinate(latitude); - latitudeValue.setText(latitudeText); + viewBinding.statsLatitudeValue.setText(latitudeText); double longitude = lastTrackPoint != null ? lastTrackPoint.getLongitude() : Double.NaN; String longitudeText = Double.isNaN(longitude) || Double.isInfinite(longitude) ? getContext().getString(R.string.value_unknown) : StringUtils.formatCoordinate(longitude); - longitudeValue.setText(longitudeText); + viewBinding.statsLongitudeValue.setText(longitudeText); } } @@ -627,10 +497,10 @@ public class StatisticsRecordingFragment extends Fragment implements TrackDataLi boolean metricUnits = PreferencesUtils.isMetricUnits(getContext()); boolean reportSpeed = PreferencesUtils.isReportSpeed(getContext(), category); - speedLabel.setText(reportSpeed ? R.string.stats_speed : R.string.stats_pace); + viewBinding.statsSpeedLabel.setText(reportSpeed ? R.string.stats_speed : R.string.stats_pace); Pair parts = StringUtils.getSpeedParts(getContext(), speed, metricUnits, reportSpeed); - speedValue.setText(parts.first); - speedUnit.setText(parts.second); + viewBinding.statsSpeedValue.setText(parts.first); + viewBinding.statsSpeedLabel.setText(parts.second); } }