diff options
| author | Bananeweizen <bananeweizen@gmx.de> | 2014-05-29 07:32:29 +0200 |
|---|---|---|
| committer | Bananeweizen <bananeweizen@gmx.de> | 2014-05-29 07:32:29 +0200 |
| commit | 47a693cdd3f8fa1b3a807c1481a1bd1464b05a4e (patch) | |
| tree | 27021c495d2e3201e721decab92939166cc163b2 | |
| parent | bad6ee3e4257fc0adc3511453178ebcae4060022 (diff) | |
| download | cgeo-47a693cdd3f8fa1b3a807c1481a1bd1464b05a4e.zip cgeo-47a693cdd3f8fa1b3a807c1481a1bd1464b05a4e.tar.gz cgeo-47a693cdd3f8fa1b3a807c1481a1bd1464b05a4e.tar.bz2 | |
new: contextual action bar for cache details and trackable
This is surely not complete (as we still use other local context menus
in the same actions), but a start for converting all context menus to
contextual action bars.
| -rw-r--r-- | main/res/drawable-mdpi/ic_menu_copy.png | bin | 0 -> 758 bytes | |||
| -rw-r--r-- | main/res/menu/details_context.xml | 19 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/CacheDetailActivity.java | 144 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/TrackableActivity.java | 118 | ||||
| -rw-r--r-- | main/src/cgeo/geocaching/activity/AbstractActivity.java | 15 |
5 files changed, 193 insertions, 103 deletions
diff --git a/main/res/drawable-mdpi/ic_menu_copy.png b/main/res/drawable-mdpi/ic_menu_copy.png Binary files differnew file mode 100644 index 0000000..eee5540 --- /dev/null +++ b/main/res/drawable-mdpi/ic_menu_copy.png diff --git a/main/res/menu/details_context.xml b/main/res/menu/details_context.xml index 53f326a..fc61d5d 100644 --- a/main/res/menu/details_context.xml +++ b/main/res/menu/details_context.xml @@ -1,27 +1,34 @@ <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:cgeo="http://schemas.android.com/apk/res-auto"> + xmlns:cgeo="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/menu_copy" - android:title="@android:string/copy"> + android:icon="@drawable/ic_menu_copy" + android:title="@android:string/copy" + cgeo:showAsAction="always|withText"> </item> <item android:id="@+id/menu_translate_to_sys_lang" - android:title="@string/translate_to_sys_lang"> + android:title="@string/translate_to_sys_lang" + cgeo:showAsAction="ifRoom"> </item> <item android:id="@+id/menu_translate_to_english" - android:title="@string/translate_to_english"> + android:title="@string/translate_to_english" + cgeo:showAsAction="ifRoom"> </item> <item android:id="@+id/menu_cache_share_field" - android:title="@string/cache_share_field"> + android:title="@string/cache_share_field" + cgeo:showAsAction="ifRoom"> </item> <item android:id="@+id/menu_calendar" + android:icon="@drawable/ic_menu_my_calendar" android:title="@string/cache_menu_event" - android:visible="false"> + android:visible="false" + cgeo:showAsAction="ifRoom"> </item> </menu>
\ No newline at end of file diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index 9b17377..ea02171 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -84,6 +84,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v4.app.FragmentManager; +import android.support.v7.view.ActionMode; import android.text.Editable; import android.text.Html; import android.text.Spannable; @@ -97,6 +98,7 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; +import android.view.View.OnLongClickListener; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.ViewParent; @@ -336,49 +338,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc super.onCreateContextMenu(menu, view, info); final int viewId = view.getId(); switch (viewId) { - case R.id.value: // coordinates, gc-code, name - assert view instanceof TextView; - clickedItemText = ((TextView) view).getText(); - final CharSequence itemTitle = ((TextView) ((View) view.getParent()).findViewById(R.id.name)).getText(); - buildDetailsContextMenu(menu, clickedItemText, itemTitle, true); - break; - case R.id.shortdesc: - assert view instanceof TextView; - clickedItemText = ((TextView) view).getText(); - buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_description), false); - break; - case R.id.longdesc: - assert view instanceof TextView; - // combine short and long description - final String shortDesc = cache.getShortDescription(); - if (StringUtils.isBlank(shortDesc)) { - clickedItemText = ((TextView) view).getText(); - } else { - clickedItemText = shortDesc + "\n\n" + ((TextView) view).getText(); - } - buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_description), false); - break; - case R.id.personalnote: - assert view instanceof TextView; - clickedItemText = ((TextView) view).getText(); - buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_personal_note), true); - break; - case R.id.hint: - assert view instanceof TextView; - clickedItemText = ((TextView) view).getText(); - buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_hint), false); - break; - case R.id.log: - assert view instanceof TextView; - clickedItemText = ((TextView) view).getText(); - buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_logs), false); - break; - case R.id.date: // event date - assert view instanceof TextView; - clickedItemText = ((TextView) view).getText(); - buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_event), true); - menu.findItem(R.id.menu_calendar).setVisible(cache.canBeAddedToCalendar()); - break; case R.id.waypoint: menu.setHeaderTitle(selectedWaypoint.getName() + " (" + res.getString(R.string.waypoint) + ")"); getMenuInflater().inflate(R.menu.waypoint_options, menu); @@ -405,9 +364,6 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc @Override public boolean onContextItemSelected(MenuItem item) { - if (onClipboardItemSelected(item, clickedItemText)) { - return true; - } switch (item.getItemId()) { // waypoints case R.id.menu_waypoint_edit: @@ -913,10 +869,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc span.setSpan(new ForegroundColorSpan(res.getColor(R.color.archived_cache_color)), 0, span.toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } - registerForContextMenu(details.add(R.string.cache_name, span)); + addContextMenu(details.add(R.string.cache_name, span)); details.add(R.string.cache_type, cache.getType().getL10n()); details.addSize(cache); - registerForContextMenu(details.add(R.string.cache_geocode, cache.getGeocode())); + addContextMenu(details.add(R.string.cache_geocode, cache.getGeocode())); details.addCacheState(cache); details.addDistance(cache, cacheDistanceView); @@ -950,7 +906,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc // hidden or event date final TextView hiddenView = details.addHiddenDate(cache); if (hiddenView != null) { - registerForContextMenu(hiddenView); + addContextMenu(hiddenView); } // cache location @@ -962,7 +918,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc if (cache.getCoords() != null) { final TextView valueView = details.add(R.string.cache_coordinates, cache.getCoords().toString()); valueView.setOnClickListener(new CoordinatesFormatSwitcher(cache.getCoords())); - registerForContextMenu(valueView); + addContextMenu(valueView); } // cache attributes @@ -1422,7 +1378,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc // cache personal note setPersonalNote(personalNoteView, cache.getPersonalNote()); personalNoteView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); - registerForContextMenu(personalNoteView); + addContextMenu(personalNoteView); final Button personalNoteEdit = (Button) view.findViewById(R.id.edit_personalnote); personalNoteEdit.setOnClickListener(new View.OnClickListener() { @Override @@ -1473,7 +1429,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc hintView.setOnClickListener(new DecryptTextClickListener(hintView)); hintBoxView.setOnClickListener(new DecryptTextClickListener(hintView)); hintBoxView.setClickable(true); - registerForContextMenu(hintView); + addContextMenu(hintView); } else { hintView.setVisibility(View.GONE); hintView.setClickable(false); @@ -1643,7 +1599,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc descriptionView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); fixTextColor(descriptionString); descriptionView.setVisibility(View.VISIBLE); - registerForContextMenu(descriptionView); + addContextMenu(descriptionView); } } @@ -1807,7 +1763,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc } }); - registerForContextMenu(rowView); + addContextMenu(rowView); rowView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -1896,6 +1852,86 @@ public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailAc context.startActivity(cachesIntent); } + public void addContextMenu(final View view) { + view.setOnLongClickListener(new OnLongClickListener() { + + @Override + public boolean onLongClick(View v) { + startSupportActionMode(new ActionMode.Callback() { + + @Override + public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { + switch (view.getId()) { + case R.id.value: // coordinates, gc-code, name + assert view instanceof TextView; + clickedItemText = ((TextView) view).getText(); + final CharSequence itemTitle = ((TextView) ((View) view.getParent()).findViewById(R.id.name)).getText(); + buildDetailsContextMenu(actionMode, menu, clickedItemText, itemTitle, true); + return true; + case R.id.shortdesc: + assert view instanceof TextView; + clickedItemText = ((TextView) view).getText(); + buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_description), false); + return true; + case R.id.longdesc: + assert view instanceof TextView; + // combine short and long description + final String shortDesc = cache.getShortDescription(); + if (StringUtils.isBlank(shortDesc)) { + clickedItemText = ((TextView) view).getText(); + } else { + clickedItemText = shortDesc + "\n\n" + ((TextView) view).getText(); + } + buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_description), false); + return true; + case R.id.personalnote: + assert view instanceof TextView; + clickedItemText = ((TextView) view).getText(); + buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_personal_note), true); + return true; + case R.id.hint: + assert view instanceof TextView; + clickedItemText = ((TextView) view).getText(); + buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_hint), false); + return true; + case R.id.log: + assert view instanceof TextView; + clickedItemText = ((TextView) view).getText(); + buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_logs), false); + return true; + case R.id.date: // event date + assert view instanceof TextView; + clickedItemText = ((TextView) view).getText(); + buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_event), true); + menu.findItem(R.id.menu_calendar).setVisible(cache.canBeAddedToCalendar()); + return true; + } + return false; + } + + @Override + public void onDestroyActionMode(ActionMode actionMode) { + // do nothing + } + + @Override + public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { + actionMode.getMenuInflater().inflate(R.menu.details_context, menu); + + // Return true so that the action mode is shown + return true; + } + + @Override + public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { + return onClipboardItemSelected(actionMode, menuItem, clickedItemText); + } + }); + return false; + } + }); + } + public static void startActivityGuid(final Context context, final String guid, final String cacheName) { final Intent cacheIntent = new Intent(context, CacheDetailActivity.class); cacheIntent.putExtra(Intents.EXTRA_GUID, guid); diff --git a/main/src/cgeo/geocaching/TrackableActivity.java b/main/src/cgeo/geocaching/TrackableActivity.java index cd39cfa..2b6808e 100644 --- a/main/src/cgeo/geocaching/TrackableActivity.java +++ b/main/src/cgeo/geocaching/TrackableActivity.java @@ -38,12 +38,14 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v7.app.ActionBar; +import android.support.v7.view.ActionMode; import android.text.Html; -import android.view.ContextMenu; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.view.View.OnClickListener; +import android.view.View.OnLongClickListener; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ScrollView; @@ -126,6 +128,10 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi }; private CharSequence clickedItemText = null; + /** + * Action mode of the current contextual action bar (e.g. for copy and share actions). + */ + private ActionMode currentActionMode; @Override public void onCreate(Bundle savedInstanceState) { @@ -210,36 +216,6 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi } @Override - public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo info) { - super.onCreateContextMenu(menu, view, info); - final int viewId = view.getId(); - assert view instanceof TextView; - clickedItemText = ((TextView) view).getText(); - switch (viewId) { - case R.id.value: // name, TB-code, origin, released, distance - final String itemTitle = (String) ((TextView) ((View) view.getParent()).findViewById(R.id.name)).getText(); - buildDetailsContextMenu(menu, clickedItemText, itemTitle, true); - break; - case R.id.goal: - buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.trackable_goal), false); - break; - case R.id.details: - buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.trackable_details), false); - break; - case R.id.log: - buildDetailsContextMenu(menu, clickedItemText, res.getString(R.string.cache_logs), false); - break; - default: - break; - } - } - - @Override - public boolean onContextItemSelected(MenuItem item) { - return onClipboardItemSelected(item, clickedItemText) || onOptionsItemSelected(item); - } - - @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.trackable_activity, menu); return true; @@ -409,7 +385,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi } // trackable name - registerForContextMenu(details.add(R.string.trackable_name, StringUtils.isNotBlank(trackable.getName()) ? Html.fromHtml(trackable.getName()).toString() : res.getString(R.string.trackable_unknown))); + addContextMenu(details.add(R.string.trackable_name, StringUtils.isNotBlank(trackable.getName()) ? Html.fromHtml(trackable.getName()).toString() : res.getString(R.string.trackable_unknown))); // trackable type String tbType; @@ -421,7 +397,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi details.add(R.string.trackable_type, tbType); // trackable geocode - registerForContextMenu(details.add(R.string.trackable_code, trackable.getGeocode())); + addContextMenu(details.add(R.string.trackable_code, trackable.getGeocode())); // trackable owner final TextView owner = details.add(R.string.trackable_owner, res.getString(R.string.trackable_unknown)); @@ -490,17 +466,17 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi if (StringUtils.isNotBlank(trackable.getOrigin())) { final TextView origin = details.add(R.string.trackable_origin, ""); origin.setText(Html.fromHtml(trackable.getOrigin()), TextView.BufferType.SPANNABLE); - registerForContextMenu(origin); + addContextMenu(origin); } // trackable released if (trackable.getReleased() != null) { - registerForContextMenu(details.add(R.string.trackable_released, Formatter.formatDate(trackable.getReleased().getTime()))); + addContextMenu(details.add(R.string.trackable_released, Formatter.formatDate(trackable.getReleased().getTime()))); } // trackable distance if (trackable.getDistance() >= 0) { - registerForContextMenu(details.add(R.string.trackable_distance, Units.getDistanceFromKilometers(trackable.getDistance()))); + addContextMenu(details.add(R.string.trackable_distance, Units.getDistanceFromKilometers(trackable.getDistance()))); } // trackable goal @@ -509,7 +485,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi goalTextView.setVisibility(View.VISIBLE); goalTextView.setText(Html.fromHtml(trackable.getGoal(), new HtmlImage(geocode, true, 0, false), null), TextView.BufferType.SPANNABLE); goalTextView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); - registerForContextMenu(goalTextView); + addContextMenu(goalTextView); } // trackable details @@ -518,7 +494,7 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi detailsTextView.setVisibility(View.VISIBLE); detailsTextView.setText(Html.fromHtml(trackable.getDetails(), new HtmlImage(geocode, true, 0, false), new UnknownTagsHandler()), TextView.BufferType.SPANNABLE); detailsTextView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance()); - registerForContextMenu(detailsTextView); + addContextMenu(detailsTextView); } // trackable image @@ -549,4 +525,70 @@ public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivi } + public void addContextMenu(final View view) { + view.setOnLongClickListener(new OnLongClickListener() { + + @Override + public boolean onLongClick(View v) { + return startContextualActionBar(view); + } + }); + + view.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View v) { + startContextualActionBar(view); + } + }); + } + + private boolean startContextualActionBar(final View view) { + if (currentActionMode != null) { + return false; + } + currentActionMode = startSupportActionMode(new ActionMode.Callback() { + + @Override + public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { + final int viewId = view.getId(); + assert view instanceof TextView; + clickedItemText = ((TextView) view).getText(); + switch (viewId) { + case R.id.value: // name, TB-code, origin, released, distance + final String itemTitle = (String) ((TextView) ((View) view.getParent()).findViewById(R.id.name)).getText(); + buildDetailsContextMenu(actionMode, menu, clickedItemText, itemTitle, true); + return true; + case R.id.goal: + buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.trackable_goal), false); + return true; + case R.id.details: + buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.trackable_details), false); + return true; + case R.id.log: + buildDetailsContextMenu(actionMode, menu, clickedItemText, res.getString(R.string.cache_logs), false); + return true; + } + return false; + } + + @Override + public void onDestroyActionMode(ActionMode actionMode) { + currentActionMode = null; + } + + @Override + public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { + actionMode.getMenuInflater().inflate(R.menu.details_context, menu); + return true; + } + + @Override + public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { + return onClipboardItemSelected(actionMode, menuItem, clickedItemText); + } + }); + return false; + } + } diff --git a/main/src/cgeo/geocaching/activity/AbstractActivity.java b/main/src/cgeo/geocaching/activity/AbstractActivity.java index 05dde40..e3df1f7 100644 --- a/main/src/cgeo/geocaching/activity/AbstractActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java @@ -12,6 +12,7 @@ import cgeo.geocaching.utils.HtmlUtils; import cgeo.geocaching.utils.TranslationUtils; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.annotation.NonNull; import rx.Subscription; import rx.subscriptions.Subscriptions; @@ -26,7 +27,8 @@ import android.nfc.NfcEvent; import android.os.Build; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; -import android.view.ContextMenu; +import android.support.v7.view.ActionMode; +import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.Window; @@ -154,9 +156,8 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs new Keyboard(this).show(view); } - protected void buildDetailsContextMenu(final ContextMenu menu, final CharSequence clickedItemText, final CharSequence fieldTitle, final boolean copyOnly) { - menu.setHeaderTitle(fieldTitle); - getMenuInflater().inflate(R.menu.details_context, menu); + protected void buildDetailsContextMenu(final ActionMode actionMode, final Menu menu, final CharSequence clickedItemText, final CharSequence fieldTitle, final boolean copyOnly) { + actionMode.setTitle(fieldTitle); menu.findItem(R.id.menu_translate_to_sys_lang).setVisible(!copyOnly); if (!copyOnly) { if (clickedItemText.length() > TranslationUtils.TRANSLATION_TEXT_LENGTH_WARN) { @@ -168,24 +169,28 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs menu.findItem(R.id.menu_translate_to_english).setVisible(!copyOnly && !localeIsEnglish); } - protected boolean onClipboardItemSelected(final MenuItem item, final CharSequence clickedItemText) { + protected boolean onClipboardItemSelected(@NonNull final ActionMode actionMode, final MenuItem item, final CharSequence clickedItemText) { switch (item.getItemId()) { // detail fields case R.id.menu_copy: ClipboardUtils.copyToClipboard(clickedItemText); showToast(res.getString(R.string.clipboard_copy_ok)); + actionMode.finish(); return true; case R.id.menu_translate_to_sys_lang: TranslationUtils.startActivityTranslate(this, Locale.getDefault().getLanguage(), HtmlUtils.extractText(clickedItemText)); + actionMode.finish(); return true; case R.id.menu_translate_to_english: TranslationUtils.startActivityTranslate(this, Locale.ENGLISH.getLanguage(), HtmlUtils.extractText(clickedItemText)); + actionMode.finish(); return true; case R.id.menu_cache_share_field: final Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_TEXT, clickedItemText.toString()); startActivity(Intent.createChooser(intent, res.getText(R.string.cache_share_field))); + actionMode.finish(); return true; default: return false; |
