saving the last track: implemented a floating action button sub menu instead of a user dialog (#2)

This commit is contained in:
y20k 2016-12-12 18:52:01 +01:00
parent c19cf469d3
commit f3909ec3a5
19 changed files with 451 additions and 208 deletions

View file

@ -25,6 +25,7 @@ dependencies {
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:25.0.1'
compile 'com.android.support:design:25.0.1'
compile 'com.android.support:cardview-v7:25.0.1'
compile 'org.osmdroid:osmdroid-android:5.5:release@aar'
compile 'com.google.code.gson:gson:2.8.0'
}

View file

@ -23,10 +23,12 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
@ -44,9 +46,9 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;
import org.y20k.trackbook.helpers.DialogClearFragment;
import org.y20k.trackbook.helpers.LogHelper;
import org.y20k.trackbook.helpers.NotificationHelper;
import org.y20k.trackbook.helpers.TrackbookKeys;
@ -60,7 +62,7 @@ import java.util.Map;
/**
* MainActivity class
*/
public class MainActivity extends AppCompatActivity implements TrackbookKeys, DialogClearFragment.DialogClearListener {
public class MainActivity extends AppCompatActivity implements TrackbookKeys {
/* Define log tag */
private static final String LOG_TAG = MainActivity.class.getSimpleName();
@ -68,9 +70,14 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys, Di
/* Main class variables */
private boolean mTrackerServiceRunning;
private boolean mCurrentTrackVisible;
private boolean mPermissionsGranted;
private boolean mFloatingActionButtonSubMenuVisible;
private List<String> mMissingPermissions;
private LinearLayout mFloatingActionButtonLayout;
private FloatingActionButton mFloatingActionButton;
private LinearLayout mFloatingActionButtonSubMenu1;
private LinearLayout mFloatingActionButtonSubMenu2;
private MainActivityMapFragment mMainActivityMapFragment;
private MainActivityTrackFragment mMainActivityTrackFragment;
private BroadcastReceiver mTrackingStoppedReceiver;
@ -81,12 +88,8 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys, Di
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// get state of tracking and get selected tab
mTrackerServiceRunning = false;
if (savedInstanceState != null) {
mTrackerServiceRunning = savedInstanceState.getBoolean(INSTANCE_TRACKING_STATE, false);
mSelectedTab = savedInstanceState.getInt(INSTANCE_SELECTED_TAB, 0);
}
// load saved state of app
loadAppState(this);
// check permissions on Android 6 and higher
mPermissionsGranted = false;
@ -104,7 +107,6 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys, Di
// set up main layout
setupLayout();
}
@ -112,27 +114,28 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys, Di
protected void onStart() {
super.onStart();
// add listeners to button
// add listeners to button and submenu
if (mFloatingActionButton != null) {
mFloatingActionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// onClick: start / stop tracking
handleFloatingActionButtonClick(view);
}
});
mFloatingActionButton.setOnLongClickListener(new View.OnLongClickListener() {
}
if (mFloatingActionButtonSubMenu1 != null) {
mFloatingActionButtonSubMenu1.setOnClickListener(new View.OnClickListener() {
@Override
public boolean onLongClick(View view) {
// onLongClick: clear map
if (mTrackerServiceRunning || mMainActivityMapFragment == null) {
return false;
} else {
// show clear dialog
DialogFragment dialog = new DialogClearFragment();
dialog.show(getFragmentManager(), "DialogClearFragment");
return true;
}
public void onClick(View view) {
handleButtonSaveAndClearClick();
}
});
}
if (mFloatingActionButtonSubMenu2 != null) {
mFloatingActionButtonSubMenu2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
handleButtonClearClick();
}
});
}
@ -177,14 +180,6 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys, Di
}
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putBoolean(INSTANCE_TRACKING_STATE, mTrackerServiceRunning);
outState.putInt(INSTANCE_SELECTED_TAB, mSelectedTab);
super.onSaveInstanceState(outState);
}
@Override
protected void onResume() {
super.onResume();
@ -243,25 +238,48 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys, Di
@Override
public void onDialogClearPositiveClick(DialogFragment dialog) {
// DialogClear: User chose CLEAR.
LogHelper.v(LOG_TAG, "User chose CLEAR");
// clear the map
mMainActivityMapFragment.clearMap();
// reset current track
mMainActivityTrackFragment.refreshTrackView();
// dismiss notification
NotificationHelper.stop();
protected void onSaveInstanceState(Bundle outState) {
LogHelper.v(LOG_TAG, "onSaveInstanceState called.");
outState.putBoolean(INSTANCE_TRACKING_STATE, mTrackerServiceRunning);
outState.putBoolean(INSTANCE_TRACK_VISIBLE, mCurrentTrackVisible);
outState.putBoolean(INSTANCE_FAB_SUB_MENU_VISIBLE, mFloatingActionButtonSubMenuVisible);
outState.putInt(INSTANCE_SELECTED_TAB, mSelectedTab);
super.onSaveInstanceState(outState);
}
@Override
public void onDialogClearNegativeClick(DialogFragment dialog) {
// DialogClear: User chose CANCEL.
LogHelper.v(LOG_TAG, "User chose CANCEL.");
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
LogHelper.v(LOG_TAG, "onRestoreInstanceState called.");
mTrackerServiceRunning = savedInstanceState.getBoolean(INSTANCE_TRACKING_STATE, false);
mCurrentTrackVisible = savedInstanceState.getBoolean(INSTANCE_TRACK_VISIBLE, false);
mFloatingActionButtonSubMenuVisible = savedInstanceState.getBoolean(INSTANCE_FAB_SUB_MENU_VISIBLE, false);
mSelectedTab = savedInstanceState.getInt(INSTANCE_SELECTED_TAB, 0);
}
/* Saves app state to SharedPreferences */
private void saveAppState(Context context) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean(INSTANCE_TRACKING_STATE, mTrackerServiceRunning);
editor.putBoolean(INSTANCE_TRACK_VISIBLE, mCurrentTrackVisible);
editor.putBoolean(INSTANCE_FAB_SUB_MENU_VISIBLE, mFloatingActionButtonSubMenuVisible);
editor.putInt(INSTANCE_SELECTED_TAB, mSelectedTab);
editor.apply();
LogHelper.v(LOG_TAG, "Saving state.");
}
/* Loads app state from preferences */
private void loadAppState(Context context) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
mTrackerServiceRunning = settings.getBoolean(INSTANCE_TRACKING_STATE, false);
mCurrentTrackVisible = settings.getBoolean(INSTANCE_TRACK_VISIBLE, false);
mFloatingActionButtonSubMenuVisible = settings.getBoolean(INSTANCE_FAB_SUB_MENU_VISIBLE, false);
mSelectedTab = settings.getInt(INSTANCE_SELECTED_TAB, 0);
LogHelper.v(LOG_TAG, "Loading state.");
}
@ -269,7 +287,7 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys, Di
private void setupLayout() {
if (mPermissionsGranted) {
// point to the main map layout
setContentView(R.layout.activity_main_test);
setContentView(R.layout.activity_main);
// show action bar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
@ -312,8 +330,16 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys, Di
}
});
// show the record button and attach listener
mFloatingActionButton = (FloatingActionButton) findViewById(R.id.fab);
// get references to the record button and show/hide its sub menu
mFloatingActionButtonLayout = (LinearLayout) findViewById(R.id.fabFrameLayout);
mFloatingActionButton = (FloatingActionButton) findViewById(R.id.fabMainButton);
mFloatingActionButtonSubMenu1 = (LinearLayout) findViewById(R.id.fabSubMenu1);
mFloatingActionButtonSubMenu2 = (LinearLayout) findViewById(R.id.fabSubMenu2);
if (mFloatingActionButtonSubMenuVisible) {
showFloatingActionButtonMenu(true);
} else {
showFloatingActionButtonMenu(false);
}
} else {
// point to the on main onboarding layout
@ -338,6 +364,15 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys, Di
}
@Override
protected void onPause() {
super.onPause();
// save current state
saveAppState(this);
}
/* Handles tap on the record button */
private void handleFloatingActionButtonClick(View view) {
if (mTrackerServiceRunning) {
@ -352,14 +387,21 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys, Di
intent.setAction(ACTION_STOP);
startService(intent);
} else if (mCurrentTrackVisible) {
// toggle floating action button sub menu
if (!mFloatingActionButtonSubMenuVisible) {
showFloatingActionButtonMenu(true);
} else {
showFloatingActionButtonMenu(false);
}
} else {
// TODO ask if user wants to save the last track before starting a new recording
// TODO alternatively only ask if last track was very short
// show snackbar
Snackbar.make(view, R.string.snackbar_message_tracking_started, Snackbar.LENGTH_SHORT).setAction("Action", null).show();
// change state
mTrackerServiceRunning = true;
mCurrentTrackVisible = true;
setFloatingActionButtonState();
// get last location from MainActivity Fragment
@ -385,16 +427,76 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys, Di
}
/* Handles tap on the save and clear button */
public void handleButtonSaveAndClearClick() {
LogHelper.v(LOG_TAG, "User chose SAVE and CLEAR");
// clear map and save track
mMainActivityMapFragment.clearMap(true); // TODO change to true
mCurrentTrackVisible = false;
// // reset current track // TODO ist this still necessary
// mMainActivityTrackFragment.refreshTrackView();
// TODO change to track tab
// dismiss notification
NotificationHelper.stop();
// hide Floating Action Button sub menu
showFloatingActionButtonMenu(false);
// update Floating Action Button icon
setFloatingActionButtonState();
}
/* Handles tap on the clear button */
public void handleButtonClearClick() {
LogHelper.v(LOG_TAG, "User chose CLEAR");
// clear map, do not save track
mMainActivityMapFragment.clearMap(false);
mCurrentTrackVisible = false;
// dismiss notification
NotificationHelper.stop();
// hide Floating Action Button sub menu
showFloatingActionButtonMenu(false);
// update Floating Action Button icon
setFloatingActionButtonState();
}
/* Set state of FloatingActionButton */
private void setFloatingActionButtonState() {
if (mTrackerServiceRunning) {
mFloatingActionButton.setImageResource(R.drawable.ic_fiber_manual_record_red_24dp);
} else if (mCurrentTrackVisible) {
mFloatingActionButton.setImageResource(R.drawable.ic_save_white_24dp);
} else {
mFloatingActionButton.setImageResource(R.drawable.ic_fiber_manual_record_white_24dp);
}
}
/* Shows (and hides) the sub menu of the floating action button */
private void showFloatingActionButtonMenu(boolean visible) {
if (visible) {
mFloatingActionButtonSubMenu1.setVisibility(View.VISIBLE);
mFloatingActionButtonSubMenu2.setVisibility(View.VISIBLE);
mFloatingActionButtonSubMenuVisible = true;
} else {
mFloatingActionButtonSubMenu1.setVisibility(View.INVISIBLE);
mFloatingActionButtonSubMenu2.setVisibility(View.INVISIBLE);
mFloatingActionButtonSubMenuVisible = false;
}
}
/* Handles new incoming intents */
private void handleIncomingIntent() {
Intent intent = getIntent();
@ -407,12 +509,6 @@ public class MainActivity extends AppCompatActivity implements TrackbookKeys, Di
mMainActivityMapFragment.setTrackingState(mTrackerServiceRunning);
// prevent multiple reactions to intent
intent.setAction(ACTION_DEFAULT);
} else if (intent.hasExtra(EXTRA_CLEAR_MAP) && mMainActivityMapFragment != null) {
// show clear dialog
DialogFragment dialog = new DialogClearFragment();
dialog.show(getFragmentManager(), "DialogClearFragment");
// prevent multiple reactions to intent
intent.setAction(ACTION_DEFAULT);
}
break;

View file

@ -108,7 +108,7 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys {
mFirstStart = savedInstanceState.getBoolean(INSTANCE_FIRST_START, true);
}
// restore tracking state
// restore tracking and map state
mTrackerServiceRunning = false;
if (savedInstanceState != null) {
mTrackerServiceRunning = savedInstanceState.getBoolean(INSTANCE_TRACKING_STATE, false);
@ -235,7 +235,7 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys {
// show/hide the location off notification bar
toggleLocationOffBar();
// start preliminary tracking - if no TrackerService is running
// start preliminary tracking - if no TrackerService is running // TODO check if this still works in tabbed ui
if (!mTrackerServiceRunning && mFragmentVisible) {
startPreliminaryTracking();
}
@ -388,20 +388,26 @@ public class MainActivityMapFragment extends Fragment implements TrackbookKeys {
/* Removes track crumbs from map */
public void clearMap() {
LogHelper.v(LOG_TAG, "!!! Ding clear.");
public void clearMap(boolean saveTrack) {
// clear map
if (mTrackOverlay != null) {
Toast.makeText(mActivity, mActivity.getString(R.string.toast_message_clear_map), Toast.LENGTH_LONG).show();
mMapView.getOverlays().remove(mTrackOverlay);
}
// save track object
SaveTrackAsyncHelper saveTrackAsyncHelper = new SaveTrackAsyncHelper();
saveTrackAsyncHelper.execute();
// TODO add toast indicating track save
// save track object if requested
if (saveTrack) {
SaveTrackAsyncHelper saveTrackAsyncHelper = new SaveTrackAsyncHelper();
saveTrackAsyncHelper.execute();
Toast.makeText(mActivity, mActivity.getString(R.string.toast_message_save_track), Toast.LENGTH_LONG).show();
}
}
/* Getter for length of current track */
public String getCurrentTrackLength() {
return mTrack.getTrackDistance();
}

View file

@ -1,83 +0,0 @@
/**
* DialogClearFragment.java
* Implements the DialogClearFragment class
* A DialogClearFragment appears when the user wants to clear the map
*
* This file is part of
* TRACKBOOK - Movement Recorder for Android
*
* Copyright (c) 2016 - Y20K.org
* Licensed under the MIT-License
* http://opensource.org/licenses/MIT
*
* Trackbook uses osmdroid - OpenStreetMap-Tools for Android
* https://github.com/osmdroid/osmdroid
*/
package org.y20k.trackbook.helpers;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import org.y20k.trackbook.R;
/**
* DialogClearFragment class
*/
public class DialogClearFragment extends DialogFragment {
/* Define log tag */
private static final String LOG_TAG = DialogClearFragment.class.getSimpleName();
/* Interface that the context that creates an instance of this fragment must implement */
public interface DialogClearListener {
public void onDialogClearPositiveClick(DialogFragment dialog);
public void onDialogClearNegativeClick(DialogFragment dialog);
}
/* Main class variables */
private DialogClearListener mListener;
@Override
public void onAttach(Context context) {
super.onAttach(context);
// verify that the host context implements the callback interface
try {
// instantiate the NoticeDialogListener so we can send events to the host
mListener = (DialogClearListener) context;
} catch (ClassCastException e) {
LogHelper.e(LOG_TAG, "Context does not implement the DialogClearListener interface.");
}
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// construct dialog
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.dialog_clear_map_title)
.setMessage(R.string.dialog_clear_map_message)
.setPositiveButton(R.string.dialog_clear_map_okay, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// user clicked CLEAR - inform initiating fragment / context
mListener.onDialogClearPositiveClick(DialogClearFragment.this);
}
})
.setNegativeButton(R.string.dialog_clear_map_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// user clicked CANCEL - inform initiating fragment / context
mListener.onDialogClearNegativeClick(DialogClearFragment.this);
}
});
// create the AlertDialog object and return it
return builder.create();
}
}

