forked from upstream-mirrors/OpenTracks
TrackController is now ControllerFragment.
This commit is contained in:
@@ -39,13 +39,13 @@ public class EspressoUITest {
|
|||||||
public void record_pause_resume_stop() {
|
public void record_pause_resume_stop() {
|
||||||
{
|
{
|
||||||
// TrackListActivity: start recording
|
// TrackListActivity: start recording
|
||||||
ViewInteraction trackControllerRecordButton = onView(withId(R.id.track_controller_record));
|
ViewInteraction trackControllerRecordButton = onView(withId(R.id.controller_record));
|
||||||
trackControllerRecordButton.perform(click());
|
trackControllerRecordButton.perform(click());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// TrackRecordingActivity
|
// TrackRecordingActivity
|
||||||
ViewInteraction trackControllerRecordButton = onView(withId(R.id.track_controller_record));
|
ViewInteraction trackControllerRecordButton = onView(withId(R.id.controller_record));
|
||||||
ViewInteraction trackControllerStopButton = onView(withId(R.id.track_controller_stop));
|
ViewInteraction trackControllerStopButton = onView(withId(R.id.controller_stop));
|
||||||
|
|
||||||
// wait; stay recording
|
// wait; stay recording
|
||||||
trackControllerRecordButton.perform(waitFor(5000));
|
trackControllerRecordButton.perform(waitFor(5000));
|
||||||
@@ -72,13 +72,13 @@ public class EspressoUITest {
|
|||||||
public void record_move_through_tabs() {
|
public void record_move_through_tabs() {
|
||||||
{
|
{
|
||||||
// TrackListActivity: start recording
|
// TrackListActivity: start recording
|
||||||
ViewInteraction trackControllerRecordButton = onView(withId(R.id.track_controller_record));
|
ViewInteraction trackControllerRecordButton = onView(withId(R.id.controller_record));
|
||||||
trackControllerRecordButton.perform(click());
|
trackControllerRecordButton.perform(click());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// TrackRecordingActivity
|
// TrackRecordingActivity
|
||||||
ViewInteraction tabLayout = onView(withId(R.id.track_detail_activity_tablayout));
|
ViewInteraction tabLayout = onView(withId(R.id.track_detail_activity_tablayout));
|
||||||
ViewInteraction trackControllerStopButton = onView(withId(R.id.track_controller_stop));
|
ViewInteraction trackControllerStopButton = onView(withId(R.id.controller_stop));
|
||||||
|
|
||||||
tabLayout.perform(selectTabAtIndex(1));
|
tabLayout.perform(selectTabAtIndex(1));
|
||||||
tabLayout.perform(waitFor(1000));
|
tabLayout.perform(waitFor(1000));
|
||||||
|
|||||||
@@ -0,0 +1,299 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.dennisguse.opentracks;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.graphics.drawable.TransitionDrawable;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.accessibility.AccessibilityEvent;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.databinding.ControllerFragmentBinding;
|
||||||
|
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||||
|
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
||||||
|
import de.dennisguse.opentracks.util.ActivityUtils;
|
||||||
|
import de.dennisguse.opentracks.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Track controller for record, pause, resume, and stop.
|
||||||
|
*
|
||||||
|
* @author Jimmy Shih
|
||||||
|
*/
|
||||||
|
//TODO Move buttons into separate components
|
||||||
|
public class ControllerFragment extends Fragment implements View.OnTouchListener {
|
||||||
|
|
||||||
|
private static final String TAG = ControllerFragment.class.getSimpleName();
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
//TODO TrackRecordingService should provide LifeData for time (replace internal timer)
|
||||||
|
private static final Duration UI_UPDATE_INTERVAL = Duration.ofSeconds(1);
|
||||||
|
@Deprecated
|
||||||
|
private Handler handlerUpdateTotalTime;
|
||||||
|
|
||||||
|
private Runnable buttonDelay;
|
||||||
|
private int buttonDelayDuration;
|
||||||
|
|
||||||
|
private ControllerFragmentBinding viewBinding;
|
||||||
|
private TransitionDrawable transition;
|
||||||
|
|
||||||
|
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
||||||
|
private TrackRecordingService.RecordingStatus recordingStatus;
|
||||||
|
private Duration totalTime;
|
||||||
|
|
||||||
|
private final Runnable bindChangedCallback = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
TrackRecordingService service = trackRecordingServiceConnection.getServiceIfBound();
|
||||||
|
if (service == null) {
|
||||||
|
Log.w(TAG, "could not get TrackRecordingService");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
service.getRecordingStatusObservable()
|
||||||
|
.observe(ControllerFragment.this, status -> onRecordingStatusChanged(status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// A runnable to update the total time.
|
||||||
|
@Deprecated
|
||||||
|
private final Runnable updateTotalTimeRunnable = new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
if (isResumed() && recordingStatus.isRecordingAndNotPaused()) {
|
||||||
|
updateTotalTime();
|
||||||
|
setTotalTime();
|
||||||
|
handlerUpdateTotalTime.postDelayed(this, UI_UPDATE_INTERVAL.toMillis());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
buttonDelayDuration = getResources().getInteger(R.integer.buttonDelayMillis);
|
||||||
|
|
||||||
|
trackRecordingServiceConnection = new TrackRecordingServiceConnection(bindChangedCallback);
|
||||||
|
handlerUpdateTotalTime = new Handler();
|
||||||
|
recordingStatus = TrackRecordingService.STATUS_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
|
viewBinding = ControllerFragmentBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
|
viewBinding.controllerRecord.setOnTouchListener(this);
|
||||||
|
viewBinding.controllerRecord.setOnClickListener((view) -> {
|
||||||
|
if (buttonDelay != null || recordingStatus.isRecordingAndNotPaused()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getCallback().recordStart();
|
||||||
|
});
|
||||||
|
|
||||||
|
viewBinding.controllerStop.setOnTouchListener(this);
|
||||||
|
transition = (TransitionDrawable) viewBinding.controllerContainer.getBackground();
|
||||||
|
|
||||||
|
onRecordingStatusChanged(recordingStatus);
|
||||||
|
|
||||||
|
return viewBinding.getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
trackRecordingServiceConnection.startConnection(getContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStop() {
|
||||||
|
super.onStop();
|
||||||
|
trackRecordingServiceConnection.unbind(getContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
viewBinding = null;
|
||||||
|
transition = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
trackRecordingServiceConnection = null;
|
||||||
|
handlerUpdateTotalTime = null;
|
||||||
|
recordingStatus = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO Move into a separate object
|
||||||
|
@SuppressLint("ClickableViewAccessibility") //We do accessibility manually.
|
||||||
|
@Override
|
||||||
|
public boolean onTouch(final View view, MotionEvent event) {
|
||||||
|
if (!isResumed()) {
|
||||||
|
Log.w(TAG, "The UI is already gone, no need to update anything; seen on Android 7.1.2");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buttonDelay != null && event.getAction() == MotionEvent.ACTION_UP) {
|
||||||
|
handlerUpdateTotalTime.removeCallbacks(buttonDelay);
|
||||||
|
buttonDelay = null;
|
||||||
|
view.setPressed(false);
|
||||||
|
|
||||||
|
transition.resetTransition();
|
||||||
|
|
||||||
|
showStatusSetDefaultText();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Trigger button pressed animation
|
||||||
|
view.setPressed(true);
|
||||||
|
|
||||||
|
//To pause a recording
|
||||||
|
if (viewBinding.controllerRecord.equals(view)
|
||||||
|
&& event.getAction() == MotionEvent.ACTION_DOWN
|
||||||
|
&& recordingStatus.isRecordingAndNotPaused()) {
|
||||||
|
|
||||||
|
transition.startTransition(buttonDelayDuration);
|
||||||
|
|
||||||
|
ActivityUtils.vibrate(getContext(), 150);
|
||||||
|
viewBinding.controllerStatus.setText(R.string.hold_to_pause);
|
||||||
|
|
||||||
|
buttonDelay = () -> {
|
||||||
|
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
|
||||||
|
view.performClick();
|
||||||
|
getCallback().recordPause();
|
||||||
|
|
||||||
|
transition.resetTransition();
|
||||||
|
|
||||||
|
ActivityUtils.vibrate(getContext(), 1000);
|
||||||
|
};
|
||||||
|
handlerUpdateTotalTime.postDelayed(buttonDelay, buttonDelayDuration);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//To stop a recording
|
||||||
|
if (viewBinding.controllerStop.equals(view)
|
||||||
|
&& event.getAction() == MotionEvent.ACTION_DOWN
|
||||||
|
&& recordingStatus.isRecording()) {
|
||||||
|
|
||||||
|
|
||||||
|
transition.startTransition(buttonDelayDuration);
|
||||||
|
|
||||||
|
ActivityUtils.vibrate(getContext(), 150);
|
||||||
|
viewBinding.controllerStatus.setText(R.string.hold_to_stop);
|
||||||
|
|
||||||
|
buttonDelay = () -> {
|
||||||
|
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
|
||||||
|
getCallback().recordStop();
|
||||||
|
ActivityUtils.vibrate(getContext(), 1000);
|
||||||
|
|
||||||
|
transition.resetTransition();
|
||||||
|
};
|
||||||
|
handlerUpdateTotalTime.postDelayed(buttonDelay, buttonDelayDuration);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hide() {
|
||||||
|
viewBinding.controllerContainer.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show() {
|
||||||
|
viewBinding.controllerContainer.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTotalTime() {
|
||||||
|
TrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
|
||||||
|
if (trackRecordingService != null) {
|
||||||
|
totalTime = trackRecordingService.getTotalTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTotalTime() {
|
||||||
|
if (totalTime != null) {
|
||||||
|
viewBinding.controllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(totalTime));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showStatusSetDefaultText() {
|
||||||
|
viewBinding.controllerStatus.setText(recordingStatus.isPaused() ? R.string.generic_paused : R.string.generic_recording);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Callback getCallback() {
|
||||||
|
return (Callback) getActivity();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Callback {
|
||||||
|
void recordStart();
|
||||||
|
|
||||||
|
void recordPause();
|
||||||
|
|
||||||
|
void recordStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) {
|
||||||
|
recordingStatus = status;
|
||||||
|
|
||||||
|
if (!recordingStatus.isRecording()) {
|
||||||
|
handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable);
|
||||||
|
}
|
||||||
|
if (recordingStatus.isRecordingAndNotPaused()) {
|
||||||
|
handlerUpdateTotalTime.postDelayed(updateTotalTimeRunnable, UI_UPDATE_INTERVAL.toMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
viewBinding.controllerRecord.setImageResource(recordingStatus.isRecordingAndNotPaused() ? R.drawable.ic_button_pause : R.drawable.button_record);
|
||||||
|
viewBinding.controllerRecord.setContentDescription(getContext().getString(recordingStatus.isRecordingAndNotPaused() ? R.string.image_pause : R.string.image_record));
|
||||||
|
|
||||||
|
viewBinding.controllerStop.setEnabled(recordingStatus.isRecording());
|
||||||
|
|
||||||
|
viewBinding.controllerStatus.setVisibility(recordingStatus.isRecording() ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
if (recordingStatus.isRecording()) {
|
||||||
|
viewBinding.controllerStatus.setTextColor(getContext().getResources().getColor(recordingStatus.isPaused() ? android.R.color.white : R.color.recording_text));
|
||||||
|
showStatusSetDefaultText();
|
||||||
|
}
|
||||||
|
|
||||||
|
viewBinding.controllerTotalTime.setVisibility(recordingStatus.isRecording() ? View.VISIBLE : View.INVISIBLE);
|
||||||
|
|
||||||
|
if (recordingStatus.isRecording()) {
|
||||||
|
updateTotalTime();
|
||||||
|
setTotalTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -175,7 +175,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker
|
|||||||
insertMarkerMenuItem = menu.findItem(R.id.marker_list_insert_marker);
|
insertMarkerMenuItem = menu.findItem(R.id.marker_list_insert_marker);
|
||||||
|
|
||||||
searchMenuItem = menu.findItem(R.id.marker_list_search);
|
searchMenuItem = menu.findItem(R.id.marker_list_search);
|
||||||
ActivityUtils.configureSearchWidget(this, searchMenuItem, null);
|
ActivityUtils.configureSearchWidget(this, searchMenuItem);
|
||||||
|
|
||||||
return super.onCreateOptionsMenu(menu);
|
return super.onCreateOptionsMenu(menu);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,260 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.dennisguse.opentracks;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.graphics.drawable.TransitionDrawable;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.accessibility.AccessibilityEvent;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
|
|
||||||
import de.dennisguse.opentracks.databinding.TrackControllerBinding;
|
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
|
||||||
import de.dennisguse.opentracks.services.TrackRecordingServiceConnection;
|
|
||||||
import de.dennisguse.opentracks.util.ActivityUtils;
|
|
||||||
import de.dennisguse.opentracks.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Track controller for record, pause, resume, and stop.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
//TODO Subscribe to TrackRecordingService.recordingStatus
|
|
||||||
//TODO Could be a fragment
|
|
||||||
public class TrackController implements View.OnTouchListener {
|
|
||||||
|
|
||||||
private static final String TAG = TrackController.class.getSimpleName();
|
|
||||||
|
|
||||||
private static final Duration UI_UPDATE_INTERVAL = Duration.ofSeconds(1);
|
|
||||||
|
|
||||||
private final Activity activity;
|
|
||||||
private final TrackRecordingServiceConnection trackRecordingServiceConnection;
|
|
||||||
private final Handler handlerUpdateTotalTime = new Handler();
|
|
||||||
private final boolean alwaysShow;
|
|
||||||
|
|
||||||
private Runnable buttonDelay;
|
|
||||||
private final int buttonDelayDuration;
|
|
||||||
|
|
||||||
private final TrackControllerBinding viewBinding;
|
|
||||||
private final TransitionDrawable transition;
|
|
||||||
|
|
||||||
|
|
||||||
private TrackRecordingService.RecordingStatus recordingStatus;
|
|
||||||
private Duration totalTime;
|
|
||||||
|
|
||||||
private final Callback callback;
|
|
||||||
|
|
||||||
// A runnable to update the total time.
|
|
||||||
private final Runnable updateTotalTimeRunnable = new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
if (isResumed() && recordingStatus.isRecordingAndNotPaused()) {
|
|
||||||
updateTotalTime();
|
|
||||||
setTotalTime();
|
|
||||||
handlerUpdateTotalTime.postDelayed(this, UI_UPDATE_INTERVAL.toMillis());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
|
||||||
TrackController(Activity activity, TrackControllerBinding viewBinding, TrackRecordingServiceConnection trackRecordingServiceConnection, boolean alwaysShow, Callback callback) {
|
|
||||||
this.activity = activity;
|
|
||||||
this.viewBinding = viewBinding;
|
|
||||||
this.trackRecordingServiceConnection = trackRecordingServiceConnection;
|
|
||||||
this.alwaysShow = alwaysShow;
|
|
||||||
this.callback = callback;
|
|
||||||
|
|
||||||
buttonDelayDuration = activity.getResources().getInteger(R.integer.buttonDelayMillis);
|
|
||||||
|
|
||||||
viewBinding.trackControllerRecord.setOnTouchListener(this);
|
|
||||||
viewBinding.trackControllerRecord.setOnClickListener((view) -> {
|
|
||||||
if (buttonDelay != null || recordingStatus.isRecordingAndNotPaused()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
callback.recordStart();
|
|
||||||
});
|
|
||||||
|
|
||||||
viewBinding.trackControllerStop.setOnTouchListener(this);
|
|
||||||
transition = (TransitionDrawable) viewBinding.trackControllerContainer.getBackground();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility") //We do accessibility manually.
|
|
||||||
@Override
|
|
||||||
public boolean onTouch(final View view, MotionEvent event) {
|
|
||||||
if (!isResumed()) {
|
|
||||||
Log.w(TAG, "The UI is already gone, no need to update anything; seen on Android 7.1.2");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (event.getAction() == MotionEvent.ACTION_MOVE) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buttonDelay != null && event.getAction() == MotionEvent.ACTION_UP) {
|
|
||||||
handlerUpdateTotalTime.removeCallbacks(buttonDelay);
|
|
||||||
buttonDelay = null;
|
|
||||||
view.setPressed(false);
|
|
||||||
|
|
||||||
transition.resetTransition();
|
|
||||||
|
|
||||||
showStatusSetDefaultText();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Trigger button pressed animation
|
|
||||||
view.setPressed(true);
|
|
||||||
|
|
||||||
//To pause a recording
|
|
||||||
if (viewBinding.trackControllerRecord.equals(view)
|
|
||||||
&& event.getAction() == MotionEvent.ACTION_DOWN
|
|
||||||
&& recordingStatus.isRecordingAndNotPaused()) {
|
|
||||||
|
|
||||||
transition.startTransition(buttonDelayDuration);
|
|
||||||
|
|
||||||
ActivityUtils.vibrate(activity, 150);
|
|
||||||
viewBinding.trackControllerStatus.setText(R.string.hold_to_pause);
|
|
||||||
|
|
||||||
buttonDelay = () -> {
|
|
||||||
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
|
|
||||||
view.performClick();
|
|
||||||
callback.recordPause();
|
|
||||||
|
|
||||||
transition.resetTransition();
|
|
||||||
|
|
||||||
ActivityUtils.vibrate(activity, 1000);
|
|
||||||
};
|
|
||||||
handlerUpdateTotalTime.postDelayed(buttonDelay, buttonDelayDuration);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//To stop a recording
|
|
||||||
if (viewBinding.trackControllerStop.equals(view)
|
|
||||||
&& event.getAction() == MotionEvent.ACTION_DOWN
|
|
||||||
&& recordingStatus.isRecording()) {
|
|
||||||
|
|
||||||
|
|
||||||
transition.startTransition(buttonDelayDuration);
|
|
||||||
|
|
||||||
ActivityUtils.vibrate(activity, 150);
|
|
||||||
viewBinding.trackControllerStatus.setText(R.string.hold_to_stop);
|
|
||||||
|
|
||||||
buttonDelay = () -> {
|
|
||||||
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
|
|
||||||
callback.recordStop();
|
|
||||||
ActivityUtils.vibrate(activity, 1000);
|
|
||||||
|
|
||||||
transition.resetTransition();
|
|
||||||
};
|
|
||||||
handlerUpdateTotalTime.postDelayed(buttonDelay, buttonDelayDuration);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void update(TrackRecordingService.RecordingStatus recordingStatus) {
|
|
||||||
if (!isResumed()) {
|
|
||||||
handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.recordingStatus = recordingStatus;
|
|
||||||
boolean isRecording = recordingStatus.isRecording();
|
|
||||||
boolean isRecordingPaused = recordingStatus.isPaused();
|
|
||||||
boolean visible = alwaysShow || isRecording;
|
|
||||||
viewBinding.trackControllerContainer.setVisibility(visible ? View.VISIBLE : View.GONE);
|
|
||||||
|
|
||||||
if (!visible) {
|
|
||||||
handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isRecording && !isRecordingPaused) {
|
|
||||||
handlerUpdateTotalTime.postDelayed(updateTotalTimeRunnable, UI_UPDATE_INTERVAL.toMillis());
|
|
||||||
}
|
|
||||||
|
|
||||||
viewBinding.trackControllerRecord.setImageResource(isRecording && !isRecordingPaused ? R.drawable.ic_button_pause : R.drawable.button_record);
|
|
||||||
viewBinding.trackControllerRecord.setContentDescription(activity.getString(isRecording && !isRecordingPaused ? R.string.image_pause : R.string.image_record));
|
|
||||||
|
|
||||||
viewBinding.trackControllerStop.setEnabled(isRecording);
|
|
||||||
|
|
||||||
viewBinding.trackControllerStatus.setVisibility(isRecording ? View.VISIBLE : View.INVISIBLE);
|
|
||||||
if (isRecording) {
|
|
||||||
viewBinding.trackControllerStatus.setTextColor(activity.getResources().getColor(isRecordingPaused ? android.R.color.white : R.color.recording_text));
|
|
||||||
showStatusSetDefaultText();
|
|
||||||
}
|
|
||||||
|
|
||||||
viewBinding.trackControllerTotalTime.setVisibility(isRecording ? View.VISIBLE : View.INVISIBLE);
|
|
||||||
|
|
||||||
if (recordingStatus.isRecording()) {
|
|
||||||
updateTotalTime();
|
|
||||||
setTotalTime();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void onResume(TrackRecordingService.RecordingStatus recordingStatus) {
|
|
||||||
this.recordingStatus = recordingStatus;
|
|
||||||
update(recordingStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
void onPause() {
|
|
||||||
recordingStatus = null;
|
|
||||||
handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void hide() {
|
|
||||||
viewBinding.trackControllerContainer.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void show() {
|
|
||||||
viewBinding.trackControllerContainer.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateTotalTime() {
|
|
||||||
TrackRecordingService trackRecordingService = trackRecordingServiceConnection.getServiceIfBound();
|
|
||||||
if (trackRecordingService != null) {
|
|
||||||
totalTime = trackRecordingService.getTotalTime();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setTotalTime() {
|
|
||||||
if (totalTime != null) {
|
|
||||||
viewBinding.trackControllerTotalTime.setText(StringUtils.formatElapsedTimeWithHour(totalTime));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showStatusSetDefaultText() {
|
|
||||||
viewBinding.trackControllerStatus.setText(recordingStatus.isPaused() ? R.string.generic_paused : R.string.generic_recording);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isResumed() {
|
|
||||||
return recordingStatus != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface Callback {
|
|
||||||
void recordStart();
|
|
||||||
|
|
||||||
void recordPause();
|
|
||||||
|
|
||||||
void recordStop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -71,14 +71,13 @@ import de.dennisguse.opentracks.util.TrackIconUtils;
|
|||||||
*
|
*
|
||||||
* @author Leif Hendrik Wilden
|
* @author Leif Hendrik Wilden
|
||||||
*/
|
*/
|
||||||
public class TrackListActivity extends AbstractListActivity implements ConfirmDeleteDialogFragment.ConfirmDeleteCaller, TrackController.Callback {
|
public class TrackListActivity extends AbstractListActivity implements ConfirmDeleteDialogFragment.ConfirmDeleteCaller, ControllerFragment.Callback {
|
||||||
|
|
||||||
private static final String TAG = TrackListActivity.class.getSimpleName();
|
private static final String TAG = TrackListActivity.class.getSimpleName();
|
||||||
|
|
||||||
// The following are set in onCreate
|
// The following are set in onCreate
|
||||||
private SharedPreferences sharedPreferences;
|
private SharedPreferences sharedPreferences;
|
||||||
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
||||||
private TrackController trackController;
|
|
||||||
private ResourceCursorAdapter resourceCursorAdapter;
|
private ResourceCursorAdapter resourceCursorAdapter;
|
||||||
|
|
||||||
private TrackListBinding viewBinding;
|
private TrackListBinding viewBinding;
|
||||||
@@ -118,7 +117,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
TrackListActivity.this.invalidateOptionsMenu();
|
TrackListActivity.this.invalidateOptionsMenu();
|
||||||
loaderCallbacks.restart();
|
loaderCallbacks.restart();
|
||||||
trackController.onResume(recordingStatus);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,9 +130,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
private final Runnable bindChangedCallback = new Runnable() {
|
private final Runnable bindChangedCallback = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// After binding changes (e.g., becomes available), update the total time in trackController.
|
|
||||||
runOnUiThread(() -> trackController.update(recordingStatus));
|
|
||||||
|
|
||||||
TrackRecordingService service = trackRecordingServiceConnection.getServiceIfBound();
|
TrackRecordingService service = trackRecordingServiceConnection.getServiceIfBound();
|
||||||
if (service == null) {
|
if (service == null) {
|
||||||
Log.e(TAG, "service not available to start gps or a new recording");
|
Log.e(TAG, "service not available to start gps or a new recording");
|
||||||
@@ -170,14 +165,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
|
sharedPreferences = PreferencesUtils.getSharedPreferences(this);
|
||||||
|
|
||||||
trackRecordingServiceConnection = new TrackRecordingServiceConnection(bindChangedCallback);
|
trackRecordingServiceConnection = new TrackRecordingServiceConnection(bindChangedCallback);
|
||||||
trackController = new TrackController(this, viewBinding.trackControllerContainer, trackRecordingServiceConnection, true, this);
|
|
||||||
|
|
||||||
|
|
||||||
// Show trackController when search dialog is dismissed
|
|
||||||
SearchManager searchManager = (SearchManager) getSystemService(SEARCH_SERVICE);
|
|
||||||
if (searchManager != null) {
|
|
||||||
searchManager.setOnDismissListener(() -> trackController.show());
|
|
||||||
}
|
|
||||||
|
|
||||||
viewBinding.trackList.setEmptyView(viewBinding.trackListEmptyView);
|
viewBinding.trackList.setEmptyView(viewBinding.trackListEmptyView);
|
||||||
viewBinding.trackList.setOnItemClickListener((parent, view, position, trackId) -> {
|
viewBinding.trackList.setOnItemClickListener((parent, view, position, trackId) -> {
|
||||||
@@ -250,14 +237,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
trackRecordingServiceConnection.startConnection(this);
|
trackRecordingServiceConnection.startConnection(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
|
|
||||||
// Update UI
|
|
||||||
trackController.onPause();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
@@ -265,7 +244,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
// Update UI
|
// Update UI
|
||||||
this.invalidateOptionsMenu();
|
this.invalidateOptionsMenu();
|
||||||
LoaderManager.getInstance(this).restartLoader(0, null, loaderCallbacks);
|
LoaderManager.getInstance(this).restartLoader(0, null, loaderCallbacks);
|
||||||
trackController.onResume(recordingStatus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -298,7 +276,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
getMenuInflater().inflate(R.menu.track_list, menu);
|
getMenuInflater().inflate(R.menu.track_list, menu);
|
||||||
|
|
||||||
searchMenuItem = menu.findItem(R.id.track_list_search);
|
searchMenuItem = menu.findItem(R.id.track_list_search);
|
||||||
ActivityUtils.configureSearchWidget(this, searchMenuItem, trackController);
|
ActivityUtils.configureSearchWidget(this, searchMenuItem);
|
||||||
startGpsMenuItem = menu.findItem(R.id.track_list_start_gps);
|
startGpsMenuItem = menu.findItem(R.id.track_list_start_gps);
|
||||||
|
|
||||||
return super.onCreateOptionsMenu(menu);
|
return super.onCreateOptionsMenu(menu);
|
||||||
@@ -396,13 +374,6 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
loaderCallbacks.setSearch(searchQuery);
|
loaderCallbacks.setSearch(searchQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onSearchRequested() {
|
|
||||||
// Hide trackController when search dialog is shown
|
|
||||||
trackController.hide();
|
|
||||||
return super.onSearchRequested();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TrackRecordingServiceConnection getTrackRecordingServiceConnection() {
|
protected TrackRecordingServiceConnection getTrackRecordingServiceConnection() {
|
||||||
return trackRecordingServiceConnection;
|
return trackRecordingServiceConnection;
|
||||||
@@ -585,10 +556,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe
|
|||||||
updateGpsMenuItem(true, recordingStatus.isRecording());
|
updateGpsMenuItem(true, recordingStatus.isRecording());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) {
|
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) {
|
||||||
recordingStatus = status;
|
recordingStatus = status;
|
||||||
|
|
||||||
trackController.update(recordingStatus);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ import de.dennisguse.opentracks.util.TrackUtils;
|
|||||||
*/
|
*/
|
||||||
//NOTE: This activity does NOT react to preference changes of R.string.recording_track_id_key.
|
//NOTE: This activity does NOT react to preference changes of R.string.recording_track_id_key.
|
||||||
//This mode of communication should be removed anyhow.
|
//This mode of communication should be removed anyhow.
|
||||||
public class TrackRecordingActivity extends AbstractActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller, TrackActivityDataHubInterface, TrackController.Callback {
|
public class TrackRecordingActivity extends AbstractActivity implements ChooseActivityTypeDialogFragment.ChooseActivityTypeCaller, TrackActivityDataHubInterface, ControllerFragment.Callback {
|
||||||
|
|
||||||
public static final String EXTRA_TRACK_ID = "track_id";
|
public static final String EXTRA_TRACK_ID = "track_id";
|
||||||
|
|
||||||
@@ -56,7 +56,6 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
|||||||
private SharedPreferences sharedPreferences;
|
private SharedPreferences sharedPreferences;
|
||||||
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
private TrackRecordingServiceConnection trackRecordingServiceConnection;
|
||||||
private TrackDataHub trackDataHub;
|
private TrackDataHub trackDataHub;
|
||||||
private TrackController trackController;
|
|
||||||
|
|
||||||
private TrackRecordingBinding viewBinding;
|
private TrackRecordingBinding viewBinding;
|
||||||
|
|
||||||
@@ -90,8 +89,6 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
|||||||
// A recording track is on.
|
// A recording track is on.
|
||||||
trackDataHub.loadTrack(trackId);
|
trackDataHub.loadTrack(trackId);
|
||||||
trackDataHub.setRecordingStatus(recordingStatus);
|
trackDataHub.setRecordingStatus(recordingStatus);
|
||||||
|
|
||||||
trackController.onResume(recordingStatus);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -148,8 +145,6 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
|||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
viewBinding.trackDetailActivityViewPager.setCurrentItem(savedInstanceState.getInt(CURRENT_TAB_TAG_KEY));
|
viewBinding.trackDetailActivityViewPager.setCurrentItem(savedInstanceState.getInt(CURRENT_TAB_TAG_KEY));
|
||||||
}
|
}
|
||||||
|
|
||||||
trackController = new TrackController(this, viewBinding.trackControllerContainer, trackRecordingServiceConnection, false, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -214,7 +209,6 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
|||||||
//TODO Pass recordingStatus directly to them
|
//TODO Pass recordingStatus directly to them
|
||||||
trackDataHub.loadTrack(trackId);
|
trackDataHub.loadTrack(trackId);
|
||||||
trackDataHub.setRecordingStatus(recordingStatus);
|
trackDataHub.setRecordingStatus(recordingStatus);
|
||||||
trackController.onResume(recordingStatus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -233,12 +227,6 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
|||||||
outState.putParcelable(EXTRA_TRACK_ID, trackId);
|
outState.putParcelable(EXTRA_TRACK_ID, trackId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
trackController.onPause();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStop() {
|
protected void onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
@@ -406,7 +394,6 @@ public class TrackRecordingActivity extends AbstractActivity implements ChooseAc
|
|||||||
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) {
|
private void onRecordingStatusChanged(TrackRecordingService.RecordingStatus status) {
|
||||||
recordingStatus = status;
|
recordingStatus = status;
|
||||||
|
|
||||||
trackController.update(recordingStatus);
|
|
||||||
trackDataHub.setRecordingStatus(recordingStatus);
|
trackDataHub.setRecordingStatus(recordingStatus);
|
||||||
|
|
||||||
setLockscreenPolicy();
|
setLockscreenPolicy();
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import java.util.ArrayList;
|
|||||||
|
|
||||||
import de.dennisguse.opentracks.ContextualActionModeCallback;
|
import de.dennisguse.opentracks.ContextualActionModeCallback;
|
||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
import de.dennisguse.opentracks.TrackController;
|
|
||||||
|
|
||||||
import static android.content.Context.VIBRATOR_SERVICE;
|
import static android.content.Context.VIBRATOR_SERVICE;
|
||||||
|
|
||||||
@@ -88,7 +87,7 @@ public class ActivityUtils {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void configureSearchWidget(Activity activity, final MenuItem menuItem, final TrackController trackController) {
|
public static void configureSearchWidget(Activity activity, final MenuItem menuItem) {
|
||||||
final SearchView searchView = (SearchView) menuItem.getActionView();
|
final SearchView searchView = (SearchView) menuItem.getActionView();
|
||||||
SearchManager searchManager = (SearchManager) activity.getSystemService(Context.SEARCH_SERVICE);
|
SearchManager searchManager = (SearchManager) activity.getSystemService(Context.SEARCH_SERVICE);
|
||||||
if (searchManager != null) {
|
if (searchManager != null) {
|
||||||
@@ -99,16 +98,6 @@ public class ActivityUtils {
|
|||||||
}
|
}
|
||||||
searchView.setQueryRefinementEnabled(true);
|
searchView.setQueryRefinementEnabled(true);
|
||||||
searchView.setSubmitButtonEnabled(true);
|
searchView.setSubmitButtonEnabled(true);
|
||||||
searchView.setOnQueryTextFocusChangeListener((v, hasFocus) -> {
|
|
||||||
// Hide and show trackController when searchable widget has focus/no focus
|
|
||||||
if (trackController != null) {
|
|
||||||
if (hasFocus) {
|
|
||||||
trackController.hide();
|
|
||||||
} else {
|
|
||||||
trackController.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -136,8 +125,8 @@ public class ActivityUtils {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void vibrate(Activity activity, int milliseconds) {
|
public static void vibrate(Context context, int milliseconds) {
|
||||||
final Vibrator vibrator = (Vibrator) activity.getSystemService(VIBRATOR_SERVICE);
|
final Vibrator vibrator = (Vibrator) context.getSystemService(VIBRATOR_SERVICE);
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
vibrator.vibrate(VibrationEffect.createOneShot(milliseconds, VibrationEffect.DEFAULT_AMPLITUDE));
|
vibrator.vibrate(VibrationEffect.createOneShot(milliseconds, VibrationEffect.DEFAULT_AMPLITUDE));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
Copyright 2013 Google Inc.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/controller_container"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@drawable/controller_background"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingStart="8dp"
|
||||||
|
android:paddingEnd="8dp">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/controller_record"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="10"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:contentDescription="@string/image_record"
|
||||||
|
android:src="@drawable/ic_button_record" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="6">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/controller_total_time"
|
||||||
|
style="@style/TextSmall"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:textColor="@android:color/white" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/controller_status"
|
||||||
|
style="@style/TextMicro"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_above="@id/controller_total_time"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:singleLine="true" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/controller_stop"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="10"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:contentDescription="@string/image_stop"
|
||||||
|
android:src="@drawable/button_stop" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
Copyright 2013 Google Inc.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
-->
|
|
||||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/track_controller_container"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@drawable/track_controller_background"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingStart="8dp"
|
|
||||||
android:paddingEnd="8dp">
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/track_controller_record"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="10"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
android:contentDescription="@string/image_record"
|
|
||||||
android:src="@drawable/ic_button_record" />
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="6">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/track_controller_total_time"
|
|
||||||
style="@style/TextSmall"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerInParent="true"
|
|
||||||
android:textColor="@android:color/white" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/track_controller_status"
|
|
||||||
style="@style/TextMicro"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_above="@id/track_controller_total_time"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:singleLine="true" />
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/track_controller_stop"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="10"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
android:contentDescription="@string/image_stop"
|
|
||||||
android:src="@drawable/button_stop" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</merge>
|
|
||||||
@@ -27,9 +27,11 @@ limitations under the License.
|
|||||||
android:baselineAligned="false"
|
android:baselineAligned="false"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<include
|
<androidx.fragment.app.FragmentContainerView
|
||||||
android:id="@+id/track_controller_container"
|
android:id="@+id/controller_fragment"
|
||||||
layout="@layout/track_controller" />
|
android:name="de.dennisguse.opentracks.ControllerFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<ListView
|
<ListView
|
||||||
android:id="@+id/track_list"
|
android:id="@+id/track_list"
|
||||||
|
|||||||
@@ -11,9 +11,11 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<include
|
<androidx.fragment.app.FragmentContainerView
|
||||||
android:id="@+id/track_controller_container"
|
android:id="@+id/controller_fragment"
|
||||||
layout="@layout/track_controller" />
|
android:name="de.dennisguse.opentracks.ControllerFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
Copyright 2012 Google Inc.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/controller_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/controller_background"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:paddingBottom="8dp">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/controller_record"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="10"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:contentDescription="@string/image_record"
|
||||||
|
android:src="@drawable/ic_button_record" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_weight="6">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/controller_total_time"
|
||||||
|
style="@style/TextSmall"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="@android:color/white"
|
||||||
|
tools:text="0:12:34" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/controller_status"
|
||||||
|
style="@style/TextMicro"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_above="@id/controller_total_time"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:gravity="center"
|
||||||
|
android:singleLine="true"
|
||||||
|
tools:text="@string/generic_recording" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/controller_stop"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="10"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:contentDescription="@string/image_stop"
|
||||||
|
android:src="@drawable/button_stop" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
Copyright 2012 Google Inc.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
-->
|
|
||||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/track_controller_container"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@drawable/track_controller_background"
|
|
||||||
android:paddingTop="8dp"
|
|
||||||
android:paddingBottom="8dp">
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/track_controller_record"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="10"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
android:contentDescription="@string/image_record"
|
|
||||||
android:src="@drawable/ic_button_record" />
|
|
||||||
|
|
||||||
<RelativeLayout
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_weight="6">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/track_controller_total_time"
|
|
||||||
style="@style/TextSmall"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
tools:text="0:12:34" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/track_controller_status"
|
|
||||||
style="@style/TextMicro"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_above="@id/track_controller_total_time"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:gravity="center"
|
|
||||||
android:singleLine="true"
|
|
||||||
tools:text="@string/generic_recording" />
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/track_controller_stop"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="10"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
android:contentDescription="@string/image_stop"
|
|
||||||
android:src="@drawable/button_stop" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</merge>
|
|
||||||
@@ -83,7 +83,9 @@ limitations under the License.
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<include
|
<androidx.fragment.app.FragmentContainerView
|
||||||
android:id="@+id/track_controller_container"
|
android:id="@+id/controller_fragment"
|
||||||
layout="@layout/track_controller" />
|
android:name="de.dennisguse.opentracks.ControllerFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -17,7 +17,9 @@
|
|||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="1" />
|
android:layout_weight="1" />
|
||||||
|
|
||||||
<include
|
<androidx.fragment.app.FragmentContainerView
|
||||||
android:id="@+id/track_controller_container"
|
android:id="@+id/controller_fragment"
|
||||||
layout="@layout/track_controller" />
|
android:name="de.dennisguse.opentracks.ControllerFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
Reference in New Issue
Block a user