1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2025-01-14 03:37:32 +01:00

Improve Sports Activities dashboard and Filter

- makes nicer dashboard, unify with design in Activity List
- dashboard is now part of the sports activities list (had to overcome
  some hurdles, because of the multiselect for sharing)
- add icons to Spinners in Sports Filter
This commit is contained in:
vanous 2020-11-22 22:33:55 +01:00
parent b0a0a29bcb
commit 5c3c23ea50
20 changed files with 910 additions and 423 deletions

View File

@ -7,8 +7,8 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="22.620001"
height="22.620001"
width="24"
height="24"
tint="#7E7E7E"
viewportWidth="25"
viewportHeight="25"
@ -46,37 +46,37 @@
showguides="true"
inkscape:guide-bbox="true"
inkscape:zoom="20.08"
inkscape:cx="22.086921"
inkscape:cy="16.68033"
inkscape:cx="19.684708"
inkscape:cy="14.278117"
inkscape:window-x="0"
inkscape:window-y="38"
inkscape:window-maximized="1"
inkscape:current-layer="svg1967"
inkscape:document-rotation="0">
<sodipodi:guide
position="22.62,162.31"
position="20.217787,166.09221"
orientation="0,-1"
id="guide2551" />
<sodipodi:guide
position="11.17728,160.50592"
position="8.775067,164.28813"
orientation="1,0"
id="guide2553" />
</sodipodi:namedview>
<g
id="g5608"
transform="matrix(0.6107681,0,0,0.6107681,3.9807832,3.9807832)"
style="stroke-width:1.63728">
transform="matrix(0.8841733,0,0,0.8841733,1.3899206,1.3899206)"
style="stroke-width:1.131">
<path
fill="#000000"
d="m 12,18 a 6,6 0 0 1 -6,-6 6,6 0 0 1 6,-6 6,6 0 0 1 6,6 6,6 0 0 1 -6,6 M 20,15.31 23.31,12 20,8.69 V 4 H 15.31 L 12,0.69 8.69,4 H 4 V 8.69 L 0.69,12 4,15.31 V 20 H 8.69 L 12,23.31 15.31,20 H 20 Z"
id="path1965"
style="stroke-width:2.82858" />
style="stroke-width:1.95392" />
<path
fill="currentColor"
d="m 4.4762317,12.388718 h 3.561751 l 2.0837443,-5.0286723 1.932068,5.4893343 1.823648,-2.726785 h 6.48905 l -0.488068,1.38717 H 14.61543 l -2.938854,4.509156 -1.60202,-4.54569 -0.9505983,2.403348 -3.506487,-4.01e-4 z"
id="path2361"
sodipodi:nodetypes="ccccccccccccc"
style="stroke-width:1.63728"
style="stroke-width:1.131"
inkscape:transform-center-x="1.0957646"
inkscape:transform-center-y="-1.4792654" />
</g>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -24,7 +24,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.util.SparseBooleanArray;
@ -33,14 +32,10 @@ import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.DatePicker;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.core.content.FileProvider;
@ -49,22 +44,17 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.Serializable;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
@ -76,29 +66,23 @@ import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummary;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryJsonSummary;
import nodomain.freeyourgadget.gadgetbridge.model.RecordedDataTypes;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class ActivitySummariesActivity extends AbstractListActivity<BaseActivitySummary> {
static final int ACTIVITY_FILTER = 1;
static final int ACTIVITY_DETAIL = 11;
private static final Logger LOG = LoggerFactory.getLogger(ActivitySummariesActivity.class);
HashMap<String, Integer> activityKindMap = new HashMap<>(0);
int activityFilter = 0;
long dateFromFilter = 0;
long dateToFilter = 0;
long deviceFilter;
List<Long> itemsFilter;
String nameContainsFilter;
private GBDevice mGBDevice;
private SwipeRefreshLayout swipeLayout;
HashMap<String , Integer> activityKindMap = new HashMap<>(1);
int activityFilter=0;
long dateFromFilter=0;
long dateToFilter=0;
long deviceFilter;
List<Long>itemsFilter;
String nameContainsFilter;
boolean offscreen = true;
static final int ACTIVITY_FILTER=1;
static final int ACTIVITY_DETAIL=11;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@ -120,6 +104,14 @@ public class ActivitySummariesActivity extends AbstractListActivity<BaseActivity
}
}
};
private int subtrackDashboard = 0;
public static int getBackgroundColor(Context context) {
TypedValue typedValue = new TypedValue();
Resources.Theme theme = context.getTheme();
theme.resolveAttribute(R.attr.sports_activity_summary_background, typedValue, true);
return typedValue.data;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
@ -136,97 +128,19 @@ public class ActivitySummariesActivity extends AbstractListActivity<BaseActivity
switch (item.getItemId()) {
case android.R.id.home:
// back button, close drawer if open, otherwise exit
if (!offscreen){
processSummaryStatistics();
}else{
finish();
}
finish();
return true;
case R.id.activity_action_manage_timestamp:
resetFetchTimestampToChosenDate();
processed = true;
break;
case R.id.activity_action_filter:
if (!offscreen) processSummaryStatistics(); //hide drawer with stats if shown
runFilterActivity();
return true;
case R.id.activity_action_calculate_summary_stats:
processSummaryStatistics();
return true;
}
return processed;
}
private void processSummaryStatistics() {
View hiddenLayout = findViewById(R.id.activity_summary_statistics_relative_layout);
hiddenLayout.setVisibility(View.VISIBLE);
//hide or show drawer
int yOffset = (offscreen) ? 0 : -1 * hiddenLayout.getHeight();
LinearLayout.LayoutParams rlParams =
(LinearLayout.LayoutParams) hiddenLayout.getLayoutParams();
rlParams.setMargins(0, yOffset, 0, 0);
hiddenLayout.setLayoutParams(rlParams);
Animation animFadeDown;
animFadeDown = AnimationUtils.loadAnimation(
this,
R.anim.slidefromtop);
setTitle(R.string.activity_summaries);
if (offscreen) {
setTitle(R.string.activity_summaries_statistics);
hiddenLayout.startAnimation(animFadeDown);
double durationSum = 0;
double caloriesBurntSum = 0;
double distanceSum = 0;
double activeSecondsSum = 0;
double firstItemDate = 0;
double lastItemDate = 0;
TextView durationSumView = findViewById(R.id.activity_stats_duration_sum_value);
TextView caloriesBurntSumView = findViewById(R.id.activity_stats_calories_burnt_sum_value);
TextView distanceSumView = findViewById(R.id.activity_stats_distance_sum_value);
TextView activeSecondsSumView = findViewById(R.id.activity_stats_activeSeconds_sum_value);
TextView timeStartView = findViewById(R.id.activity_stats_timeFrom_value);
TextView timeEndView = findViewById(R.id.activity_stats_timeTo_value);
for (BaseActivitySummary sportitem : getItemAdapter().getItems()) {
if (firstItemDate == 0) firstItemDate = sportitem.getStartTime().getTime();
lastItemDate = sportitem.getEndTime().getTime();
durationSum += sportitem.getEndTime().getTime() - sportitem.getStartTime().getTime();
ActivitySummaryJsonSummary activitySummaryJsonSummary = new ActivitySummaryJsonSummary(sportitem);
JSONObject summarySubdata = activitySummaryJsonSummary.getSummaryData();
if (summarySubdata != null) {
try {
if (summarySubdata.has("caloriesBurnt")) {
caloriesBurntSum += summarySubdata.getJSONObject("caloriesBurnt").getDouble("value");
}
if (summarySubdata.has("distanceMeters")) {
distanceSum += summarySubdata.getJSONObject("distanceMeters").getDouble("value");
}
if (summarySubdata.has("activeSeconds")) {
activeSecondsSum += summarySubdata.getJSONObject("activeSeconds").getDouble("value");
}
} catch (JSONException e) {
LOG.error("SportsActivity", e);
}
}
}
DecimalFormat df = new DecimalFormat("#.##");
durationSumView.setText(String.format("%s", DateTimeUtils.formatDurationHoursMinutes((long) durationSum, TimeUnit.MILLISECONDS)));
caloriesBurntSumView.setText(String.format("%s %s", (long) caloriesBurntSum, getString(R.string.calories_unit)));
distanceSumView.setText(String.format("%s %s", df.format(distanceSum / 1000), getString(R.string.km)));
activeSecondsSumView.setText(String.format("%s", DateTimeUtils.formatDurationHoursMinutes((long) activeSecondsSum, TimeUnit.SECONDS)));
//start and end are inverted when filer not applied, because items are sorted the other way
timeStartView.setText((dateFromFilter != 0) ? DateTimeUtils.formatDate(new Date(dateFromFilter)) : DateTimeUtils.formatDate(new Date((long) lastItemDate)));
timeEndView.setText((dateToFilter != 0) ? DateTimeUtils.formatDate(new Date(dateToFilter)) : DateTimeUtils.formatDate(new Date((long) firstItemDate)));
}
offscreen = !offscreen;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
super.onActivityResult(requestCode, resultCode, resultData);
@ -239,7 +153,6 @@ public class ActivitySummariesActivity extends AbstractListActivity<BaseActivity
nameContainsFilter = bundle.getString("nameContainsFilter");
itemsFilter = (List<Long>) bundle.getSerializable("itemsFilter");
setActivityKindFilter(activityFilter);
setActivityKindFilter(activityFilter);
setDateFromFilter(dateFromFilter);
setDateToFilter(dateToFilter);
setNameContainsFilter(nameContainsFilter);
@ -252,6 +165,7 @@ public class ActivitySummariesActivity extends AbstractListActivity<BaseActivity
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
Bundle extras = getIntent().getExtras();
@ -260,7 +174,7 @@ public class ActivitySummariesActivity extends AbstractListActivity<BaseActivity
} else {
throw new IllegalArgumentException("Must provide a device when invoking this activity");
}
deviceFilter=getDeviceId(mGBDevice);
deviceFilter = getDeviceId(mGBDevice);
IntentFilter filterLocal = new IntentFilter();
filterLocal.addAction(GBDevice.ACTION_DEVICE_CHANGED);
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filterLocal);
@ -275,6 +189,7 @@ public class ActivitySummariesActivity extends AbstractListActivity<BaseActivity
getItemListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (position == 0) return; // item 0 is empty for dashboard
Object item = parent.getItemAtPosition(position);
if (item != null) {
ActivitySummary summary = (ActivitySummary) item;
@ -289,14 +204,13 @@ public class ActivitySummariesActivity extends AbstractListActivity<BaseActivity
});
getItemListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
//hide top drawer on init
View hiddenLayout = findViewById(R.id.activity_summary_statistics_relative_layout);
hiddenLayout.setVisibility(View.GONE);
getItemListView().setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
@Override
public void onItemCheckedStateChanged(ActionMode actionMode, int position, long id, boolean checked) {
final int selectedItems = getItemListView().getCheckedItemCount();
if (position == 0 && checked) subtrackDashboard = 1;
if (position == 0 && !checked) subtrackDashboard = 0;
final int selectedItems = getItemListView().getCheckedItemCount() - subtrackDashboard;
actionMode.setTitle(selectedItems + " selected");
}
@ -319,19 +233,18 @@ public class ActivitySummariesActivity extends AbstractListActivity<BaseActivity
switch (menuItem.getItemId()) {
case R.id.activity_action_delete:
List<BaseActivitySummary> toDelete = new ArrayList<>();
for(int i = 0; i< checked.size(); i++) {
for (int i = 0; i < checked.size(); i++) {
if (checked.valueAt(i)) {
toDelete.add(getItemAdapter().getItem(checked.keyAt(i)));
}
}
deleteItems(toDelete);
processed = true;
processed = true;
break;
case R.id.activity_action_export:
List<String> paths = new ArrayList<>();
for(int i = 0; i< checked.size(); i++) {
for (int i = 0; i < checked.size(); i++) {
if (checked.valueAt(i)) {
BaseActivitySummary item = getItemAdapter().getItem(checked.keyAt(i));
@ -349,7 +262,7 @@ public class ActivitySummariesActivity extends AbstractListActivity<BaseActivity
processed = true;
break;
case R.id.activity_action_select_all:
for ( int i=0; i < getItemListView().getCount(); i++) {
for (int i = 0; i < getItemListView().getCount(); i++) {
getItemListView().setItemChecked(i, true);
}
return true; //don't finish actionmode in this case!
@ -358,7 +271,7 @@ public class ActivitySummariesActivity extends AbstractListActivity<BaseActivity
for (int i = 0; i < checked.size(); i++) {
if (checked.valueAt(i)) {
BaseActivitySummary item = getItemAdapter().getItem(checked.keyAt(i));
if (item != null) {
if (item != null && item.getId() != null) {
ActivitySummary summary = item;
Long id = summary.getId();
toFilter.add(id);
@ -403,16 +316,17 @@ public class ActivitySummariesActivity extends AbstractListActivity<BaseActivity
activityKindMap = fillKindMap();
}
private LinkedHashMap fillKindMap(){
LinkedHashMap<String , Integer> newMap = new LinkedHashMap<>(1); //reset
private LinkedHashMap fillKindMap() {
LinkedHashMap<String, Integer> newMap = new LinkedHashMap<>(0); //reset
newMap.put(getString(R.string.activity_summaries_all_activities), 0);
for (BaseActivitySummary item : getItemAdapter().getItems()) {
String activityName = ActivityKind.asString(item.getActivityKind(), this);
if (!newMap.containsKey(activityName)) {
if (!newMap.containsKey(activityName) && item.getActivityKind() != 0) {
newMap.put(activityName, item.getActivityKind());
}
}
return newMap;
@ -442,9 +356,13 @@ public class ActivitySummariesActivity extends AbstractListActivity<BaseActivity
}
private void deleteItems(List<BaseActivitySummary> items) {
for(BaseActivitySummary item : items) {
item.delete();
getItemAdapter().remove(item);
for (BaseActivitySummary item : items) {
try {
item.delete();
getItemAdapter().remove(item);
} catch (Exception e) {
//pass delete error
}
}
refresh();
}
@ -460,15 +378,15 @@ public class ActivitySummariesActivity extends AbstractListActivity<BaseActivity
}
}
private void shareMultiple(List<String> paths){
private void shareMultiple(List<String> paths) {
ArrayList<Uri> uris = new ArrayList<>();
for(String path: paths){
for (String path : paths) {
File file = new File(path);
uris.add(FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".screenshot_provider", file));
}
if(uris.size() > 0) {
if (uris.size() > 0) {
final Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
intent.setType("application/gpx+xml");
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
@ -479,13 +397,6 @@ public class ActivitySummariesActivity extends AbstractListActivity<BaseActivity
}
public static int getBackgroundColor(Context context) {
TypedValue typedValue = new TypedValue();
Resources.Theme theme = context.getTheme();
theme.resolveAttribute(R.attr.sports_activity_summary_background, typedValue, true);
return typedValue.data;
}
private void showActivityDetail(int position) {
Intent ActivitySummaryDetailIntent = new Intent(this, ActivitySummaryDetail.class);
Bundle bundle = new Bundle();
@ -497,6 +408,7 @@ public class ActivitySummariesActivity extends AbstractListActivity<BaseActivity
bundle.putLong("dateFromFilter", dateFromFilter);
bundle.putLong("dateToFilter", dateToFilter);
bundle.putLong("deviceFilter", deviceFilter);
bundle.putLong("initial_deviceFilter", getDeviceId(mGBDevice));
bundle.putString("nameContainsFilter", nameContainsFilter);
ActivitySummaryDetailIntent.putExtras(bundle);
@ -513,6 +425,7 @@ public class ActivitySummariesActivity extends AbstractListActivity<BaseActivity
bundle.putLong("dateFromFilter", dateFromFilter);
bundle.putLong("dateToFilter", dateToFilter);
bundle.putLong("deviceFilter", deviceFilter);
bundle.putLong("initial_deviceFilter", getDeviceId(mGBDevice));
bundle.putString("nameContainsFilter", nameContainsFilter);
filterIntent.putExtras(bundle);
startActivityForResult(filterIntent, ACTIVITY_FILTER);

View File

@ -24,6 +24,7 @@ import android.graphics.LightingColorFilter;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Pair;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
@ -52,12 +53,15 @@ import java.util.Objects;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.adapter.SpinnerWithIconAdapter;
import nodomain.freeyourgadget.gadgetbridge.adapter.SpinnerWithIconItem;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
@ -76,7 +80,7 @@ public class ActivitySummariesFilter extends AbstractGBActivity {
long deviceFilter;
long initial_deviceFilter;
int BACKGROUND_COLOR;
LinkedHashMap<String, Long> allDevices;
LinkedHashMap<String, Pair<Long, Integer>> allDevices;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -88,7 +92,8 @@ public class ActivitySummariesFilter extends AbstractGBActivity {
activityFilter = bundle.getInt("activityFilter", 0);
dateFromFilter = bundle.getLong("dateFromFilter", 0);
dateToFilter = bundle.getLong("dateToFilter", 0);
initial_deviceFilter = deviceFilter = bundle.getLong("deviceFilter", 0);
initial_deviceFilter = bundle.getLong("initial_deviceFilter", 0);
deviceFilter = bundle.getLong("deviceFilter", 0);
nameContainsFilter = bundle.getString("nameContainsFilter");
Context appContext = this.getApplicationContext();
@ -101,26 +106,40 @@ public class ActivitySummariesFilter extends AbstractGBActivity {
//device filter spinner
final Spinner deviceFilterSpinner = findViewById(R.id.select_device);
ArrayList<String> filterDevicesArray = new ArrayList<String>(allDevices.keySet());
final ArrayAdapter<String> filterDevicesAdapter = new ArrayAdapter<String>(this,
R.layout.simple_spinner_item_themed, filterDevicesArray);
ArrayList<SpinnerWithIconItem> filterDevicesArray = new ArrayList<>();
for (Map.Entry<String, Pair<Long, Integer>> item : allDevices.entrySet()) {
filterDevicesArray.add(new SpinnerWithIconItem(item.getKey(), item.getValue().first, item.getValue().second));
}
final SpinnerWithIconAdapter filterDevicesAdapter = new SpinnerWithIconAdapter(this,
R.layout.spinner_with_image_layout, R.id.spinner_item_text, filterDevicesArray);
deviceFilterSpinner.setAdapter(filterDevicesAdapter);
deviceFilterSpinner.setSelection(filterDevicesAdapter.getPosition(getDeviceById(deviceFilter)));
deviceFilterSpinner.setSelection(filterDevicesAdapter.getItemPositionForSelection(getDeviceById(deviceFilter)));
addListenerOnSpinnerDeviceSelection();
//Kind filter spinner - assign data, set selected item...
final Spinner filterKindSpinner = findViewById(R.id.select_kind);
ArrayList<String> kindArray = new ArrayList<>(activityKindMap.keySet());
//ensure that all items is always first in the list
kindArray.remove(getString(R.string.activity_summaries_all_activities));
kindArray.add(0, getString(R.string.activity_summaries_all_activities));
ArrayList<SpinnerWithIconItem> kindArray = new ArrayList<>();
ArrayAdapter<String> filterKindAdapter = new ArrayAdapter<String>(this,
R.layout.simple_spinner_item_themed, kindArray);
filterKindSpinner.setAdapter(filterKindAdapter);
filterKindSpinner.setSelection(filterKindAdapter.getPosition(getKindByValue(activityFilter)));
for (Map.Entry<String, Integer> item : activityKindMap.entrySet()) {
if (item.getValue() == 0) continue; //do not put here All devices, but we do need them in the array
kindArray.add(new SpinnerWithIconItem(item.getKey(), new Long(item.getValue()), ActivityKind.getIconId(item.getValue())));
}
//ensure that all items is always first in the list, this is an issue on old android
SpinnerWithIconItem allActivities = new SpinnerWithIconItem(getString(R.string.activity_summaries_all_activities), new Long(0), ActivityKind.getIconId(0));
kindArray.add(0, allActivities);
SpinnerWithIconAdapter adapter = new SpinnerWithIconAdapter(this,
R.layout.spinner_with_image_layout, R.id.spinner_item_text, kindArray);
SpinnerWithIconItem selectedActivity = getKindByValue(activityFilter);
int selectedPosition = adapter.getItemPositionForSelection(selectedActivity);
filterKindSpinner.setAdapter(adapter);
filterKindSpinner.setSelection(selectedPosition);
addListenerOnSpinnerKindSelection();
//quick date filter selection
final Spinner quick_filter_period_select = findViewById(R.id.quick_filter_period_select);
ArrayList<String> quickDateArray = new ArrayList<>(activityKindMap.keySet());
@ -168,8 +187,7 @@ public class ActivitySummariesFilter extends AbstractGBActivity {
nameContainsFilter = "";
filterKindSpinner.setSelection(0);
itemsFilter = null;
deviceFilter = initial_deviceFilter;
deviceFilterSpinner.setSelection(filterDevicesAdapter.getPosition(getDeviceById(deviceFilter)));
deviceFilterSpinner.setSelection(filterDevicesAdapter.getItemPositionForSelection(getDeviceById(initial_deviceFilter)));
quick_filter_period_select.setSelection(0);
update_filter_fields();
}
@ -366,19 +384,20 @@ public class ActivitySummariesFilter extends AbstractGBActivity {
private LinkedHashMap getAllDevices(Context appContext) {
DaoSession daoSession;
GBApplication gbApp = (GBApplication) appContext;
LinkedHashMap<String, Long> newMap = new LinkedHashMap<>(1);
LinkedHashMap<String, Pair<Long, Integer>> newMap = new LinkedHashMap<>(1);
List<? extends GBDevice> devices = gbApp.getDeviceManager().getDevices();
newMap.put(getString(R.string.activity_summaries_all_devices), ALL_DEVICES);
newMap.put(getString(R.string.activity_summaries_all_devices), new Pair(ALL_DEVICES, R.drawable.ic_device_default_disabled));
try (DBHandler handler = GBApplication.acquireDB()) {
daoSession = handler.getDaoSession();
for (GBDevice device : devices) {
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(device);
Device dbDevice = DBHelper.findDevice(device, daoSession);
int icon = device.isInitialized() ? device.getType().getIcon() : device.getType().getDisabledIcon();
if (dbDevice != null && coordinator != null
&& coordinator.supportsActivityTracks()
&& !newMap.containsKey(device.getAliasOrName())) {
newMap.put(device.getAliasOrName(), dbDevice.getId());
newMap.put(device.getAliasOrName(), new Pair(dbDevice.getId(), icon));
}
}
@ -388,19 +407,23 @@ public class ActivitySummariesFilter extends AbstractGBActivity {
return newMap;
}
public String getKindByValue(Integer value) {
public SpinnerWithIconItem getKindByValue(Integer value) {
for (Map.Entry<String, Integer> entry : activityKindMap.entrySet()) {
if (Objects.equals(value, entry.getValue())) {
return entry.getKey();
return new SpinnerWithIconItem(entry.getKey(),
new Long(entry.getValue()),
ActivityKind.getIconId(entry.getValue()));
}
}
return null;
}
public String getDeviceById(long id) {
for (Map.Entry<String, Long> device : allDevices.entrySet()) {
if (Objects.equals(id, device.getValue())) {
return device.getKey();
public SpinnerWithIconItem getDeviceById(long id) {
for (Map.Entry<String, Pair<Long, Integer>> device : allDevices.entrySet()) {
if (Objects.equals(id, device.getValue().first)) {
return new SpinnerWithIconItem(device.getKey(),
device.getValue().first,
device.getValue().second);
}
}
return null;
@ -409,7 +432,9 @@ public class ActivitySummariesFilter extends AbstractGBActivity {
public class CustomOnKindSelectedListener implements AdapterView.OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
activityFilter = activityKindMap.get(parent.getItemAtPosition(pos));
SpinnerWithIconItem selectedItem = (SpinnerWithIconItem) parent.getItemAtPosition(pos);
String activity = selectedItem.getText();
activityFilter = activityKindMap.get(activity);
update_filter_fields();
}
@ -423,7 +448,8 @@ public class ActivitySummariesFilter extends AbstractGBActivity {
public class CustomOnDeviceSelectedListener implements AdapterView.OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
deviceFilter = allDevices.get(parent.getItemAtPosition(pos));
SpinnerWithIconItem selectedItem = (SpinnerWithIconItem) parent.getItemAtPosition(pos);
deviceFilter = selectedItem.getId();
update_filter_fields();
}

View File

@ -475,7 +475,10 @@ public class ActivitySummaryDetail extends AbstractGBActivity {
}
private void show_hide_gpx_menu() {
final String gpxTrack = currentItem.getGpxTrack();
String gpxTrack = null;
if (currentItem != null) {
gpxTrack = currentItem.getGpxTrack();
}
if (gpxTrack == null) {
mOptionsMenu.findItem(R.id.activity_detail_overflowMenu).getSubMenu().findItem(R.id.activity_action_share_gpx).setVisible(false);
} else {

View File

@ -302,7 +302,7 @@ public class ActivityListingAdapter extends AbstractActivityListingAdapter<Activ
}
@Override
protected boolean isSummary(ActivitySession item) {
protected boolean isSummary(ActivitySession item, int position) {
int sessionType = item.getSessionType();
return sessionType == SESSION_SUMMARY;
}

View File

@ -35,7 +35,6 @@ import java.util.ArrayList;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.StepAnalysis;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySession;
/**
@ -75,7 +74,7 @@ public abstract class AbstractActivityListingAdapter<T> extends ArrayAdapter<T>
public View getView(int position, View view, ViewGroup parent) {
T item = getItem(position);
if (isSummary(item)) {
if (isSummary(item, position)) {
view = fill_dashboard(item, position, view, parent, context);
} else {
view = fill_item(item, position, view, parent);
@ -168,7 +167,7 @@ public abstract class AbstractActivityListingAdapter<T> extends ArrayAdapter<T>
}
activityIcon.setImageResource(getIcon(item));
if (zebraStripes && position % 2 == 0) {
if (zebraStripes && position % 2 != 0) {
parentLayout.setBackgroundColor(alternateColor);
}
@ -212,7 +211,7 @@ public abstract class AbstractActivityListingAdapter<T> extends ArrayAdapter<T>
protected abstract boolean hasTotalSteps(T item);
protected abstract boolean isSummary(T item);
protected abstract boolean isSummary(T item, int position);
protected abstract boolean isEmptySummary(T item);

View File

@ -18,11 +18,20 @@ package nodomain.freeyourgadget.gadgetbridge.adapter;
import android.content.Context;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.Calendar;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
@ -37,12 +46,14 @@ import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummaryDao;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryJsonSummary;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import static nodomain.freeyourgadget.gadgetbridge.activities.ActivitySummariesFilter.ALL_DEVICES;
public class ActivitySummariesAdapter extends AbstractActivityListingAdapter<BaseActivitySummary> {
protected static final Logger LOG = LoggerFactory.getLogger(ActivitySummariesAdapter.class);
private final GBDevice device;
long dateFromFilter = 0;
long dateToFilter = 0;
@ -105,7 +116,11 @@ public class ActivitySummariesAdapter extends AbstractActivityListingAdapter<Bas
qb.where(
BaseActivitySummaryDao.Properties.Id.in(itemsFilter));
}
List<BaseActivitySummary> allSummaries = qb.build().list();
List<BaseActivitySummary> allSummaries = new ArrayList<>();
allSummaries.add(new BaseActivitySummary());
allSummaries.addAll(qb.build().list());
setItems(allSummaries, true);
} catch (Exception e) {
GB.toast("Error loading activity summaries.", Toast.LENGTH_SHORT, GB.ERROR, e);
@ -136,9 +151,96 @@ public class ActivitySummariesAdapter extends AbstractActivityListingAdapter<Bas
this.deviceFilter = device;
}
public int gettActivityKindFilter() {
return this.activityKindFilter;
}
@Override
protected View fill_dashboard(BaseActivitySummary item, int position, View view, ViewGroup parent, Context context) {
return null;
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.activity_summary_dashboard_item, parent, false);
double durationSum = 0;
double caloriesBurntSum = 0;
double distanceSum = 0;
double activeSecondsSum = 0;
double firstItemDate = 0;
double lastItemDate = 0;
int activitiesCount = getCount() - 1;
int activityIcon = 0;
boolean activitySame = true;
TextView durationSumView = view.findViewById(R.id.summary_dashboard_layout_duration_label);
TextView caloriesBurntSumView = view.findViewById(R.id.summary_dashboard_layout_calories_label);
TextView distanceSumView = view.findViewById(R.id.summary_dashboard_layout_distance_label);
TextView activeSecondsSumView = view.findViewById(R.id.summary_dashboard_layout_active_duration_label);
TextView timeStartView = view.findViewById(R.id.summary_dashboard_layout_from_label);
TextView timeEndView = view.findViewById(R.id.summary_dashboard_layout_to_label);
TextView activitiesCountView = view.findViewById(R.id.summary_dashboard_layout_count_label);
TextView activityKindView = view.findViewById(R.id.summary_dashboard_layout_activity_label);
ImageView activityIconView = view.findViewById(R.id.summary_dashboard_layout_activity_icon);
ImageView activityIconBigView = view.findViewById(R.id.summary_dashboard_layout_big_activity_icon);
for (BaseActivitySummary sportitem : getItems()) {
if (sportitem.getStartTime() == null) continue; //first item is empty, for dashboard
if (firstItemDate == 0) firstItemDate = sportitem.getStartTime().getTime();
lastItemDate = sportitem.getEndTime().getTime();
durationSum += sportitem.getEndTime().getTime() - sportitem.getStartTime().getTime();
if (activityIcon == 0) {
activityIcon = sportitem.getActivityKind();
} else {
if (activityIcon != sportitem.getActivityKind()) {
activitySame = false;
}
}
ActivitySummaryJsonSummary activitySummaryJsonSummary = new ActivitySummaryJsonSummary(sportitem);
JSONObject summarySubdata = activitySummaryJsonSummary.getSummaryData();
if (summarySubdata != null) {
try {
if (summarySubdata.has("caloriesBurnt")) {
caloriesBurntSum += summarySubdata.getJSONObject("caloriesBurnt").getDouble("value");
}
if (summarySubdata.has("distanceMeters")) {
distanceSum += summarySubdata.getJSONObject("distanceMeters").getDouble("value");
}
if (summarySubdata.has("activeSeconds")) {
activeSecondsSum += summarySubdata.getJSONObject("activeSeconds").getDouble("value");
}
} catch (JSONException e) {
LOG.error("SportsActivity", e);
}
}
}
DecimalFormat df = new DecimalFormat("#.##");
durationSumView.setText(String.format("%s", DateTimeUtils.formatDurationHoursMinutes((long) durationSum, TimeUnit.MILLISECONDS)));
caloriesBurntSumView.setText(String.format("%s %s", (long) caloriesBurntSum, context.getString(R.string.calories_unit)));
distanceSumView.setText(String.format("%s %s", df.format(distanceSum / 1000), context.getString(R.string.km)));
activeSecondsSumView.setText(String.format("%s", DateTimeUtils.formatDurationHoursMinutes((long) activeSecondsSum, TimeUnit.SECONDS)));
activitiesCountView.setText(String.valueOf(activitiesCount));
String activityName = context.getString(R.string.activity_summaries_all_activities);
if (gettActivityKindFilter() != 0) {
activityName = ActivityKind.asString(gettActivityKindFilter(), context);
activityIconView.setImageResource(ActivityKind.getIconId(gettActivityKindFilter()));
activityIconBigView.setImageResource(ActivityKind.getIconId(gettActivityKindFilter()));
} else {
if (activitySame) {
activityIconView.setImageResource(ActivityKind.getIconId(activityIcon));
activityIconBigView.setImageResource(ActivityKind.getIconId(activityIcon));
}
}
activityKindView.setText(activityName);
//start and end are inverted when filer not applied, because items are sorted the other way
timeStartView.setText((dateFromFilter != 0) ? DateTimeUtils.formatDate(new Date(dateFromFilter)) : DateTimeUtils.formatDate(new Date((long) lastItemDate)));
timeEndView.setText((dateToFilter != 0) ? DateTimeUtils.formatDate(new Date(dateToFilter)) : DateTimeUtils.formatDate(new Date((long) firstItemDate)));
return view;
}
@Override
@ -257,8 +359,8 @@ public class ActivitySummariesAdapter extends AbstractActivityListingAdapter<Bas
}
@Override
protected boolean isSummary(BaseActivitySummary item) {
return false;
protected boolean isSummary(BaseActivitySummary item, int position) {
return position == 0;
}
@Override

View File

@ -0,0 +1,62 @@
package nodomain.freeyourgadget.gadgetbridge.adapter;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import nodomain.freeyourgadget.gadgetbridge.R;
public class SpinnerWithIconAdapter extends ArrayAdapter<SpinnerWithIconItem> {
private static final Logger LOG = LoggerFactory.getLogger(SpinnerWithIconAdapter.class);
int groupid;
Activity context;
ArrayList<SpinnerWithIconItem> list;
LayoutInflater inflater;
public SpinnerWithIconAdapter(Activity context, int groupid, int id, ArrayList<SpinnerWithIconItem>
list) {
super(context, id, list);
this.list = list;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.groupid = groupid;
}
public View getView(int position, View convertView, ViewGroup parent) {
View itemView = inflater.inflate(groupid, parent, false);
ImageView imageView = (ImageView) itemView.findViewById(R.id.spinner_item_icon);
imageView.setImageResource(list.get(position).getImageId());
TextView textView = (TextView) itemView.findViewById(R.id.spinner_item_text);
textView.setText(list.get(position).getText());
return itemView;
}
public View getDropDownView(int position, View convertView, ViewGroup
parent) {
return getView(position, convertView, parent);
}
public int getItemPositionForSelection(SpinnerWithIconItem item) {
if (item == null) return -1;
int index = 0;
for (SpinnerWithIconItem listItem : list) {
if (listItem.id.equals(item.id)) {
return index;
}
index++;
}
return -1;
}
}

View File

@ -0,0 +1,32 @@
package nodomain.freeyourgadget.gadgetbridge.adapter;
public class SpinnerWithIconItem {
String text;
Long id;
int imageId;
public SpinnerWithIconItem(String text, Long id, int imageId) {
this.text = text;
this.id = id;
this.imageId = imageId;
}
public String getText() {
return text;
}
public int getImageId() {
return imageId;
}
public Long getId() {
return id;
}
@Override
public String toString() {
return text + " " + id + " " + imageId;
}
}

View File

@ -17,26 +17,27 @@ public class ActivitySummaryItems {
this.itemsAdapter = new ActivitySummariesAdapter(context, device, activityKindFilter, dateFromFilter, dateToFilter, nameContainsFilter, deviceFilter, itemsFilter);
}
public BaseActivitySummary getItem(int position){
current_position=position;
public BaseActivitySummary getItem(int position) {
if (position == 0) return null;
current_position = position;
return itemsAdapter.getItem(position);
}
public int getPosition(BaseActivitySummary item){
public int getPosition(BaseActivitySummary item) {
return itemsAdapter.getPosition(item);
}
public BaseActivitySummary getNextItem(){
if (current_position+1 < itemsAdapter.getCount()){
current_position+=1;
public BaseActivitySummary getNextItem() {
if (current_position + 1 < itemsAdapter.getCount()) {
current_position += 1;
return itemsAdapter.getItem(current_position);
}
return null;
}
public BaseActivitySummary getPrevItem(){
if (current_position-1 >= 0){
current_position-=1;
public BaseActivitySummary getPrevItem() {
if (current_position - 1 >= 1) { //0 is empty item for summary dashboard
current_position -= 1;
return itemsAdapter.getItem(current_position);
}
return null;

View File

@ -1,4 +1,4 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="22.62dp" android:height="22.62dp" android:tint="#7E7E7E" android:viewportWidth="22.62" android:viewportHeight="22.62">
<path android:pathData="M11.31 14.975a3.665 3.665 0 0 1-3.665-3.665 3.665 3.665 0 0 1 3.665-3.665 3.665 3.665 0 0 1 3.665 3.665 3.665 3.665 0 0 1-3.665 3.665m4.886-1.643l2.022-2.022-2.022-2.022V6.424h-2.864L11.31 4.402 9.288 6.424H6.424v2.864L4.402 11.31l2.022 2.022v2.864h2.864l2.022 2.022 2.022-2.022h2.864z" android:strokeWidth="2.82858" android:fillColor="#000000"/>
<path android:pathData="M6.715 11.547H8.89l1.273-3.071 1.18 3.353 1.114-1.666h3.963l-0.298 0.847h-3.215l-1.795 2.755-0.978-2.777-0.58 1.468H7.411z" android:strokeWidth="1.63728" android:fillColor="#000000"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:tint="#7E7E7E" android:viewportHeight="24">
<path android:pathData="M12 17.305A5.305 5.305 0 0 1 6.695 12 5.305 5.305 0 0 1 12 6.695 5.305 5.305 0 0 1 17.305 12 5.305 5.305 0 0 1 12 17.305m7.073-2.378L22 12l-2.927-2.927V4.927h-4.146L12 2 9.073 4.927H4.927v4.146L2 12l2.927 2.927v4.146h4.146L12 22l2.927-2.927h4.146z" android:strokeWidth="1.95392" android:fillColor="#000000"/>
<path android:pathData="M5.348 12.344h3.149l1.842-4.446 1.709 4.853 1.612-2.411h5.737l-0.431 1.227h-4.654l-2.598 3.986-1.417-4.019-0.84 2.125h-3.1z" android:strokeWidth="1.131" android:fillColor="#000000"/>
</vector>

View File

@ -0,0 +1,3 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24" android:tint="#7E7E7E">
<path android:fillColor="@android:color/white" android:pathData="M19.48 12.35c-1.57-4.08-7.16-4.3-5.81-10.23 0.1-0.44-0.37-0.78-0.75-0.55C9.29 3.71 6.68 8 8.87 13.62c0.18 0.46-0.36 0.89-0.75 0.59-1.81-1.37-2-3.34-1.84-4.75 0.06-0.52-0.62-0.77-0.91-0.34C4.69 10.16 4 11.84 4 14.37c0.38 5.6 5.11 7.32 6.81 7.54 2.43 0.31 5.06-0.14 6.95-1.87 2.08-1.93 2.84-5.01 1.72-7.69zm-9.28 5.03c1.44-0.35 2.18-1.39 2.38-2.31 0.33-1.43-0.96-2.83-0.09-5.09 0.33 1.87 3.27 3.04 3.27 5.08 0.08 2.53-2.66 4.7-5.56 2.32z"/>
</vector>

View File

@ -0,0 +1,3 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24" android:tint="#7E7E7E">
<path android:fillColor="@android:color/white" android:pathData="M7 11h2v2H7v-2zm14-5v14c0 1.1-0.9 2-2 2H5c-1.11 0-2-0.9-2-2L3.01 6c0-1.1 0.88-2 1.99-2h1V2h2v2h8V2h2v2h1c1.1 0 2 0.9 2 2zM5 8h14V6H5v2zm14 12V10H5v10h14zm-4-7h2v-2h-2v2zm-4 0h2v-2h-2v2z"/>
</vector>

View File

@ -0,0 +1,3 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24" android:tint="#7E7E7E">
<path android:fillColor="@android:color/white" android:pathData="M15.07 1.01h-6v2h6v-2zm-4 13h2v-6h-2v6zm8.03-6.62l1.42-1.42c-0.43-0.51-0.9-0.99-1.41-1.41l-1.42 1.42C16.14 4.74 14.19 4 12.07 4c-4.97 0-9 4.03-9 9s4.02 9 9 9 9-4.03 9-9c0-2.11-0.74-4.06-1.97-5.61zm-7.03 12.62c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/>
</vector>

View File

@ -17,7 +17,6 @@
</LinearLayout>
<include layout="@layout/activity_summary_statistics"/>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/list_activity_swipe_layout"

View File

@ -0,0 +1,470 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/list_item_parent_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--
android:background="?android:attr/activatedBackgroundIndicator"
-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="0dp"
android:baselineAligned="false"
android:gravity="center"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/summary_dashboard_layout_big_activity_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/summary_dashboard_layout_big_activity_icon"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center"
android:contentDescription="@string/candidate_item_device_image"
app:srcCompat="@drawable/ic_activity_unknown_small" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:layout_marginBottom="5dp"
android:baselineAligned="false"
android:gravity="center"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/summary_dashboard_layout_distance"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/summary_dashboard_layout_distance_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:contentDescription="@string/candidate_item_device_image"
app:srcCompat="@drawable/ic_distance" />
<TextView
android:id="@+id/summary_dashboard_layout_distance_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="@string/distance"
android:textAllCaps="true"
android:textColor="@color/accent"
android:textStyle="bold" />
<TextView
android:id="@+id/summary_dashboard_layout_distance_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="15000"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/summary_dashboard_layout_calories"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="bottom|center"
android:orientation="vertical">
<ImageView
android:id="@+id/summary_dashboard_layout_calories_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center"
android:contentDescription="@string/candidate_item_device_image"
app:srcCompat="@drawable/ic_calories" />
<TextView
android:id="@+id/summary_dashboard_layout_calories_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="@string/caloriesBurnt"
android:textAllCaps="true"
android:textColor="@color/accent"
android:textStyle="bold" />
<TextView
android:id="@+id/summary_dashboard_layout_calories_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="30000"
android:textSize="18sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:baselineAligned="false"
android:gravity="bottom|center"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/summary_dashboard_layout_duration"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center|top"
android:orientation="vertical">
<ImageView
android:id="@+id/summary_dashboard_layout_duration_icon"
android:layout_width="19dp"
android:layout_height="19dp"
android:layout_gravity="center"
android:contentDescription="@string/candidate_item_device_image"
app:srcCompat="@drawable/ic_timer" />
<TextView
android:id="@+id/summary_dashboard_layout_duration_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="@string/activity_detail_duration_label"
android:textAllCaps="true"
android:textColor="@color/accent"
android:textStyle="bold" />
<TextView
android:id="@+id/summary_dashboard_layout_duration_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="1d 20h 35m"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/summary_dashboard_layout_active_duration"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center|top"
android:orientation="vertical">
<ImageView
android:id="@+id/summary_dashboard_layout_active_duration_icon"
android:layout_width="19dp"
android:layout_height="19dp"
android:layout_gravity="center"
android:contentDescription="@string/candidate_item_device_image"
app:srcCompat="@drawable/ic_timer" />
<TextView
android:id="@+id/summary_dashboard_layout_active_duration_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="@string/activity_list_summary_active_time"
android:textAllCaps="true"
android:textColor="@color/accent"
android:textStyle="bold" />
<TextView
android:id="@+id/summary_dashboard_layout_active_duration_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="1d 13h 30m"
android:textSize="18sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:baselineAligned="false"
android:gravity="center"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/summary_dashboard_layout_activity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/summary_dashboard_layout_activity_icon"
android:layout_width="19dp"
android:layout_height="19dp"
android:layout_gravity="center"
android:contentDescription="@string/candidate_item_device_image"
app:srcCompat="@drawable/ic_activity_unknown_small" />
<TextView
android:id="@+id/summary_dashboard_layout_activity_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="@string/Activity"
android:textAllCaps="true"
android:textColor="@color/accent"
android:textStyle="bold" />
<TextView
android:id="@+id/summary_dashboard_layout_activity_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="All Activities"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/summary_dashboard_layout_count"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/summary_dashboard_layout_count_icon"
android:layout_width="19dp"
android:layout_height="19dp"
android:layout_gravity="center"
android:contentDescription="@string/candidate_item_device_image"
app:srcCompat="@drawable/ic_activity_stacked" />
<TextView
android:id="@+id/summary_dashboard_layout_count_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="@string/activity_list_summary_activities"
android:textAllCaps="true"
android:textColor="@color/accent"
android:textStyle="bold" />
<TextView
android:id="@+id/summary_dashboard_layout_count_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="15"
android:textSize="18sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:baselineAligned="false"
android:gravity="bottom|center"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/summary_dashboard_layout_from"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center|top"
android:orientation="vertical">
<ImageView
android:id="@+id/summary_dashboard_layout_from_icon"
android:layout_width="19dp"
android:layout_height="19dp"
android:layout_gravity="center"
android:contentDescription="@string/candidate_item_device_image"
app:srcCompat="@drawable/ic_date_range" />
<TextView
android:id="@+id/summary_dashboard_layout_from_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="@string/activity_filter_date_from"
android:textAllCaps="true"
android:textColor="@color/accent"
android:textStyle="bold" />
<TextView
android:id="@+id/summary_dashboard_layout_from_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="January 1, 1970"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/summary_dashboard_layout_to"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center|top"
android:layout_marginStart="1dp"
android:layout_marginEnd="1dp"
android:layout_weight="1"
android:gravity="center|top"
android:orientation="vertical">
<ImageView
android:id="@+id/summary_dashboard_layout_to_icon"
android:layout_width="19dp"
android:layout_height="19dp"
android:layout_gravity="center"
android:contentDescription="@string/candidate_item_device_image"
app:srcCompat="@drawable/ic_date_range" />
<TextView
android:id="@+id/summary_dashboard_layout_to_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:maxLines="2"
android:scrollHorizontally="false"
android:text="@string/activity_filter_date_to"
android:textAllCaps="true"
android:textColor="@color/accent"
android:textStyle="bold" />
<TextView
android:id="@+id/summary_dashboard_layout_to_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-black"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="December 1, 2020"
android:textSize="18sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View File

@ -1,202 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_summary_statistics_relative_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="?android:attr/activatedBackgroundIndicator"
android:clickable="false"
android:focusable="auto"
android:padding="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="vertical"
android:paddingStart="8dp"
android:paddingEnd="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/activity_stats_timeFrom_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:fontFamily="sans-serif-black"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="@string/activity_filter_date_from"
android:textAlignment="textStart"
android:textSize="18sp" />
<TextView
android:id="@+id/activity_stats_timeFrom_value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:fontFamily="sans-serif-black"
android:maxLines="1"
android:scrollHorizontally="false"
android:textAlignment="textEnd"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/activity_stats_timeTo_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:fontFamily="sans-serif-black"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="@string/activity_filter_date_to"
android:textAlignment="textStart"
android:textSize="18sp" />
<TextView
android:id="@+id/activity_stats_timeTo_value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:fontFamily="sans-serif-black"
android:maxLines="1"
android:scrollHorizontally="false"
android:textAlignment="textEnd"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/activity_stats_duration_sum_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:fontFamily="sans-serif-black"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="@string/activity_detail_duration_label"
android:textAlignment="textStart"
android:textSize="18sp" />
<TextView
android:id="@+id/activity_stats_duration_sum_value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:fontFamily="sans-serif-black"
android:maxLines="1"
android:scrollHorizontally="false"
android:textAlignment="textEnd"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/activity_stats_distance_sum_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:fontFamily="sans-serif-black"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="@string/Distance"
android:textAlignment="textStart"
android:textSize="18sp" />
<TextView
android:id="@+id/activity_stats_distance_sum_value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:fontFamily="sans-serif-black"
android:maxLines="1"
android:scrollHorizontally="false"
android:textAlignment="textEnd"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/activity_stats_activeSeconds_sum_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:fontFamily="sans-serif-black"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="@string/activeSeconds"
android:textAlignment="textStart"
android:textSize="18sp" />
<TextView
android:id="@+id/activity_stats_activeSeconds_sum_value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:fontFamily="sans-serif-black"
android:maxLines="1"
android:scrollHorizontally="false"
android:textAlignment="textEnd"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/activity_stats_calories_burnt_sum_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:fontFamily="sans-serif-black"
android:maxLines="1"
android:scrollHorizontally="false"
android:text="@string/caloriesBurnt"
android:textAlignment="textStart"
android:textSize="18sp" />
<TextView
android:id="@+id/activity_stats_calories_burnt_sum_value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:fontFamily="sans-serif-black"
android:maxLines="1"
android:scrollHorizontally="false"
android:textAlignment="textEnd"
android:textSize="18sp" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@android:color/darker_gray" />
</LinearLayout>
</RelativeLayout>

View File

@ -0,0 +1,21 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/spinner_item_icon"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center_horizontal|center_vertical"
android:padding="10dp" />
<TextView
android:id="@+id/spinner_item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:layout_gravity="center_vertical"
>
</TextView>
</LinearLayout>

View File

@ -1,15 +1,16 @@
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/sport_activity_filter_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="15dp">
android:paddingStart="15dp"
android:paddingEnd="15dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Spinner
android:id="@+id/select_device"
android:layout_width="match_parent"
@ -17,8 +18,17 @@
android:gravity="start|center_vertical"
android:spinnerMode="dropdown"
android:textAlignment="gravity" />
<View android:background="#000" android:layout_width="match_parent" android:layout_height="1.5dp"/>
<Space android:background="#000" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="1dp" />
<View
android:layout_width="match_parent"
android:layout_height="1.5dp"
android:background="#000" />
<Space
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="1dp"
android:background="#000" />
<Spinner
android:id="@+id/select_kind"
@ -27,8 +37,17 @@
android:gravity="start|center_vertical"
android:spinnerMode="dropdown"
android:textAlignment="gravity" />
<View android:background="#000" android:layout_width="match_parent" android:layout_height="1.5dp"/>
<Space android:background="#000" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="5dp" />
<View
android:layout_width="match_parent"
android:layout_height="1.5dp"
android:background="#000" />
<Space
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:background="#000" />
<LinearLayout
android:id="@+id/filtername"
@ -42,18 +61,27 @@
<EditText
android:id="@+id/textViewNameData"
android:layout_width="fill_parent"
android:hint="@string/activity_filter_name_contains"
android:layout_height="wrap_content"
android:autofillHints="@string/activity_filter_name_contains"
android:hint="@string/activity_filter_name_contains"
android:inputType="text"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:textAlignment="textStart"
android:textSize="16sp"
android:autofillHints="@string/activity_filter_name_contains" />
android:textSize="16sp" />
</LinearLayout>
<View android:background="#000" android:layout_width="match_parent" android:layout_height="1.5dp"/>
<Space android:background="#000" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="15dp" />
<View
android:layout_width="match_parent"
android:layout_height="1.5dp"
android:background="#000" />
<Space
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:background="#000" />
<LinearLayout
android:id="@+id/filterfrom"
@ -79,14 +107,23 @@
<TextView
android:id="@+id/textViewFromData"
android:hint="@string/activity_filter_from_placeholder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/activity_filter_from_placeholder"
android:textAlignment="textStart"
android:textSize="16sp" />
</LinearLayout>
<View android:background="#000" android:layout_width="match_parent" android:layout_height="1.5dp"/>
<Space android:background="#000" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="15dp" />
<View
android:layout_width="match_parent"
android:layout_height="1.5dp"
android:background="#000" />
<Space
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:background="#000" />
<LinearLayout
android:id="@+id/filterto"
@ -112,14 +149,18 @@
<TextView
android:id="@+id/textViewToData"
android:hint="@string/activity_filter_to_placeholder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/activity_filter_to_placeholder"
android:textAlignment="textStart"
android:textSize="16sp" />
</LinearLayout>
<View android:background="#000" android:layout_width="match_parent" android:layout_height="1.5dp"/>
<View
android:layout_width="match_parent"
android:layout_height="1.5dp"
android:background="#000" />
<Spinner
android:id="@+id/quick_filter_period_select"
@ -128,8 +169,17 @@
android:gravity="start|center_vertical"
android:spinnerMode="dropdown"
android:textAlignment="gravity" />
<View android:background="#000" android:layout_width="match_parent" android:layout_height="1.5dp"/>
<Space android:background="#000" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="15dp" />
<View
android:layout_width="match_parent"
android:layout_height="1.5dp"
android:background="#000" />
<Space
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:background="#000" />
<LinearLayout
android:id="@+id/filteritems"
@ -161,8 +211,17 @@
android:textAlignment="textStart"
android:textSize="16sp" />
</LinearLayout>
<View android:background="#000" android:layout_width="match_parent" android:layout_height="1.5dp"/>
<Space android:background="#000" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="15dp" />
<View
android:layout_width="match_parent"
android:layout_height="1.5dp"
android:background="#000" />
<Space
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:background="#000" />
<Button
android:id="@+id/reset_filter_button"
@ -181,6 +240,5 @@
android:layout_height="wrap_content"
android:text="@string/activity_filter_apply_filter" />
</LinearLayout>
</ScrollView>

View File

@ -8,12 +8,6 @@
android:title="@string/pref_header_filter"
app:iconTint="@color/primarytext_dark"
app:showAsAction="always" />
<item
android:id="@+id/activity_action_calculate_summary_stats"
android:icon="@drawable/ic_calculate"
android:title="@string/pref_header_statistics"
app:iconTint="@color/primarytext_dark"
app:showAsAction="always" />
<item
android:id="@+id/overflowMenu"