View file

@ -114,8 +114,6 @@ public class NotificationHelper implements TrackbookKeys {
TaskStackBuilder swipeActionIntentBuilder = TaskStackBuilder.create(mService);
swipeActionIntentBuilder.addParentStack(MainActivity.class);
swipeActionIntentBuilder.addNextIntent(swipeActionIntent);
// pending intent wrapper for notification tap
PendingIntent swipeActionPendingIntent = swipeActionIntentBuilder.getPendingIntent(11, PendingIntent.FLAG_UPDATE_CURRENT);
// ACTION: NOTIFICATION BUTTON STOP
Intent stopActionIntent = new Intent(mService, TrackerService.class);
@ -136,10 +134,8 @@ public class NotificationHelper implements TrackbookKeys {
builder.setContentTitle(mService.getString(R.string.notification_title_trackbook_running));
builder.setContentText(contentText);
} else {
builder.setDeleteIntent(swipeActionPendingIntent);
builder.setContentTitle(mService.getString(R.string.notification_title_trackbook_not_running));
builder.setContentText(contentText);
builder.setSubText(mService.getString(R.string.notification_swipe_to_clear_map));
}
return builder;

View file

@ -42,6 +42,8 @@ public interface TrackbookKeys {
String ARG_PERMISSIONS_GRANTED = "ArgPermissionsGranted";
String ARG_TRACKING_STATE = "ArgTrackingState";
String ARG_TRACK = "ArgTrack";
String ARG_TRACK_VISIBLE = "ArgTrackVisible";
String ARG_TRACK_DISTANCE = "ArgTrackDistance";
/* TAGS */
String TAG_MAIN_ACTIVITY_FRAGMENT = "TagMainActivityFragment";
@ -58,7 +60,9 @@ public interface TrackbookKeys {
/* INSTANCE STATE */
String INSTANCE_FIRST_START = "firstStart";
String INSTANCE_TRACKING_STATE = "trackingState";
String INSTANCE_TRACK_VISIBLE = "trackVisible";
String INSTANCE_SELECTED_TAB = "selectedTab";
String INSTANCE_FAB_SUB_MENU_VISIBLE = "fabSubMenuVisible";
String INSTANCE_TRACK_MAIN_MAP = "trackMainMap";
String INSTANCE_LATITUDE_MAIN_MAP = "latitudeMainMap";
String INSTANCE_LONGITUDE_MAIN_MAP = "longitudeMainMap";

View file

@ -0,0 +1,68 @@
/**
* DodgeAbleLayoutBehavior.java
* Implements the DodgeAbleLayoutBehavior class
* A DodgeAbleLayoutBehavior enables any element to be dodged up by a snackbar
*
* This file is part of
* TRACKBOOK - Movement Recorder for Android
*
* Copyright (c) 2016 - Y20K.org
* Licensed under the MIT-License
* http://opensource.org/licenses/MIT
*
* Trackbook uses osmdroid - OpenStreetMap-Tools for Android
* https://github.com/osmdroid/osmdroid
*/
package org.y20k.trackbook.layout;
import android.content.Context;
import android.os.Build;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.util.AttributeSet;
import android.view.View;
/**
* DodgeAbleLayoutBehavior class
* adapted from: http://stackoverflow.com/a/35904421
*/
public class DodgeAbleLayoutBehavior extends CoordinatorLayout.Behavior<View> {
/* Main class variables */
private static final boolean SNACKBAR_BEHAVIOR_ENABLED;
/* Constructor (default) */
public DodgeAbleLayoutBehavior() {
super();
}
/* Constructor for context and attributes */
public DodgeAbleLayoutBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
return SNACKBAR_BEHAVIOR_ENABLED && dependency instanceof Snackbar.SnackbarLayout;
}
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());
child.setTranslationY(translationY);
return true;
}
static {
SNACKBAR_BEHAVIOR_ENABLED = Build.VERSION.SDK_INT >= 11;
}
}

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"
android:fillColor="@color/trackbook_white" />
</vector>

