diff --git a/src/main/java/de/dennisguse/opentracks/AbstractActivity.java b/src/main/java/de/dennisguse/opentracks/AbstractActivity.java index a98d5a581..c06f4fd81 100644 --- a/src/main/java/de/dennisguse/opentracks/AbstractActivity.java +++ b/src/main/java/de/dennisguse/opentracks/AbstractActivity.java @@ -20,6 +20,7 @@ import android.os.Bundle; import android.speech.tts.TextToSpeech; import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; /** * @author Jimmy Shih @@ -34,6 +35,9 @@ public abstract class AbstractActivity extends AppCompatActivity { setVolumeControlStream(TextToSpeech.Engine.DEFAULT_STREAM); setContentView(getLayoutResId()); + + Toolbar toolbar = findViewById(R.id.toolbar); + setSupportActionBar(toolbar); } /** diff --git a/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java b/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java index 80de8c5bc..9e9ffb2c2 100644 --- a/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/AbstractListActivity.java @@ -16,23 +16,7 @@ package de.dennisguse.opentracks; -import android.app.Activity; -import android.app.SearchManager; -import android.content.ComponentName; -import android.content.Context; import android.content.Intent; -import android.util.Log; -import android.util.SparseBooleanArray; -import android.view.ActionMode; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.widget.AbsListView; -import android.widget.ListView; - -import androidx.appcompat.widget.SearchView; - -import java.util.ArrayList; import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment; import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment.ConfirmDeleteCaller; @@ -57,115 +41,6 @@ public abstract class AbstractListActivity extends AbstractActivity implements C protected static final int GPS_REQUEST_CODE = 6; private static final int DELETE_REQUEST_CODE = 3; - public static void configureListViewContextualMenu(final ListView listView, final ContextualActionModeCallback contextualActionModeCallback) { - listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); - listView.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() { - - @Override - public boolean onCreateActionMode(ActionMode mode, Menu menu) { - mode.getMenuInflater().inflate(R.menu.list_context_menu, menu); - return true; - } - - @Override - public boolean onPrepareActionMode(ActionMode mode, Menu menu) { - contextualActionModeCallback.onPrepare(menu, getCheckedPositions(listView), listView.getCheckedItemIds(), true); - return true; - } - - @Override - public void onDestroyActionMode(ActionMode mode) { - // Do nothing - } - - @Override - public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) { - mode.invalidate(); - } - - @Override - public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - if (contextualActionModeCallback.onClick(item.getItemId(), getCheckedPositions(listView), listView.getCheckedItemIds())) { - mode.finish(); - } - return true; - } - - /** - * Gets the checked positions in a list view. - * - * @param list the list view - */ - private int[] getCheckedPositions(ListView list) { - SparseBooleanArray positions = list.getCheckedItemPositions(); - ArrayList arrayList = new ArrayList<>(); - for (int i = 0; i < positions.size(); i++) { - int key = positions.keyAt(i); - if (positions.valueAt(i)) { - arrayList.add(key); - } - } - int[] result = new int[arrayList.size()]; - for (int i = 0; i < arrayList.size(); i++) { - result[i] = arrayList.get(i); - } - return result; - } - }); - } - - public static void configureSearchWidget(Activity activity, final MenuItem menuItem, final TrackController trackController) { - final SearchView searchView = (SearchView) menuItem.getActionView(); - SearchManager searchManager = (SearchManager) activity.getSystemService(Context.SEARCH_SERVICE); - if (searchManager != null) { - //NOTE: for some reason activity.getComponentName() did not trigger the SearchListActivity - searchView.setSearchableInfo(searchManager.getSearchableInfo(new ComponentName(activity, SearchListActivity.class))); - } else { - Log.w(TAG, "Could not retrieve SearchManager."); - } - searchView.setQueryRefinementEnabled(true); - searchView.setSubmitButtonEnabled(true); - searchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() { - - @Override - public void onFocusChange(View v, boolean hasFocus) { - // Hide and show trackController when searchable widget has focus/no focus - if (trackController != null) { - if (hasFocus) { - trackController.hide(); - } else { - trackController.show(); - } - } - } - }); - - searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { - @Override - public boolean onQueryTextSubmit(String query) { - menuItem.collapseActionView(); - return false; - } - - @Override - public boolean onQueryTextChange(String newText) { - return false; - } - }); - searchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() { - @Override - public boolean onSuggestionSelect(int position) { - return false; - } - - @Override - public boolean onSuggestionClick(int position) { - menuItem.collapseActionView(); - return false; - } - }); - } - @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == DELETE_REQUEST_CODE) { diff --git a/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java b/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java index 649988a1d..086e3e79b 100644 --- a/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/MarkerListActivity.java @@ -46,6 +46,7 @@ import de.dennisguse.opentracks.content.Waypoint.WaypointType; import de.dennisguse.opentracks.content.WaypointsColumns; import de.dennisguse.opentracks.fragments.DeleteMarkerDialogFragment; import de.dennisguse.opentracks.fragments.DeleteMarkerDialogFragment.DeleteMarkerCaller; +import de.dennisguse.opentracks.util.ActivityUtils; import de.dennisguse.opentracks.util.IntentUtils; import de.dennisguse.opentracks.util.ListItemUtils; import de.dennisguse.opentracks.util.PreferencesUtils; @@ -175,7 +176,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker } }; listView.setAdapter(resourceCursorAdapter); - AbstractListActivity.configureListViewContextualMenu(listView, contextualActionModeCallback); + ActivityUtils.configureListViewContextualMenu(listView, contextualActionModeCallback); LoaderManager.getInstance(this).initLoader(0, null, new LoaderCallbacks() { @NonNull @@ -234,7 +235,7 @@ public class MarkerListActivity extends AbstractActivity implements DeleteMarker insertMarkerMenuItem = menu.findItem(R.id.marker_list_insert_marker); searchMenuItem = menu.findItem(R.id.marker_list_search); - AbstractListActivity.configureSearchWidget(this, searchMenuItem, null); + ActivityUtils.configureSearchWidget(this, searchMenuItem, null); return super.onCreateOptionsMenu(menu); } diff --git a/src/main/java/de/dennisguse/opentracks/SearchListActivity.java b/src/main/java/de/dennisguse/opentracks/SearchListActivity.java index 8b81e3a55..a456d2f72 100644 --- a/src/main/java/de/dennisguse/opentracks/SearchListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/SearchListActivity.java @@ -55,6 +55,7 @@ import de.dennisguse.opentracks.fragments.DeleteMarkerDialogFragment; import de.dennisguse.opentracks.fragments.DeleteMarkerDialogFragment.DeleteMarkerCaller; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.stats.TripStatistics; +import de.dennisguse.opentracks.util.ActivityUtils; import de.dennisguse.opentracks.util.IntentUtils; import de.dennisguse.opentracks.util.ListItemUtils; import de.dennisguse.opentracks.util.PreferencesUtils; @@ -223,7 +224,7 @@ public class SearchListActivity extends AbstractListActivity implements DeleteMa startActivity(intent); } }); - AbstractListActivity.configureListViewContextualMenu(listView, contextualActionModeCallback); + ActivityUtils.configureListViewContextualMenu(listView, contextualActionModeCallback); handleIntent(getIntent()); } diff --git a/src/main/java/de/dennisguse/opentracks/TrackController.java b/src/main/java/de/dennisguse/opentracks/TrackController.java index bfa404e13..c461f2f85 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackController.java +++ b/src/main/java/de/dennisguse/opentracks/TrackController.java @@ -130,11 +130,11 @@ public class TrackController { handlerUpdateTotalTime.removeCallbacks(updateTotalTimeRunnable); } - void hide() { + public void hide() { containerView.setVisibility(View.GONE); } - void show() { + public void show() { containerView.setVisibility(View.VISIBLE); } diff --git a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java index 61e712ce8..188ccc312 100644 --- a/src/main/java/de/dennisguse/opentracks/TrackListActivity.java +++ b/src/main/java/de/dennisguse/opentracks/TrackListActivity.java @@ -59,6 +59,7 @@ import de.dennisguse.opentracks.fragments.ConfirmDeleteDialogFragment; import de.dennisguse.opentracks.services.ITrackRecordingService; import de.dennisguse.opentracks.services.TrackRecordingServiceConnection; import de.dennisguse.opentracks.settings.SettingsActivity; +import de.dennisguse.opentracks.util.ActivityUtils; import de.dennisguse.opentracks.util.IntentUtils; import de.dennisguse.opentracks.util.ListItemUtils; import de.dennisguse.opentracks.util.PreferencesUtils; @@ -325,9 +326,8 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe } }; listView.setAdapter(resourceCursorAdapter); - TrackListActivity.this.registerForContextMenu(listView); - AbstractListActivity.configureListViewContextualMenu(listView, contextualActionModeCallback); + ActivityUtils.configureListViewContextualMenu(listView, contextualActionModeCallback); LoaderManager.getInstance(this).initLoader(0, null, loaderCallbacks); showStartupDialogs(); @@ -389,7 +389,7 @@ public class TrackListActivity extends AbstractListActivity implements ConfirmDe getMenuInflater().inflate(R.menu.track_list, menu); searchMenuItem = menu.findItem(R.id.track_list_search); - AbstractListActivity.configureSearchWidget(this, searchMenuItem, trackController); + ActivityUtils.configureSearchWidget(this, searchMenuItem, trackController); startGpsMenuItem = menu.findItem(R.id.track_list_start_gps); aggregatedStatisticsMenuItem = menu.findItem(R.id.track_list_aggregated_statistics); diff --git a/src/main/java/de/dennisguse/opentracks/util/ActivityUtils.java b/src/main/java/de/dennisguse/opentracks/util/ActivityUtils.java new file mode 100644 index 000000000..4fa6b080c --- /dev/null +++ b/src/main/java/de/dennisguse/opentracks/util/ActivityUtils.java @@ -0,0 +1,137 @@ +package de.dennisguse.opentracks.util; + +import android.app.Activity; +import android.app.SearchManager; +import android.content.ComponentName; +import android.content.Context; +import android.util.Log; +import android.util.SparseBooleanArray; +import android.view.ActionMode; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.AbsListView; +import android.widget.ListView; + +import androidx.appcompat.widget.SearchView; + +import java.util.ArrayList; + +import de.dennisguse.opentracks.ContextualActionModeCallback; +import de.dennisguse.opentracks.R; +import de.dennisguse.opentracks.SearchListActivity; +import de.dennisguse.opentracks.TrackController; + +public class ActivityUtils { + + private static final String TAG = ActivityUtils.class.getSimpleName(); + + public static void configureListViewContextualMenu(final ListView listView, final ContextualActionModeCallback contextualActionModeCallback) { + listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); + listView.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() { + + @Override + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + mode.getMenuInflater().inflate(R.menu.list_context_menu, menu); + return true; + } + + @Override + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + contextualActionModeCallback.onPrepare(menu, getCheckedPositions(listView), listView.getCheckedItemIds(), true); + return true; + } + + @Override + public void onDestroyActionMode(ActionMode mode) { + // Do nothing + } + + @Override + public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) { + mode.invalidate(); + } + + @Override + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + if (contextualActionModeCallback.onClick(item.getItemId(), getCheckedPositions(listView), listView.getCheckedItemIds())) { + mode.finish(); + } + return true; + } + + /** + * Gets the checked positions in a list view. + * + * @param list the list view + */ + private int[] getCheckedPositions(ListView list) { + SparseBooleanArray positions = list.getCheckedItemPositions(); + ArrayList arrayList = new ArrayList<>(); + for (int i = 0; i < positions.size(); i++) { + int key = positions.keyAt(i); + if (positions.valueAt(i)) { + arrayList.add(key); + } + } + int[] result = new int[arrayList.size()]; + for (int i = 0; i < arrayList.size(); i++) { + result[i] = arrayList.get(i); + } + return result; + } + }); + } + + public static void configureSearchWidget(Activity activity, final MenuItem menuItem, final TrackController trackController) { + final SearchView searchView = (SearchView) menuItem.getActionView(); + SearchManager searchManager = (SearchManager) activity.getSystemService(Context.SEARCH_SERVICE); + if (searchManager != null) { + //NOTE: for some reason activity.getComponentName() did not trigger the SearchListActivity + searchView.setSearchableInfo(searchManager.getSearchableInfo(new ComponentName(activity, SearchListActivity.class))); + } else { + Log.w(TAG, "Could not retrieve SearchManager."); + } + searchView.setQueryRefinementEnabled(true); + searchView.setSubmitButtonEnabled(true); + searchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() { + + @Override + public void onFocusChange(View v, boolean hasFocus) { + // Hide and show trackController when searchable widget has focus/no focus + if (trackController != null) { + if (hasFocus) { + trackController.hide(); + } else { + trackController.show(); + } + } + } + }); + + searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String query) { + menuItem.collapseActionView(); + return false; + } + + @Override + public boolean onQueryTextChange(String newText) { + return false; + } + }); + searchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() { + @Override + public boolean onSuggestionSelect(int position) { + return false; + } + + @Override + public boolean onSuggestionClick(int position) { + menuItem.collapseActionView(); + return false; + } + }); + } +} diff --git a/src/main/res/layout-land/track_list.xml b/src/main/res/layout-land/track_list.xml index 39e6c4f87..13276df88 100644 --- a/src/main/res/layout-land/track_list.xml +++ b/src/main/res/layout-land/track_list.xml @@ -16,7 +16,10 @@ limitations under the License. + android:baselineAligned="false" + android:orientation="horizontal"> + + diff --git a/src/main/res/layout/about.xml b/src/main/res/layout/about.xml index 2d1e4d09a..841b009e8 100644 --- a/src/main/res/layout/about.xml +++ b/src/main/res/layout/about.xml @@ -4,6 +4,8 @@ android:layout_height="match_parent" android:orientation="vertical"> + + + + + + - + android:layout_height="match_parent" + android:orientation="vertical"> + + - \ No newline at end of file + \ No newline at end of file diff --git a/src/main/res/layout/search_list.xml b/src/main/res/layout/search_list.xml index 76d4a0d65..9cccf8bde 100644 --- a/src/main/res/layout/search_list.xml +++ b/src/main/res/layout/search_list.xml @@ -17,6 +17,8 @@ limitations under the License. android:layout_width="match_parent" android:layout_height="match_parent"> + + + + + + diff --git a/src/main/res/layout/track_detail.xml b/src/main/res/layout/track_detail.xml index e378fc775..16f24f20b 100644 --- a/src/main/res/layout/track_detail.xml +++ b/src/main/res/layout/track_detail.xml @@ -18,6 +18,8 @@ limitations under the License. android:layout_height="match_parent" android:orientation="vertical"> + + + + + + -