diff options
Diffstat (limited to 'main/src')
11 files changed, 202 insertions, 46 deletions
diff --git a/main/src/cgeo/geocaching/CacheListActivity.java b/main/src/cgeo/geocaching/CacheListActivity.java index 611d17e..717b6f5 100644 --- a/main/src/cgeo/geocaching/CacheListActivity.java +++ b/main/src/cgeo/geocaching/CacheListActivity.java @@ -7,6 +7,7 @@ import cgeo.geocaching.activity.AbstractListActivity; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.activity.FilteredActivity; import cgeo.geocaching.activity.Progress; +import cgeo.geocaching.activity.ShowcaseViewBuilder; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; import cgeo.geocaching.apps.cachelist.CacheListAppFactory; import cgeo.geocaching.compatibility.Compatibility; @@ -58,6 +59,9 @@ import cgeo.geocaching.utils.Log; import ch.boye.httpclientandroidlib.HttpResponse; +import com.github.amlcurran.showcaseview.targets.ActionViewTarget; +import com.github.amlcurran.showcaseview.targets.ActionViewTarget.Type; + import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang3.StringUtils; @@ -427,9 +431,9 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA if (isInvokedFromAttachment()) { importGpxAttachement(); } - - - + else { + presentShowcase(); + } } /** @@ -1741,4 +1745,11 @@ public class CacheListActivity extends AbstractListActivity implements FilteredA } return numbers.isEmpty() ? null : StringUtils.join(numbers, '/'); } + + @Override + public ShowcaseViewBuilder getShowcase() { + return new ShowcaseViewBuilder(this) + .setTarget(new ActionViewTarget(this, Type.SPINNER)) + .setContent(R.string.showcase_cachelist_title, R.string.showcase_cachelist_text); + } } diff --git a/main/src/cgeo/geocaching/LogCacheActivity.java b/main/src/cgeo/geocaching/LogCacheActivity.java index e8334f8..bc87525 100644 --- a/main/src/cgeo/geocaching/LogCacheActivity.java +++ b/main/src/cgeo/geocaching/LogCacheActivity.java @@ -2,6 +2,7 @@ package cgeo.geocaching; import butterknife.ButterKnife; +import cgeo.geocaching.activity.ShowcaseViewBuilder; import cgeo.geocaching.connector.ILoggingManager; import cgeo.geocaching.connector.ImageResult; import cgeo.geocaching.connector.LogResult; @@ -21,6 +22,8 @@ import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.LogTemplateProvider; import cgeo.geocaching.utils.LogTemplateProvider.LogContext; +import com.github.amlcurran.showcaseview.targets.ActionItemTarget; + import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -637,7 +640,14 @@ public class LogCacheActivity extends AbstractLoggingActivity implements DateDia menu.findItem(R.id.menu_image).setVisible(cache.supportsLogImages()); menu.findItem(R.id.save).setVisible(true); menu.findItem(R.id.clear).setVisible(true); + presentShowcase(); return true; } + @Override + public ShowcaseViewBuilder getShowcase() { + return new ShowcaseViewBuilder(this) + .setTarget(new ActionItemTarget(this, R.id.menu_send)) + .setContent(R.string.showcase_logcache_title, R.string.showcase_logcache_text); + } } diff --git a/main/src/cgeo/geocaching/MainActivity.java b/main/src/cgeo/geocaching/MainActivity.java index 2d6e9f0..18b3b01 100644 --- a/main/src/cgeo/geocaching/MainActivity.java +++ b/main/src/cgeo/geocaching/MainActivity.java @@ -4,6 +4,7 @@ import butterknife.ButterKnife; import butterknife.InjectView; import cgeo.geocaching.activity.AbstractActionBarActivity; +import cgeo.geocaching.activity.ShowcaseViewBuilder; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.capability.ILogin; import cgeo.geocaching.connector.gc.GCConnector; @@ -27,6 +28,7 @@ import cgeo.geocaching.utils.RxUtils; import cgeo.geocaching.utils.TextUtils; import cgeo.geocaching.utils.Version; +import com.github.amlcurran.showcaseview.targets.ActionViewTarget; import com.google.zxing.integration.android.IntentIntegrator; import com.google.zxing.integration.android.IntentResult; @@ -284,7 +286,7 @@ public class MainActivity extends AbstractActionBarActivity { final MenuItem searchItem = menu.findItem(R.id.menu_gosearch); final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem); searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName())); - + presentShowcase(); return true; } @@ -749,4 +751,11 @@ public class MainActivity extends AbstractActionBarActivity { public void showAbout(final View view) { startActivity(new Intent(this, AboutActivity.class)); } + + @Override + public ShowcaseViewBuilder getShowcase() { + return new ShowcaseViewBuilder(this) + .setTarget(new ActionViewTarget(this, ActionViewTarget.Type.OVERFLOW)) + .setContent(R.string.showcase_main_title, R.string.showcase_main_text); + } } diff --git a/main/src/cgeo/geocaching/SearchActivity.java b/main/src/cgeo/geocaching/SearchActivity.java index 81dec98..edd611a 100644 --- a/main/src/cgeo/geocaching/SearchActivity.java +++ b/main/src/cgeo/geocaching/SearchActivity.java @@ -4,6 +4,7 @@ import butterknife.ButterKnife; import butterknife.InjectView; import cgeo.geocaching.activity.AbstractActionBarActivity; +import cgeo.geocaching.activity.ShowcaseViewBuilder; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.IConnector; import cgeo.geocaching.connector.capability.ISearchByGeocode; @@ -177,14 +178,14 @@ public class SearchActivity extends AbstractActionBarActivity implements Coordin buttonLatitude.setOnClickListener(new OnClickListener() { @Override - public void onClick(View v) { + public void onClick(final View v) { updateCoordinates(); } }); buttonLongitude.setOnClickListener(new OnClickListener() { @Override - public void onClick(View v) { + public void onClick(final View v) { updateCoordinates(); } }); @@ -398,6 +399,7 @@ public class SearchActivity extends AbstractActionBarActivity implements Coordin @Override public final boolean onCreateOptionsMenu(final Menu menu) { getMenuInflater().inflate(R.menu.search_activity_options, menu); + presentShowcase(); return true; } @@ -417,4 +419,13 @@ public class SearchActivity extends AbstractActionBarActivity implements Coordin putExtra(Intents.EXTRA_KEYWORD_SEARCH, false); fromActivity.startActivityForResult(searchIntent, MainActivity.SEARCH_REQUEST_CODE); } + + @Override + public ShowcaseViewBuilder getShowcase() { + // The showcase doesn't work well with the search activity, because on searching a geocode (or + // selecting a cache from the search field) we immediately close the activity. That in turn confuses the delayed + // creation of the showcase bitmap. To avoid someone running into this issue again, this method explicitly overrides + // the parent method with the same implementation. + return null; + } } diff --git a/main/src/cgeo/geocaching/activity/AbstractActivity.java b/main/src/cgeo/geocaching/activity/AbstractActivity.java index e3df1f7..4480f8f 100644 --- a/main/src/cgeo/geocaching/activity/AbstractActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java @@ -60,26 +60,36 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs } @Override - public final void showToast(String text) { + public final void showToast(final String text) { ActivityMixin.showToast(this, text); } @Override - public final void showShortToast(String text) { + public final void showShortToast(final String text) { ActivityMixin.showShortToast(this, text); } @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); supportRequestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); initializeCommonFields(); + } + + @Override + public final void presentShowcase() { + ActivityMixin.presentShowcase(this); + } + @Override + public ShowcaseViewBuilder getShowcase() { + // do nothing by default + return null; } @Override - public boolean onOptionsItemSelected(MenuItem item) { + public boolean onOptionsItemSelected(final MenuItem item) { if (item.getItemId() == android.R.id.home) { return ActivityMixin.navigateUp(this); } @@ -116,7 +126,6 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs } protected void onCreate(final Bundle savedInstanceState, final int resourceLayoutID) { - super.onCreate(savedInstanceState); initializeCommonFields(); @@ -141,7 +150,7 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs } @Override - public void setContentView(int layoutResID) { + public void setContentView(final int layoutResID) { super.setContentView(layoutResID); // initialize the action bar title with the activity title for single source @@ -206,7 +215,7 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs public String getUri(); } - protected void initializeAndroidBeam(ActivitySharingInterface sharingInterface) { + protected void initializeAndroidBeam(final ActivitySharingInterface sharingInterface) { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH) { initializeICSAndroidBeam(sharingInterface); } @@ -214,14 +223,14 @@ public abstract class AbstractActivity extends ActionBarActivity implements IAbs @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) protected void initializeICSAndroidBeam(final ActivitySharingInterface sharingInterface) { - NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); + final NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); if (nfcAdapter == null) { return; } nfcAdapter.setNdefPushMessageCallback(new NfcAdapter.CreateNdefMessageCallback() { @Override - public NdefMessage createNdefMessage(NfcEvent event) { - NdefRecord record = NdefRecord.createUri(sharingInterface.getUri()); + public NdefMessage createNdefMessage(final NfcEvent event) { + final NdefRecord record = NdefRecord.createUri(sharingInterface.getUri()); return new NdefMessage(new NdefRecord[]{record}); } }, this); diff --git a/main/src/cgeo/geocaching/activity/AbstractListActivity.java b/main/src/cgeo/geocaching/activity/AbstractListActivity.java index eac191a..718dc70 100644 --- a/main/src/cgeo/geocaching/activity/AbstractListActivity.java +++ b/main/src/cgeo/geocaching/activity/AbstractListActivity.java @@ -32,17 +32,17 @@ public abstract class AbstractListActivity extends ActionBarListActivity impleme } @Override - public final void showToast(String text) { + public final void showToast(final String text) { ActivityMixin.showToast(this, text); } @Override - public final void showShortToast(String text) { + public final void showShortToast(final String text) { ActivityMixin.showShortToast(this, text); } @Override - public void onCreate(Bundle savedInstanceState) { + public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); supportRequestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); @@ -55,7 +55,7 @@ public abstract class AbstractListActivity extends ActionBarListActivity impleme } @Override - public boolean onOptionsItemSelected(MenuItem item) { + public boolean onOptionsItemSelected(final MenuItem item) { if (item.getItemId()== android.R.id.home) { return ActivityMixin.navigateUp(this); } @@ -79,7 +79,7 @@ public abstract class AbstractListActivity extends ActionBarListActivity impleme ActivityMixin.invalidateOptionsMenu(this); } - public void onCreate(Bundle savedInstanceState, int resourceLayoutID) { + public void onCreate(final Bundle savedInstanceState, final int resourceLayoutID) { super.onCreate(savedInstanceState); initializeCommonFields(); @@ -88,10 +88,22 @@ public abstract class AbstractListActivity extends ActionBarListActivity impleme } @Override - public void setContentView(int layoutResID) { + public void setContentView(final int layoutResID) { super.setContentView(layoutResID); // initialize action bar title with activity title ActivityMixin.setTitle(this, getTitle()); } + + @Override + public final void presentShowcase() { + ActivityMixin.presentShowcase(this); + } + + @Override + public ShowcaseViewBuilder getShowcase() { + // do nothing by default + return null; + } + } diff --git a/main/src/cgeo/geocaching/activity/ActivityMixin.java b/main/src/cgeo/geocaching/activity/ActivityMixin.java index b58d3ae..f91de7e 100644 --- a/main/src/cgeo/geocaching/activity/ActivityMixin.java +++ b/main/src/cgeo/geocaching/activity/ActivityMixin.java @@ -103,13 +103,13 @@ public final class ActivityMixin { postShowToast(activity, text, Toast.LENGTH_SHORT); } - public static void keepScreenOn(final Activity abstractActivity, boolean keepScreenOn) { + public static void keepScreenOn(final Activity abstractActivity, final boolean keepScreenOn) { if (keepScreenOn) { abstractActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } } - public static void invalidateOptionsMenu(Activity activity) { + public static void invalidateOptionsMenu(final Activity activity) { if (activity instanceof ActionBarActivity) { ((ActionBarActivity) activity).supportInvalidateOptionsMenu(); } @@ -127,10 +127,10 @@ public final class ActivityMixin { * place the cursor after the inserted text */ public static void insertAtPosition(final EditText editText, final String insertText, final boolean moveCursor) { - int selectionStart = editText.getSelectionStart(); - int selectionEnd = editText.getSelectionEnd(); - int start = Math.min(selectionStart, selectionEnd); - int end = Math.max(selectionStart, selectionEnd); + final int selectionStart = editText.getSelectionStart(); + final int selectionEnd = editText.getSelectionEnd(); + final int start = Math.min(selectionStart, selectionEnd); + final int end = Math.max(selectionStart, selectionEnd); final String content = editText.getText().toString(); String completeText; @@ -141,13 +141,13 @@ public final class ActivityMixin { } editText.getText().replace(start, end, completeText); - int newCursor = moveCursor ? start + completeText.length() : start; + final int newCursor = moveCursor ? start + completeText.length() : start; editText.setSelection(newCursor); } public static boolean navigateUp(@NonNull final Activity activity) { // see http://developer.android.com/training/implementing-navigation/ancestral.html - Intent upIntent = NavUtils.getParentActivityIntent(activity); + final Intent upIntent = NavUtils.getParentActivityIntent(activity); if (upIntent == null) { activity.finish(); return true; @@ -167,4 +167,12 @@ public final class ActivityMixin { } return true; } + + public static void presentShowcase(final IAbstractActivity activity) { + final ShowcaseViewBuilder builder = activity.getShowcase(); + if (builder != null) { + builder.setStyle(R.style.ShowcaseView); + builder.build(); + } + } } diff --git a/main/src/cgeo/geocaching/activity/IAbstractActivity.java b/main/src/cgeo/geocaching/activity/IAbstractActivity.java index 4fb6a2a..59aa284 100644 --- a/main/src/cgeo/geocaching/activity/IAbstractActivity.java +++ b/main/src/cgeo/geocaching/activity/IAbstractActivity.java @@ -8,4 +8,18 @@ public interface IAbstractActivity { public void showShortToast(String text); public void invalidateOptionsMenuCompatible(); + + /** + * Override this method to create a showcase view highlighting the most important UI element. + * + */ + public ShowcaseViewBuilder getShowcase(); + + /** + * Call this method to actually present a showcase. The right time to invoke this method depends on the showcase + * target. I.e. if the showcase target is an action bar item, this method can only be invoked after that item has + * been created in onCreateOptionsMenu. + */ + public void presentShowcase(); + } diff --git a/main/src/cgeo/geocaching/activity/ShowcaseViewBuilder.java b/main/src/cgeo/geocaching/activity/ShowcaseViewBuilder.java new file mode 100644 index 0000000..6b00f0f --- /dev/null +++ b/main/src/cgeo/geocaching/activity/ShowcaseViewBuilder.java @@ -0,0 +1,61 @@ +package cgeo.geocaching.activity; + +import com.github.amlcurran.showcaseview.ShowcaseView.Builder; +import com.github.amlcurran.showcaseview.targets.Target; + +import android.app.Activity; + +/** + * TODO: replace by simple utility class embedding a builder instead of inheriting from it + */ +public class ShowcaseViewBuilder extends Builder { + + private final Activity activity; + + public ShowcaseViewBuilder(final Activity activity) { + super(activity); + this.activity = activity; + } + + @Override + public ShowcaseViewBuilder setContentTitle(final int resId) { + setSingleshot(activity.getResources().getString(resId)); + return (ShowcaseViewBuilder) super.setContentTitle(resId); + } + + /** + * Use the hash of the title for the single shot remembering + * + * @param resId + */ + private void setSingleshot(final CharSequence title) { + super.singleShot(title.hashCode()); + } + + @Override + public ShowcaseViewBuilder setContentText(final int resId) { + return (ShowcaseViewBuilder) super.setContentText(resId); + } + + @Override + public ShowcaseViewBuilder setContentText(final CharSequence text) { + return (ShowcaseViewBuilder) super.setContentText(text); + } + + @Override + public ShowcaseViewBuilder setContentTitle(final CharSequence title) { + setSingleshot(title); + return (ShowcaseViewBuilder) super.setContentTitle(title); + } + + @Override + public ShowcaseViewBuilder setTarget(final Target target) { + return (ShowcaseViewBuilder) super.setTarget(target); + } + + public ShowcaseViewBuilder setContent(final int titleId, final int textId) { + setContentTitle(titleId); + return setContentText(textId); + } + +} diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java index e24c055..c00723d 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java @@ -142,23 +142,21 @@ public final class NavigationAppFactory extends AbstractAppFactory { final boolean showInternalMap, final boolean showDefaultNavigation) { final List<NavigationAppsEnum> items = new ArrayList<>(); final int defaultNavigationTool = Settings.getDefaultNavigationTool(); - for (final NavigationAppsEnum navApp : getInstalledNavigationApps()) { + for (final NavigationAppsEnum navApp : getActiveNavigationApps()) { if ((showInternalMap || !(navApp.app instanceof InternalMap)) && (showDefaultNavigation || defaultNavigationTool != navApp.id)) { - if (Settings.isUseNavigationApp(navApp)) { - boolean add = false; - if (cache != null && navApp.app instanceof CacheNavigationApp && navApp.app.isEnabled(cache)) { - add = true; - } - if (waypoint != null && navApp.app instanceof WaypointNavigationApp && ((WaypointNavigationApp) navApp.app).isEnabled(waypoint)) { - add = true; - } - if (destination != null && navApp.app instanceof GeopointNavigationApp) { - add = true; - } - if (add) { - items.add(navApp); - } + boolean add = false; + if (cache != null && navApp.app instanceof CacheNavigationApp && navApp.app.isEnabled(cache)) { + add = true; + } + if (waypoint != null && navApp.app instanceof WaypointNavigationApp && ((WaypointNavigationApp) navApp.app).isEnabled(waypoint)) { + add = true; + } + if (destination != null && navApp.app instanceof GeopointNavigationApp) { + add = true; + } + if (add) { + items.add(navApp); } } } @@ -203,6 +201,19 @@ public final class NavigationAppFactory extends AbstractAppFactory { } /** + * @return all navigation apps, which are installed and activated in the settings + */ + public static List<NavigationAppsEnum> getActiveNavigationApps() { + final List<NavigationAppsEnum> activeApps = new ArrayList<>(); + for (final NavigationAppsEnum appEnum : getInstalledNavigationApps()) { + if (Settings.isUseNavigationApp(appEnum)) { + activeApps.add(appEnum); + } + } + return activeApps; + } + + /** * Returns all installed navigation apps for default navigation. * * @return diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationSelectionActionProvider.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationSelectionActionProvider.java index 9abc581..82883a2 100644 --- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationSelectionActionProvider.java +++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigationSelectionActionProvider.java @@ -47,7 +47,7 @@ public class NavigationSelectionActionProvider extends ActionProvider { if (geocache == null) { return; } - for (final NavigationAppsEnum app : NavigationAppFactory.getInstalledNavigationApps()) { + for (final NavigationAppsEnum app : NavigationAppFactory.getActiveNavigationApps()) { if (app.app.isEnabled(geocache)) { subMenu.add(Menu.NONE, app.id, Menu.NONE, app.app.getName()).setOnMenuItemClickListener(new OnMenuItemClickListener() { |