View file

@ -5,5 +5,5 @@
android:viewportHeight="24.0">
<path
android:pathData="M12,12m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
android:fillColor="#FFFFFF"/>
android:fillColor="@color/trackbook_white" />
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/trackbook_white"
android:pathData="M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/trackbook_white"
android:pathData="M9,11L7,11v2h2v-2zM13,11h-2v2h2v-2zM17,11h-2v2h2v-2zM19,4h-1L18,2h-2v2L8,4L8,2L6,2v2L5,4c-1.11,0 -1.99,0.9 -1.99,2L3,20c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,6c0,-1.1 -0.9,-2 -2,-2zM19,20L5,20L5,9h14v11z"/>
</vector>

View file

@ -1,15 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="org.y20k.trackbook.MainActivity">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/appbar_padding_top"
android:theme="@style/TrackbookAppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
@ -17,31 +21,39 @@
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/TrackbookAppTheme.PopupOverlay" />
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/TrackbookAppTheme.PopupOverlay">
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMaxWidth="0dp"
app:tabGravity="fill"
app:tabMode="fixed" />
</android.support.design.widget.AppBarLayout>
<!-- include MainActivityMapFragment -->
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/content_main"
android:name="org.y20k.trackbook.MainActivityMapFragment"
<android.support.v4.view.ViewPager
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:layout="@layout/fragment_main_map" />
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<!-- MainActivityMapFragment and MainActivityTrackFragment are included at runtime -->
<android.support.design.widget.FloatingActionButton
<include layout="@layout/floating_action_button" />
<!-- <android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@drawable/ic_fiber_manual_record_white_24dp"
app:fabSize="auto"/>
app:fabSize="auto"/> -->
</android.support.design.widget.CoordinatorLayout>
</android.support.design.widget.CoordinatorLayout>

View file

@ -1,19 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="org.y20k.trackbook.MainActivity">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/appbar_padding_top"
android:theme="@style/TrackbookAppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
@ -21,37 +17,33 @@
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/TrackbookAppTheme.PopupOverlay">
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMaxWidth="0dp"
app:tabGravity="fill"
app:tabMode="fixed" />
app:popupTheme="@style/TrackbookAppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/container"
<!-- include MainActivityMapFragment -->
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/content_main"
android:name="org.y20k.trackbook.MainActivityMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<!-- MainActivityMapFragment and MainActivityTrackFragment are included at runtime -->
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:layout="@layout/fragment_main_map" />
<android.support.design.widget.FloatingActionButton
<include layout="@layout/floating_action_button" />
<!-- <android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@drawable/ic_fiber_manual_record_white_24dp"
app:fabSize="auto"/>
app:fabSize="auto"/> -->
</android.support.design.widget.CoordinatorLayout>
</android.support.design.widget.CoordinatorLayout>

View file

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- TODO add missing descriptions and color definitions -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/fabFrameLayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:layout_behavior="org.y20k.trackbook.layout.DodgeAbleLayoutBehavior">
<LinearLayout
android:id="@+id/fabSubMenu1"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:gravity="center_vertical"
android:layout_weight="1"
android:layout_gravity="bottom|end"
android:layout_marginEnd="8dp"
android:layout_marginBottom="@dimen/fab_margin"
android:orientation="horizontal"
android:visibility="visible">
<android.support.v7.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
app:cardBackgroundColor="@color/trackbook_white"
app:cardCornerRadius="4dp"
app:cardElevation="4dp"
app:cardUseCompatPadding="true" >
<TextView
android:id="@+id/fabSubMenuLabel1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="@string/fab_sub_menu_save_and_clear"
android:textStyle="bold"
android:paddingRight="6dp"
android:paddingLeft="6dp"
android:paddingBottom="2dp"
android:paddingTop="2dp" />
</android.support.v7.widget.CardView>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fabSubMenuButton1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
app:srcCompat="@drawable/ic_save_white_24dp"
app:backgroundTint="#4CAF50"
app:fabSize="mini" />
</LinearLayout>
<LinearLayout
android:id="@+id/fabSubMenu2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_gravity="bottom|end"
android:layout_marginEnd="8dp"
android:layout_marginBottom="@dimen/fab_margin"
android:orientation="horizontal"
android:visibility="visible">
<android.support.v7.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/trackbook_white"
app:cardCornerRadius="4dp"
app:cardElevation="4dp"
app:cardUseCompatPadding="true">
<TextView
android:id="@+id/fabSubMenuLabel2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="@string/fab_sub_menu_clear"
android:textStyle="bold"
android:paddingRight="6dp"
android:paddingLeft="6dp"
android:paddingBottom="2dp"
android:paddingTop="2dp" />
</android.support.v7.widget.CardView>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fabSubMenuButton2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_clear_white_24dp"
app:backgroundTint="#2196F3"
app:fabSize="mini" />
</LinearLayout>
<LinearLayout
android:id="@+id/fabMain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:orientation="horizontal">
<android.support.design.widget.FloatingActionButton
android:id="@+id/fabMainButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_fiber_manual_record_white_24dp"
app:fabSize="normal" />
</LinearLayout>
<!-- <android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@drawable/ic_fiber_manual_record_white_24dp"
app:fabSize="auto"/> -->
</LinearLayout>

View file

@ -7,7 +7,7 @@
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:context=".MainActivityMapFragment"
tools:showIn="@layout/activity_main">
tools:showIn="@layout/activity_main_old">
<org.osmdroid.views.MapView android:id="@+id/map"
android:layout_width="fill_parent"

View file

@ -15,8 +15,6 @@
android:layout_height="fill_parent"
android:contentDescription="@string/descr_map_last_track" />
<!-- TODO ADD android:contentDescription="@string/descr_xyz" -->
<!-- BOTTOM SHEET -->
<android.support.v4.widget.NestedScrollView
android:id="@+id/statistics_sheet"

View file

@ -28,11 +28,9 @@
<string name="snackbar_message_tracking_started">Tracking aktiviert</string>
<string name="snackbar_message_location_offline">Standortdienste sind deaktiviert. Trackbook kann nicht aufzeichnen.</string>
<!-- dialogs -->
<string name="dialog_clear_map_title">Zurücksetzen</string>
<string name="dialog_clear_map_message">Möchten Sie die Karte zurücksetzen?</string>
<string name="dialog_clear_map_okay">Zurücksetzen</string>
<string name="dialog_clear_map_cancel">Abbrechen</string>
<!-- fab sub menu -->
<string name="fab_sub_menu_clear">Zurücksetzen</string>
<string name="fab_sub_menu_save_and_clear">Speichern und Zurücksetzen</string>
<!-- toast messages -->
<string name="toast_message_permissions_granted">Berechtigungen erteilt.</string>
@ -42,7 +40,7 @@
<string name="toast_message_acquiring_location">Suche aktuellen Standort.</string>
<string name="toast_message_location_services_not_ready">Standortdienste noch nicht bereit. Bitte erneut versuchen.</string>
<string name="toast_message_last_location">Letzte Position:</string>
<string name="toast_message_clear_map">Kartenansicht wird zurückgesetzt</string>
<string name="toast_message_save_track">Aufzeichnung wird gespeichert.</string>
<string name="toast_message_last_location_age_one_hour">über eine Stunde</string>
<!-- map markers -->

View file

@ -28,11 +28,10 @@
<string name="snackbar_message_tracking_started">Tracking started</string>
<string name="snackbar_message_location_offline">Location is turned off. Trackbook will not work.</string>
<!-- dialogs -->
<string name="dialog_clear_map_title">Clear</string>
<string name="dialog_clear_map_message">Do you want to clear the map?</string>
<string name="dialog_clear_map_okay">Clear</string>
<string name="dialog_clear_map_cancel">Cancel</string>
<!-- fab sub menu -->
<string name="fab_sub_menu_clear">Clear</string>
<string name="fab_sub_menu_save_and_clear">Save and Clear</string>
<!-- toast messages -->
<string name="toast_message_permissions_granted">Permissions granted.</string>
@ -42,7 +41,7 @@
<string name="toast_message_acquiring_location">Acquiring current location.</string>
<string name="toast_message_location_services_not_ready">Location services not ready. Please retry.</string>
<string name="toast_message_last_location">Last location:</string>
<string name="toast_message_clear_map">Clearing map.</string>
<string name="toast_message_save_track">Saving current track.</string>
<string name="toast_message_last_location_age_one_hour">over one hour</string>
<!-- map markers -->

View file

@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.2'
classpath 'com.android.tools.build:gradle:2.2.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files