From f54d67bfd91f2b1be9cf22e5f5c6ce44586182b5 Mon Sep 17 00:00:00 2001 From: The Gitter Badger Date: Mon, 6 Apr 2015 08:55:09 +0000 Subject: [PATCH 01/17] Added Gitter badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 9681e80..6b54337 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-TutorialView-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/1408) ##TutorialView +[![Join the chat at https://gitter.im/itzikBraun/TutorialView](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/itzikBraun/TutorialView?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + ![alt tag](http://raw.github.com/ItzikBraun/TutorialView/master/screen_shots/example.gif) An Android library project providing `Activity` with explanation about views in your app. From 2b0212568a3e1335df27d19fcd56c2ebc01e5514 Mon Sep 17 00:00:00 2001 From: ItzikBraun Date: Fri, 1 May 2015 09:08:08 +0200 Subject: [PATCH 02/17] - Fixed problem showing walk through - Fixed problem saving walk through state when activity is killed - Added coloring of the System navigation bar and status bar for lollipop devices. --- .idea/.name | 2 +- .idea/compiler.xml | 5 +- .idea/dictionaries/braunster.xml | 7 -- .idea/encodings.xml | 5 -- .idea/gradle.xml | 7 +- .idea/misc.xml | 18 +++- .idea/modules.xml | 4 +- .idea/scopes/scope_settings.xml | 5 -- .idea/vcs.xml | 3 +- TutorialView.iml | 10 +-- app/app.iml | 10 ++- .../tutorialviewapp/MainActivity.java | 48 ++++++++++ .../tutorialview/TutorialActivity.java | 88 ++++++++++++++++++- .../tutorialview/object/TutorialBuilder.java | 3 +- .../object/TutorialIntentBuilder.java | 78 +++++++++++++--- .../tutorialview/view/TutorialLayout.java | 8 +- .../src/main/res/values-v21/styles.xml | 10 +++ tutorial_view/tutorial_view.iml | 10 ++- 18 files changed, 256 insertions(+), 65 deletions(-) delete mode 100644 .idea/dictionaries/braunster.xml delete mode 100644 .idea/encodings.xml delete mode 100644 .idea/scopes/scope_settings.xml create mode 100644 tutorial_view/src/main/res/values-v21/styles.xml diff --git a/.idea/.name b/.idea/.name index f65cffb..9c740f3 100644 --- a/.idea/.name +++ b/.idea/.name @@ -1 +1 @@ -TutorialViewApp \ No newline at end of file +TutorialView \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 217af47..96cc43e 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,7 +1,6 @@ - - - + \ No newline at end of file diff --git a/.idea/dictionaries/braunster.xml b/.idea/dictionaries/braunster.xml deleted file mode 100644 index b8bee26..0000000 --- a/.idea/dictionaries/braunster.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - animtaing - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index e206d70..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 9137773..c7e984d 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -3,8 +3,10 @@ - - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 9076de5..e4a5fa4 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,8 +3,20 @@ - + + + + + + + + + + + - - + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index bfe8ee9..59b16af 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -3,10 +3,8 @@ - - - + \ No newline at end of file diff --git a/.idea/scopes/scope_settings.xml b/.idea/scopes/scope_settings.xml deleted file mode 100644 index 922003b..0000000 --- a/.idea/scopes/scope_settings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index c80f219..94a25f7 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -3,5 +3,4 @@ - - + \ No newline at end of file diff --git a/TutorialView.iml b/TutorialView.iml index 2a02201..746a30d 100644 --- a/TutorialView.iml +++ b/TutorialView.iml @@ -1,15 +1,14 @@ - + - - - + @@ -17,5 +16,4 @@ - - + \ No newline at end of file diff --git a/app/app.iml b/app/app.iml index 3cf6bd9..f3c7264 100644 --- a/app/app.iml +++ b/app/app.iml @@ -1,5 +1,5 @@ - + @@ -9,10 +9,12 @@ + @@ -85,5 +88,4 @@ - - + \ No newline at end of file diff --git a/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java b/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java index 528e907..971b3b5 100644 --- a/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java +++ b/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java @@ -52,6 +52,10 @@ protected void onCreate(Bundle savedInstanceState) { tutorialView.setTutorialTextTypeFace("fonts/roboto_light.ttf"); tutorialView.setHasStatusBar(true); tutorialView.setTutorialText("This is some general text that is not that long but also not so short."); + + // Only show the walk through when the activity is first created. + if (savedInstanceState == null) + startWalkThrough(); } @Override @@ -139,4 +143,48 @@ public void onClick(View v) { // This will allow the nice wrapping of the view by the tutorial activity. overridePendingTransition(R.anim.dummy, R.anim.dummy); } + + private void startWalkThrough(){ + + // Running a walk through as the activity is opened, Tutorial + // building should be wrapped in a runnable that is posted so + // all views will have their positions on the screen. + getWindow().getDecorView().post(new Runnable() { + @Override + public void run() { + + Tutorial t1 = getBasicBuilderForTest(findViewById(R.id.view_bottom_left)) + .setTutorialInfoTextPosition(Tutorial.InfoPosition.ABOVE) + .setTutorialGotItPosition(Tutorial.GotItPosition.BOTTOM) + .build(); + + Tutorial t2 = getBasicBuilderForTest(findViewById(R.id.view_top_right)) + .setTutorialInfoTextPosition(Tutorial.InfoPosition.LEFT_OF) + .build(); + + Tutorial t3 = getBasicBuilderForTest(findViewById(R.id.view_almost_top_right)) + .setTutorialInfoTextPosition(Tutorial.InfoPosition.RIGHT_OF) + .build(); + + Tutorial t4 = getBasicBuilderForTest(findViewById(R.id.view_top_left)) + .setTutorialInfoTextPosition(Tutorial.InfoPosition.BELOW) + .build(); + + Tutorial t5 = getBasicBuilderForTest(findViewById(R.id.view_center)) + .setTutorialInfoTextPosition(Tutorial.InfoPosition.BELOW) + .setTutorialGotItPosition(Tutorial.GotItPosition.BOTTOM) + .build(); + + + TutorialIntentBuilder builder = new TutorialIntentBuilder(MainActivity.this); + + builder.setWalkThroughList(t1, t2, t3, t4, t5); + startActivity(builder.getIntent()); + + // Override the default animation of the entering activity. + // This will allow the nice wrapping of the view by the tutorial activity. + overridePendingTransition(R.anim.dummy, R.anim.dummy); + } + }); + } } diff --git a/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialActivity.java b/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialActivity.java index 39d60ce..c2e0e59 100644 --- a/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialActivity.java +++ b/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialActivity.java @@ -1,12 +1,17 @@ package com.braunster.tutorialview; import android.app.Activity; +import android.os.Build; import android.os.Bundle; +import android.util.Log; +import com.braunster.tutorialview.object.Tutorial; import com.braunster.tutorialview.object.TutorialIntentBuilder; import com.braunster.tutorialview.view.TutorialLayout; import com.braunster.tutorialview.view.TutorialView; +import java.util.ArrayList; + /** * Created by braunster on 02/12/14. */ @@ -17,6 +22,12 @@ public class TutorialActivity extends Activity { private TutorialLayout mTutorialLayout; + private Tutorial mTutorial; + + private int mCurrentTutorialPos = 0; + + private static final String CURRENT_TUTORIAL = "current_tutorial"; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -30,6 +41,43 @@ protected void onCreate(Bundle savedInstanceState) { throw new NullPointerException("You must provide extras to the activity to set up the tutorial view."); } + mTutorialLayout.setHasStatusBar(TutorialIntentBuilder.hasStatusBar(getIntent())); + + mTutorial = TutorialIntentBuilder.getTutorial(getIntent()); + + if (TutorialIntentBuilder.isWalkThrough(getIntent())) + { + ArrayList tutorials = TutorialIntentBuilder.getWalkThroughData(getIntent()); + + // If the activity is re created we should start + // from the last tutorial that was visible + if (savedInstanceState != null) + { + mCurrentTutorialPos = savedInstanceState.getInt(CURRENT_TUTORIAL); + + if (DEBUG) Log.d(TAG, String.format("mCurrentTutorialPos: %s, Tutorial list size: %s", + mCurrentTutorialPos, tutorials.size())); + + // Removing tutorials that was already shown. + int i = 0; + while (i < mCurrentTutorialPos) + { + i++; + tutorials.remove(0); + } + + // Setting the current tutorial to be the new first tutorial + mTutorial = tutorials.get(0); + } + + mTutorialLayout.setWalkThroughData(tutorials); + } + else + { + mTutorialLayout.setTutorial(mTutorial, false); + } + + // Finish the activity when the tutorial is closed. mTutorialLayout.setTutorialClosedListener(new TutorialView.TutorialClosedListener() { @Override @@ -37,6 +85,8 @@ public void onClosed() { finish(); } }); + + updateSystemUIColors(); } /** @@ -52,8 +102,6 @@ public void onWindowFocusChanged(boolean hasFocus) { @Override public void run() { { - TutorialIntentBuilder.updateTutorialViewFromIntent(mTutorialLayout, getIntent()); - TutorialIntentBuilder.showTutorial(mTutorialLayout, getIntent()); // If the tutorial is a walk through we would need to set a WalkThroughListener. @@ -61,13 +109,19 @@ public void run() { { mTutorialLayout.setWalkThroughListener(new TutorialLayout.WalkThroughListener() { @Override - public void onNextTutorialShown() { + public void onNextTutorialShown(Tutorial tutorial) { + + // Keeping track of the position in the tutorial list. + // Used for a situation that the activity was killed and we need + // to re-create it from the last visible tutorial. + mCurrentTutorialPos++; + mTutorial = tutorial; + updateSystemUIColors(); } @Override public void onWalkTroughSkipped() { -// Toast.makeText(TutorialActivity.this, "Walk through was skipped.", Toast.LENGTH_LONG).show(); finish(); } @@ -82,6 +136,13 @@ public void onWalkThroughDone() { }); } + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + + outState.putInt(CURRENT_TUTORIAL, mCurrentTutorialPos); + } + /** * Back press will close the tutorial which will trigger the * {@link com.braunster.tutorialview.view.TutorialView.TutorialClosedListener#onClosed() onClosed()} method @@ -102,4 +163,23 @@ public void onBackPressed() { else mTutorialLayout.closeTutorial(); } + private void updateSystemUIColors(){ + + if (isFinishing()) + return; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) + if (isDestroyed()) + return; + + // coloring the status bar and navigation bar from lollipop. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) + { + if (TutorialIntentBuilder.changesSystemUiColors(getIntent()) && mTutorial != null) + { + getWindow().setStatusBarColor(mTutorial.getTutorialBackgroundColor()); + getWindow().setNavigationBarColor(mTutorial.getTutorialBackgroundColor()); + } + } + } } diff --git a/tutorial_view/src/main/java/com/braunster/tutorialview/object/TutorialBuilder.java b/tutorial_view/src/main/java/com/braunster/tutorialview/object/TutorialBuilder.java index d215dd5..bdd67d0 100644 --- a/tutorial_view/src/main/java/com/braunster/tutorialview/object/TutorialBuilder.java +++ b/tutorial_view/src/main/java/com/braunster/tutorialview/object/TutorialBuilder.java @@ -168,8 +168,9 @@ public TutorialBuilder setTutorialInfoTextPosition(int infoTextPosition) { return this; } - public void setTutorialGotItPosition(int gotItPosition) { + public TutorialBuilder setTutorialGotItPosition(int gotItPosition) { this.mTutorialGotItPosition = gotItPosition; + return this; } public Tutorial build(){ diff --git a/tutorial_view/src/main/java/com/braunster/tutorialview/object/TutorialIntentBuilder.java b/tutorial_view/src/main/java/com/braunster/tutorialview/object/TutorialIntentBuilder.java index 276e275..08b2e04 100644 --- a/tutorial_view/src/main/java/com/braunster/tutorialview/object/TutorialIntentBuilder.java +++ b/tutorial_view/src/main/java/com/braunster/tutorialview/object/TutorialIntentBuilder.java @@ -18,7 +18,7 @@ public class TutorialIntentBuilder { public static final String TAG = TutorialIntentBuilder.class.getSimpleName(); - public static final boolean DEBUG = false; + public static final boolean DEBUG = true; private static final String TUTORIAL_OBJ = "tutorial_obj"; @@ -28,6 +28,8 @@ public class TutorialIntentBuilder { private static final String SKIP_TUTORIAL_ON_BACK_PRESSED = "skip_tutorial_on_back_pressed"; + private static final String CHANGE_SYSTEM_UI_COLOR = "change_system_ui_colors"; + private Intent intent; public TutorialIntentBuilder(Context context){ @@ -43,6 +45,14 @@ public TutorialIntentBuilder(Intent intent){ this.intent = intent; } + /** + * Change the color of the status and navigation bars on devices running API 21 (Lollipop) and up. + * * * */ + public TutorialIntentBuilder changeSystemUiColor(boolean change){ + intent.putExtra(CHANGE_SYSTEM_UI_COLOR, change); + + return this; + } public TutorialIntentBuilder hasStatusBar(boolean hasStatusBar){ intent.putExtra(HAS_STATUS_BAR, hasStatusBar); @@ -78,6 +88,7 @@ public TutorialIntentBuilder skipTutorialOnBackPressed(boolean skip){ return this; } + /** * @return the intent that was build and populated with all attributes. * */ @@ -85,6 +96,25 @@ public Intent getIntent(){ return intent; } + + + + + + + + public static boolean changesSystemUiColors(Intent intent){ + return intent.getBooleanExtra(CHANGE_SYSTEM_UI_COLOR, true); + } + + /** + * @return the value passed in the intent, Default value is true as most apps has a status bar. + * */ + public static boolean hasStatusBar(Intent intent){ + return intent.getBooleanExtra(HAS_STATUS_BAR, true); + + } + /** * @return true if should skip the walk through when user press on the back button. * */ @@ -107,6 +137,9 @@ public static void showTutorial(TutorialViewInterface tutorial, Intent intent){ if (intent.getExtras().containsKey(WALK_THROUGH_DATA)) { + ArrayList tutorials = intent.getExtras().getParcelableArrayList(WALK_THROUGH_DATA); + + ((WalkThroughInterface) tutorial).setWalkThroughData(tutorials); ((WalkThroughInterface) tutorial).startWalkThrough(); return; } @@ -127,19 +160,44 @@ public static void showTutorial(TutorialViewInterface tutorial, Intent intent){ } /** - * Setup tutorial from data saved in the intent. + * @return true if the intent contains a walk through data (List of tutorials) * */ - public static void updateTutorialViewFromIntent(final TutorialViewInterface tutorial, Intent intent){ - tutorial.setHasStatusBar(intent.getBooleanExtra(HAS_STATUS_BAR, true)); + public static boolean isWalkThrough(Intent intent){ + if (intent.getExtras().containsKey(WALK_THROUGH_DATA)) + return true; - /** - * Update the tutorial with data from the intent. - * */ - if (intent.getExtras().containsKey(TUTORIAL_OBJ)) + + return false; + } + + /** + * Get the tutorial passed in the intent, If a list of tutorial had been passed as + * a walk through the first in the list will be returned. + * */ + public static Tutorial getTutorial(Intent intent){ + + // Showing the first tutorial in the list. + if (intent.getExtras().containsKey(WALK_THROUGH_DATA)) { - tutorial.setTutorial((Tutorial) intent.getParcelableExtra(TUTORIAL_OBJ), false); + ArrayList tutorials = intent.getExtras().getParcelableArrayList(WALK_THROUGH_DATA); + + return tutorials.get(0); } - else throw new IllegalArgumentException("You must pass at least on Tutorial object to the intent builder."); + else return (Tutorial) intent.getParcelableExtra(TUTORIAL_OBJ); + } + /** + * Getting the list of tutorials that will be used for the walk through + * */ + public static ArrayList getWalkThroughData(Intent intent){ + if (intent.getExtras().containsKey(WALK_THROUGH_DATA)) + { + ArrayList tutorials = intent.getExtras().getParcelableArrayList(WALK_THROUGH_DATA); + + return tutorials; + } + + return new ArrayList<>(); + } } diff --git a/tutorial_view/src/main/java/com/braunster/tutorialview/view/TutorialLayout.java b/tutorial_view/src/main/java/com/braunster/tutorialview/view/TutorialLayout.java index 529b61e..0c7f27a 100644 --- a/tutorial_view/src/main/java/com/braunster/tutorialview/view/TutorialLayout.java +++ b/tutorial_view/src/main/java/com/braunster/tutorialview/view/TutorialLayout.java @@ -240,7 +240,7 @@ public void setWalkThroughListener(WalkThroughListener walkThroughListener) { @Override public void nextTutorial(Tutorial tutorial) { setTutorial(tutorial, true); - dispatchNextTutorialShown(); + dispatchNextTutorialShown(tutorial); } @Override @@ -327,9 +327,9 @@ private void dispatchWalkThroughSkipped(){ walkThroughListener.onWalkTroughSkipped(); } - private void dispatchNextTutorialShown(){ + private void dispatchNextTutorialShown(Tutorial tutorial){ if (walkThroughListener != null) - walkThroughListener.onNextTutorialShown(); + walkThroughListener.onNextTutorialShown(tutorial); } private void dispatchWalkThroughDone(){ @@ -340,7 +340,7 @@ private void dispatchWalkThroughDone(){ public interface WalkThroughListener { - public void onNextTutorialShown(); + public void onNextTutorialShown(Tutorial tutorial); public void onWalkTroughSkipped(); diff --git a/tutorial_view/src/main/res/values-v21/styles.xml b/tutorial_view/src/main/res/values-v21/styles.xml new file mode 100644 index 0000000..aac20df --- /dev/null +++ b/tutorial_view/src/main/res/values-v21/styles.xml @@ -0,0 +1,10 @@ + + + + diff --git a/tutorial_view/tutorial_view.iml b/tutorial_view/tutorial_view.iml index 3aaa42b..58f2bf1 100644 --- a/tutorial_view/tutorial_view.iml +++ b/tutorial_view/tutorial_view.iml @@ -1,5 +1,5 @@ - + @@ -9,10 +9,12 @@ + @@ -85,5 +88,4 @@ - - + \ No newline at end of file From 949ed9ef0164506ab8cfc0f62d70266d54c9f981 Mon Sep 17 00:00:00 2001 From: ItzikBraun Date: Sun, 3 May 2015 09:39:33 +0200 Subject: [PATCH 03/17] - Fixed error showing tutorial from previous commit. - Updated the version number and name --- .idea/dictionaries/braunster.xml | 7 +++ .idea/misc.xml | 2 +- README.md | 4 +- app/app.iml | 2 +- app/build.gradle | 15 ++++-- .../tutorialviewapp/MainActivity.java | 7 +++ app/src/main/res/layout/activity_main.xml | 12 +++++ tutorial_view/build.gradle | 16 +++++-- .../tutorialview/TutorialActivity.java | 46 ++++++++++--------- .../braunster/tutorialview/object/Debug.java | 10 ++++ .../object/TutorialIntentBuilder.java | 8 ++-- .../view/AbstractTutorialView.java | 8 ++-- .../tutorialview/view/RippleTutorialView.java | 10 ++-- tutorial_view/tutorial_view.iml | 2 +- 14 files changed, 103 insertions(+), 46 deletions(-) create mode 100644 .idea/dictionaries/braunster.xml create mode 100644 tutorial_view/src/main/java/com/braunster/tutorialview/object/Debug.java diff --git a/.idea/dictionaries/braunster.xml b/.idea/dictionaries/braunster.xml new file mode 100644 index 0000000..f9b2d78 --- /dev/null +++ b/.idea/dictionaries/braunster.xml @@ -0,0 +1,7 @@ + + + + braunster + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index e4a5fa4..e284b1d 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -13,7 +13,7 @@ - + diff --git a/README.md b/README.md index 6b54337..faf4837 100644 --- a/README.md +++ b/README.md @@ -92,12 +92,14 @@ dependencies { You can also copy past it to your project and before adding it to your dependencies you need to add it to *settings.gradle* so the system will understand it's a module like this: ``` -// Notice that in your settings file there would be more names so dont delete them, This are your other modules. +// Notice that in your settings file there would be more names so don't delete them, This are your other modules. include':tutorial_view' ``` ###TODO: * Return result when `TutorialActivity` finishes so you could know when it was done and if was skipped. +* add the roboto font family to the app assets so it will work on lower versions +* Make a sample app and publish it on Google Play ###Author [Itzik Braun - Google+](https://plus.google.com/+ItzikBraunster) diff --git a/app/app.iml b/app/app.iml index f3c7264..bdf7878 100644 --- a/app/app.iml +++ b/app/app.iml @@ -84,7 +84,7 @@ - + diff --git a/app/build.gradle b/app/build.gradle index 72706c0..a063628 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,16 +1,23 @@ apply plugin: 'com.android.application' +def versionMajor = 0 +def versionMinor = 8 +def versionPatch = 1 +def versionBuild = 0 // bump for dogfood builds, public betas, etc. + android { - compileSdkVersion 21 + compileSdkVersion 22 buildToolsVersion "21.1.2" defaultConfig { applicationId "com.braunster.tutorialviewapp" minSdkVersion 15 - targetSdkVersion 21 - versionCode 1 - versionName "1.0" + targetSdkVersion 22 + + versionCode versionMajor * 1000000 + versionMinor * 10000 + versionPatch * 100 + versionBuild + versionName "${versionMajor}.${versionMinor}.${versionPatch}" } + buildTypes { release { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' diff --git a/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java b/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java index 971b3b5..bd2f75b 100644 --- a/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java +++ b/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java @@ -6,6 +6,7 @@ import android.os.Bundle; import android.view.Menu; import android.view.View; +import android.widget.TextView; import com.braunster.tutorialview.object.Tutorial; import com.braunster.tutorialview.object.TutorialBuilder; @@ -30,6 +31,11 @@ protected void onCreate(Bundle savedInstanceState) { // getWindow().requestFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); + + // Setting the version name. + ((TextView) findViewById(R.id.txt_version)).setText(String.format("Version: %s", BuildConfig.VERSION_NAME)); + + tutorialView = (TutorialView) findViewById(R.id.tutorial_view); findViewById(R.id.view_bottom_left).setOnClickListener(this); @@ -41,6 +47,7 @@ protected void onCreate(Bundle savedInstanceState) { if (getActionBar() != null) getActionBar().setBackgroundDrawable(new ColorDrawable(Color.DKGRAY)); + //Using the tutorial view // This is used for the tutorial view that should be in your root view. // This may lead to problems when used inside LinearLayout and maybe other view. diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 7c71bfa..2be4f58 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -84,4 +84,16 @@ android:layout_marginTop="50dp" android:id="@+id/view_top_right"/> + + diff --git a/tutorial_view/build.gradle b/tutorial_view/build.gradle index 409ef72..e1d0d53 100644 --- a/tutorial_view/build.gradle +++ b/tutorial_view/build.gradle @@ -1,15 +1,23 @@ apply plugin: 'com.android.library' +def versionMajor = 0 +def versionMinor = 8 +def versionPatch = 1 +def versionBuild = 0 // bump for dogfood builds, public betas, etc. + + android { - compileSdkVersion 21 + compileSdkVersion 22 buildToolsVersion "21.1.2" defaultConfig { minSdkVersion 15 - targetSdkVersion 21 - versionCode 1 - versionName "0.7.1" + targetSdkVersion 22 + + versionCode versionMajor * 1000000 + versionMinor * 10000 + versionPatch * 100 + versionBuild + versionName "${versionMajor}.${versionMinor}.${versionPatch}" } + buildTypes { release { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' diff --git a/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialActivity.java b/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialActivity.java index c2e0e59..b67037f 100644 --- a/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialActivity.java +++ b/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialActivity.java @@ -5,6 +5,7 @@ import android.os.Bundle; import android.util.Log; +import com.braunster.tutorialview.object.Debug; import com.braunster.tutorialview.object.Tutorial; import com.braunster.tutorialview.object.TutorialIntentBuilder; import com.braunster.tutorialview.view.TutorialLayout; @@ -18,7 +19,7 @@ public class TutorialActivity extends Activity { public static final String TAG = TutorialActivity.class.getSimpleName(); - public static final boolean DEBUG = true; + public static final boolean DEBUG = Debug.TutorialActivity; private TutorialLayout mTutorialLayout; @@ -28,10 +29,14 @@ public class TutorialActivity extends Activity { private static final String CURRENT_TUTORIAL = "current_tutorial"; + private Bundle savedInstanceState; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + this.savedInstanceState = savedInstanceState; + setContentView(R.layout.activity_tutorial_layout); mTutorialLayout = (TutorialLayout) findViewById(R.id.tutorial_layout); @@ -45,6 +50,25 @@ protected void onCreate(Bundle savedInstanceState) { mTutorial = TutorialIntentBuilder.getTutorial(getIntent()); + // Finish the activity when the tutorial is closed. + mTutorialLayout.setTutorialClosedListener(new TutorialView.TutorialClosedListener() { + @Override + public void onClosed() { + finish(); + } + }); + + updateSystemUIColors(); + } + + /** + * Need to wait until the window get focused before doing the animation. + * Also it is good to post it. + * */ + @Override + public void onWindowFocusChanged(boolean hasFocus) { + super.onWindowFocusChanged(hasFocus); + if (TutorialIntentBuilder.isWalkThrough(getIntent())) { ArrayList tutorials = TutorialIntentBuilder.getWalkThroughData(getIntent()); @@ -77,26 +101,6 @@ protected void onCreate(Bundle savedInstanceState) { mTutorialLayout.setTutorial(mTutorial, false); } - - // Finish the activity when the tutorial is closed. - mTutorialLayout.setTutorialClosedListener(new TutorialView.TutorialClosedListener() { - @Override - public void onClosed() { - finish(); - } - }); - - updateSystemUIColors(); - } - - /** - * Need to wait until the window get focused before doing the animation. - * Also it is good to post it. - * */ - @Override - public void onWindowFocusChanged(boolean hasFocus) { - super.onWindowFocusChanged(hasFocus); - if (hasFocus && !mTutorialLayout.isShowing()) mTutorialLayout.post(new Runnable() { @Override diff --git a/tutorial_view/src/main/java/com/braunster/tutorialview/object/Debug.java b/tutorial_view/src/main/java/com/braunster/tutorialview/object/Debug.java new file mode 100644 index 0000000..e6cbf6f --- /dev/null +++ b/tutorial_view/src/main/java/com/braunster/tutorialview/object/Debug.java @@ -0,0 +1,10 @@ +package com.braunster.tutorialview.object; + +/** + * Created by braunster on 03.05.15. + */ +public class Debug { + + public static final boolean TutorialActivity = false; + public static final boolean TutorialIntentBuilder = false; +} diff --git a/tutorial_view/src/main/java/com/braunster/tutorialview/object/TutorialIntentBuilder.java b/tutorial_view/src/main/java/com/braunster/tutorialview/object/TutorialIntentBuilder.java index 08b2e04..ef5c872 100644 --- a/tutorial_view/src/main/java/com/braunster/tutorialview/object/TutorialIntentBuilder.java +++ b/tutorial_view/src/main/java/com/braunster/tutorialview/object/TutorialIntentBuilder.java @@ -18,7 +18,7 @@ public class TutorialIntentBuilder { public static final String TAG = TutorialIntentBuilder.class.getSimpleName(); - public static final boolean DEBUG = true; + public static final boolean DEBUG = Debug.TutorialIntentBuilder; private static final String TUTORIAL_OBJ = "tutorial_obj"; @@ -30,7 +30,7 @@ public class TutorialIntentBuilder { private static final String CHANGE_SYSTEM_UI_COLOR = "change_system_ui_colors"; - private Intent intent; + private final Intent intent; public TutorialIntentBuilder(Context context){ intent = new Intent(context, TutorialActivity.class ); @@ -193,9 +193,7 @@ public static Tutorial getTutorial(Intent intent){ public static ArrayList getWalkThroughData(Intent intent){ if (intent.getExtras().containsKey(WALK_THROUGH_DATA)) { - ArrayList tutorials = intent.getExtras().getParcelableArrayList(WALK_THROUGH_DATA); - - return tutorials; + return intent.getExtras().getParcelableArrayList(WALK_THROUGH_DATA); } return new ArrayList<>(); diff --git a/tutorial_view/src/main/java/com/braunster/tutorialview/view/AbstractTutorialView.java b/tutorial_view/src/main/java/com/braunster/tutorialview/view/AbstractTutorialView.java index 3eff875..2898a28 100644 --- a/tutorial_view/src/main/java/com/braunster/tutorialview/view/AbstractTutorialView.java +++ b/tutorial_view/src/main/java/com/braunster/tutorialview/view/AbstractTutorialView.java @@ -523,7 +523,7 @@ protected void drawInnerCircles(Canvas canvas){ /** * OnClickListener for hiding the tutorial when clicked. * */ - private OnClickListener closeTutorialClickListener = new OnClickListener() { + private final OnClickListener closeTutorialClickListener = new OnClickListener() { @Override public void onClick(View v) { closeTutorial(); @@ -533,7 +533,7 @@ public void onClick(View v) { /** * OnClickListener for skipping the walk through tutorial. * */ - private OnClickListener skipWalkThroughClickListener = new OnClickListener() { + private final OnClickListener skipWalkThroughClickListener = new OnClickListener() { @Override public void onClick(View v) { ((WalkThroughInterface) getParent()).skip(); @@ -782,9 +782,9 @@ && getParent() instanceof WalkThroughInterface } /** - * Posted on the tutorial info view to do ajustment and animation to the view. + * Posted on the tutorial info view to do adjustment and animation to the view. * */ - private Runnable tutorialInfoViewPost = new Runnable() { + private final Runnable tutorialInfoViewPost = new Runnable() { RelativeLayout.LayoutParams skipButtonParams = null; RelativeLayout.LayoutParams titleParams = null; diff --git a/tutorial_view/src/main/java/com/braunster/tutorialview/view/RippleTutorialView.java b/tutorial_view/src/main/java/com/braunster/tutorialview/view/RippleTutorialView.java index 3ca347d..29059e0 100644 --- a/tutorial_view/src/main/java/com/braunster/tutorialview/view/RippleTutorialView.java +++ b/tutorial_view/src/main/java/com/braunster/tutorialview/view/RippleTutorialView.java @@ -15,15 +15,15 @@ */ public class RippleTutorialView extends AbstractTutorialView { - public static final String TAG = RippleTutorialView.class.getSimpleName(); - public static final boolean DEBUG = false; + private static final String TAG = RippleTutorialView.class.getSimpleName(); + private static final boolean DEBUG = false; private int mAnimatedRadius = -1; private int mAnimationRadiusMax = -1; - private static PorterDuffXfermode sXfermodeClear = new PorterDuffXfermode(PorterDuff.Mode.CLEAR); - private static PorterDuffXfermode sXfermodeNormal = new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER); + private static final PorterDuffXfermode sXfermodeClear = new PorterDuffXfermode(PorterDuff.Mode.CLEAR); + private static final PorterDuffXfermode sXfermodeNormal = new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER); public RippleTutorialView(Context context) { super(context); @@ -76,6 +76,8 @@ protected boolean shouldDraw() { return super.shouldDraw() && showing && mAnimatedRadius != -1; } + // To remove a warning regrading using maxHeight as an x parameter. + @SuppressWarnings("all") @Override public void beforeFirstDraw(){ if (DEBUG) Log.d(TAG, "FirstDraw, Width: " + getMeasuredWidth() + ", Height: " + getMeasuredHeight()); diff --git a/tutorial_view/tutorial_view.iml b/tutorial_view/tutorial_view.iml index 58f2bf1..a7141ce 100644 --- a/tutorial_view/tutorial_view.iml +++ b/tutorial_view/tutorial_view.iml @@ -85,7 +85,7 @@ - + \ No newline at end of file From 5df0cbbbb53e354190266142f2cb007bbfc7ec22 Mon Sep 17 00:00:00 2001 From: ItzikBraun Date: Mon, 4 May 2015 12:53:27 +0200 Subject: [PATCH 04/17] - Added an orientation lock to the TutorialActivity, Meaning that the orientation that was used for the previous activity will persist until the TutorialActivity will exist. The calculation of which area to keep blank happens before the activity is shown thus it is not possible currently to handle the orientation change differently. If you are reading this and have another idea please share. Another way to do so for some edge cases is to specify the wanted orientation if has any in the manifest. --- .idea/dictionaries/braunster.xml | 1 + app/build.gradle | 6 --- .../tutorialview/TutorialActivity.java | 42 +++++++++++++++++++ 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/.idea/dictionaries/braunster.xml b/.idea/dictionaries/braunster.xml index f9b2d78..2fb5201 100644 --- a/.idea/dictionaries/braunster.xml +++ b/.idea/dictionaries/braunster.xml @@ -2,6 +2,7 @@ braunster + stackoverflow \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index a063628..e6a5341 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,12 +17,6 @@ android { versionCode versionMajor * 1000000 + versionMinor * 10000 + versionPatch * 100 + versionBuild versionName "${versionMajor}.${versionMinor}.${versionPatch}" } - - buildTypes { - release { - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } } dependencies { diff --git a/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialActivity.java b/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialActivity.java index b67037f..9a2cdeb 100644 --- a/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialActivity.java +++ b/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialActivity.java @@ -1,6 +1,8 @@ package com.braunster.tutorialview; import android.app.Activity; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; import android.os.Build; import android.os.Bundle; import android.util.Log; @@ -37,6 +39,8 @@ protected void onCreate(Bundle savedInstanceState) { this.savedInstanceState = savedInstanceState; + lockOrientation(); + setContentView(R.layout.activity_tutorial_layout); mTutorialLayout = (TutorialLayout) findViewById(R.id.tutorial_layout); @@ -186,4 +190,42 @@ private void updateSystemUIColors(){ } } } + + /** + * Locking the orientation so the activity will stay in the same orientation as it was entered. + * The position of the place that need to stay visible is pre-calculated so currently there + * is no other way to handle orientation changes. + * + * Code was taken from this stackoverflow answer: + * http://stackoverflow.com/a/8450316/2568492 + * */ + private void lockOrientation(){ + switch (getResources().getConfiguration().orientation){ + case Configuration.ORIENTATION_PORTRAIT: + if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.FROYO){ + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } else { + int rotation = getWindowManager().getDefaultDisplay().getRotation(); + if(rotation == android.view.Surface.ROTATION_90|| rotation == android.view.Surface.ROTATION_180){ + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); + } else { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } + } + break; + + case Configuration.ORIENTATION_LANDSCAPE: + if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.FROYO){ + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } else { + int rotation = getWindowManager().getDefaultDisplay().getRotation(); + if(rotation == android.view.Surface.ROTATION_0 || rotation == android.view.Surface.ROTATION_90){ + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + } else { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); + } + } + break; + } + } } From 72d07059a9501d69f89781f30a00800483124836 Mon Sep 17 00:00:00 2001 From: ItzikBraun Date: Thu, 7 May 2015 09:41:26 +0200 Subject: [PATCH 05/17] - Added an option to get a result from the tutorial, The result will proved feedback of how the user handled the tutorial or walkthrough. - Updated the README file. --- .idea/dictionaries/braunster.xml | 1 + README.md | 20 ++++-- app/build.gradle | 2 +- .../tutorialviewapp/MainActivity.java | 59 +++++++++++++++- .../tutorialview/TutorialActivity.java | 69 +++++++++++++++++-- .../tutorialview/view/TutorialLayout.java | 4 +- 6 files changed, 140 insertions(+), 15 deletions(-) diff --git a/.idea/dictionaries/braunster.xml b/.idea/dictionaries/braunster.xml index 2fb5201..ddc8d0a 100644 --- a/.idea/dictionaries/braunster.xml +++ b/.idea/dictionaries/braunster.xml @@ -3,6 +3,7 @@ braunster stackoverflow + walkthrough \ No newline at end of file diff --git a/README.md b/README.md index faf4837..7c46093 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,17 @@ ![alt tag](http://raw.github.com/ItzikBraun/TutorialView/master/screen_shots/example.gif) -An Android library project providing `Activity` with explanation about views in your app. +An Android library project providing `Activity` with an explanation about views in your app. -The `TutorialActivity` can be used as a walk through for the entire screen that is currently visible, Or just for one view on the screen. +The `TutorialActivity` can be used as a walkthrough for the entire screen that is currently visible, Or just for one view on the screen. To get the intent to start the `TutorialActivity` you need to use the `TutorialIntentBuilder`, The builder will help you build the intent to start the activity, You would have to pass a `Tutorial` object to the intent builder. +If you use any kind of analytics to track your user behavior in your app you can start the `TutorialActivity` for result and +so when it returns you can collect the data whether the user skipped the tutorials or watched it fully. +You can also retrieve the amount of tutorials the user have viewed before skipping the walkthrough using `TutorialActivity.VIEWED_TUTORIALS`. + ###Usage ####Tutorial The tutorial object holds the tutorial info and attributes. You can create a Tutorial by using the `TutorialBuilder`. @@ -23,11 +27,16 @@ You can customize the following: * TypefaceName - The path to the wanted typeface to use for all text view in the tutorial, Example: "/fonts/arial.ttf". * AnimationDuration - the duration time in milliseconds that will be used for the animation. * InfoPosition - The position of the info text, This could be Above, Below, LeftOf and Right of all relevant to the view that need to be surrounded. Values are stored in `Tutorial.InfoPosition` -* GotItPosition - The position of the "GotIt" button, This could be Top(If has title it will be below it) and Bottom. Values are stored in `Tutorial.GotItPosition` +* GotItPosition - The position of the "GotIt" button, This could be Top(If has a title it will be below it) and Bottom. Values are stored in `Tutorial.GotItPosition` * ~~AnimationType - the animation that will be used for showing and hiding the tutorial~~ This is a work in progress currently not working. -Each tutorial that was passed holds it's position on screen, title, background color, the text explenation and more customizable attributes. +Each tutorial that was passed holds it's position on the screen, title, background color, the text explanation and more customizable attributes. +By default the "StatusBar" and the "NavigationBar" are also being colored on Lollipop devices, You can change the default behavior by using: +``` +TutorialIntentBuilder builder = new TutorialIntentBuilder(MainActivity.this); +builder.changeSystemUiColor(false); +``` ######Example of creating a simple tutorial. ``` java @@ -92,12 +101,11 @@ dependencies { You can also copy past it to your project and before adding it to your dependencies you need to add it to *settings.gradle* so the system will understand it's a module like this: ``` -// Notice that in your settings file there would be more names so don't delete them, This are your other modules. +// Notice that in your settings file there would be more names so don't delete them, Those are your other modules. include':tutorial_view' ``` ###TODO: -* Return result when `TutorialActivity` finishes so you could know when it was done and if was skipped. * add the roboto font family to the app assets so it will work on lower versions * Make a sample app and publish it on Google Play diff --git a/app/build.gradle b/app/build.gradle index e6a5341..21aa771 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' def versionMajor = 0 def versionMinor = 8 -def versionPatch = 1 +def versionPatch = 2 def versionBuild = 0 // bump for dogfood builds, public betas, etc. android { diff --git a/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java b/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java index bd2f75b..bfc913d 100644 --- a/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java +++ b/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java @@ -1,13 +1,16 @@ package com.braunster.tutorialviewapp; import android.app.Activity; +import android.content.Intent; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.widget.TextView; +import android.widget.Toast; +import com.braunster.tutorialview.TutorialActivity; import com.braunster.tutorialview.object.Tutorial; import com.braunster.tutorialview.object.TutorialBuilder; import com.braunster.tutorialview.object.TutorialIntentBuilder; @@ -20,6 +23,11 @@ public class MainActivity extends Activity implements View.OnClickListener { private TutorialView tutorialView; + private static final int TUTORIAL_REQUEST = 1991; + + // For switching between startActivityForResult and startActivity + private boolean startTutorialForResult = false; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -72,6 +80,40 @@ public boolean onCreateOptionsMenu(Menu menu) { return true; } + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + if (requestCode == TUTORIAL_REQUEST) + { + boolean isWalkThrough = data.getBooleanExtra(TutorialActivity.IS_WALKTHROUGH, false); + + if (resultCode == RESULT_OK) + { + if (isWalkThrough) + Toast.makeText(this, "The walkthrough was viewed fully", Toast.LENGTH_SHORT).show(); + else + Toast.makeText(this, "The user GotIt", Toast.LENGTH_SHORT).show(); + } + else if (resultCode == RESULT_CANCELED) + { + if (isWalkThrough) + { + Toast.makeText(this, + String.format("Tutorial was skipped, User viewed %s Tutorials", data.getIntExtra(TutorialActivity.VIEWED_TUTORIALS, 0)), + Toast.LENGTH_SHORT).show(); + } + else + { + Toast.makeText(this, + "Tutorial was skipped" , + Toast.LENGTH_SHORT).show(); + } + + } + } + } + private int randomColor(){ Random rnd = new Random(); return Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256)); @@ -105,6 +147,9 @@ public void onClick(View v) { TutorialIntentBuilder builder = new TutorialIntentBuilder(MainActivity.this); + // if true the status bar and navigation bar will be colored on Lollipop devices. + builder.changeSystemUiColor(true); + TutorialBuilder tBuilder = getBasicBuilderForTest(v); switch (v.getId()) @@ -144,7 +189,10 @@ public void onClick(View v) { builder.setTutorial(tBuilder.build()); - startActivity(builder.getIntent()); + if (startTutorialForResult) + startActivityForResult(builder.getIntent(), TUTORIAL_REQUEST); + else + startActivity(builder.getIntent()); // Override the default animation of the entering activity. // This will allow the nice wrapping of the view by the tutorial activity. @@ -185,8 +233,15 @@ public void run() { TutorialIntentBuilder builder = new TutorialIntentBuilder(MainActivity.this); + // if true the status bar and navigation bar will be colored on Lollipop devices. + builder.changeSystemUiColor(true); + builder.setWalkThroughList(t1, t2, t3, t4, t5); - startActivity(builder.getIntent()); + + if (startTutorialForResult) + startActivityForResult(builder.getIntent(), TUTORIAL_REQUEST); + else + startActivity(builder.getIntent()); // Override the default animation of the entering activity. // This will allow the nice wrapping of the view by the tutorial activity. diff --git a/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialActivity.java b/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialActivity.java index 9a2cdeb..2e4db5c 100644 --- a/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialActivity.java +++ b/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialActivity.java @@ -1,6 +1,7 @@ package com.braunster.tutorialview; import android.app.Activity; +import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.os.Build; @@ -10,6 +11,7 @@ import com.braunster.tutorialview.object.Debug; import com.braunster.tutorialview.object.Tutorial; import com.braunster.tutorialview.object.TutorialIntentBuilder; +import com.braunster.tutorialview.view.AbstractTutorialView; import com.braunster.tutorialview.view.TutorialLayout; import com.braunster.tutorialview.view.TutorialView; @@ -33,6 +35,8 @@ public class TutorialActivity extends Activity { private Bundle savedInstanceState; + public static final String VIEWED_TUTORIALS= "viewed_tutorials", IS_WALKTHROUGH = "is_tutorial"; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -55,10 +59,11 @@ protected void onCreate(Bundle savedInstanceState) { mTutorial = TutorialIntentBuilder.getTutorial(getIntent()); // Finish the activity when the tutorial is closed. + // In case the tutorial view is showing a walkthrough this would be ignored. mTutorialLayout.setTutorialClosedListener(new TutorialView.TutorialClosedListener() { @Override public void onClosed() { - finish(); + resultDone(); } }); @@ -130,12 +135,12 @@ public void onNextTutorialShown(Tutorial tutorial) { @Override public void onWalkTroughSkipped() { - finish(); + resultSkipped(); } @Override public void onWalkThroughDone() { - finish(); + resultDone(); } }); } @@ -164,11 +169,26 @@ protected void onSaveInstanceState(Bundle outState) { * */ @Override public void onBackPressed() { - if (TutorialIntentBuilder.skipOnBackPressed(getIntent())) + // Skipping the walkthrough if requested. + if (mTutorialLayout.isWalkThrough() && TutorialIntentBuilder.skipOnBackPressed(getIntent())) { mTutorialLayout.skip(); } - else mTutorialLayout.closeTutorial(); + else { + // Setting a new TutorialCloseListener so we could return + // a result to the calling activity that the tutorial was closed using the back press. + if (!mTutorialLayout.isWalkThrough()) + { + mTutorialLayout.setTutorialClosedListener(new AbstractTutorialView.TutorialClosedListener() { + @Override + public void onClosed() { + resultSkipped(); + } + }); + } + + mTutorialLayout.closeTutorial(); + } } private void updateSystemUIColors(){ @@ -228,4 +248,43 @@ private void lockOrientation(){ break; } } + + private void resultSkipped(){ + + if (getCallingActivity() != null) + { + Intent intent = getResultIntent(); + + // Adding the amount of tutorials that was shown before skipping. + if (mTutorialLayout.isWalkThrough()){ + intent.putExtra(VIEWED_TUTORIALS, mCurrentTutorialPos); + } + + setResult(RESULT_CANCELED, intent); + } + + finish(); + } + + private void resultDone(){ + + if (getCallingActivity() != null) + { + Intent intent = getResultIntent(); + setResult(RESULT_OK, intent); + } + + + finish(); + } + + private Intent getResultIntent(){ + + + Intent intent = new Intent(); + + intent.putExtra(IS_WALKTHROUGH, mTutorialLayout.isWalkThrough()); + + return intent; + } } diff --git a/tutorial_view/src/main/java/com/braunster/tutorialview/view/TutorialLayout.java b/tutorial_view/src/main/java/com/braunster/tutorialview/view/TutorialLayout.java index 0c7f27a..c0225cf 100644 --- a/tutorial_view/src/main/java/com/braunster/tutorialview/view/TutorialLayout.java +++ b/tutorial_view/src/main/java/com/braunster/tutorialview/view/TutorialLayout.java @@ -102,7 +102,9 @@ public void setActionBar(ActionBar actionBar) { } /** - * Set the listener on the tutorial view, If walk through is used this will be overriden and you should set a {@link com.braunster.tutorialview.view.TutorialLayout.WalkThroughListener WalkThroughListener} instead. + * Set the listener on the tutorial view, + * If walk through is used this will be overridden and you should set a + * {@link com.braunster.tutorialview.view.TutorialLayout.WalkThroughListener WalkThroughListener} instead. * * @see #setWalkThroughListener(com.braunster.tutorialview.view.TutorialLayout.WalkThroughListener) * */ From 1f3ba038a63039016ade42373d9ea185a8039b03 Mon Sep 17 00:00:00 2001 From: Itzik Braun Date: Mon, 25 May 2015 16:35:26 +0200 Subject: [PATCH 06/17] README update, Added Jit Badge --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 7c46093..1a64435 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-TutorialView-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/1408) + +[![Release](https://img.shields.io/github/release/itzikBraun/TutorialView.svg?label=JitPack)](https://jitpack.io/#itzikBraun/TutorialView) + ##TutorialView [![Join the chat at https://gitter.im/itzikBraun/TutorialView](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/itzikBraun/TutorialView?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) From dc03d210bcb8758dfae742c4343f1787afcf3de2 Mon Sep 17 00:00:00 2001 From: ItzikBraun Date: Tue, 9 Jun 2015 14:16:44 +0200 Subject: [PATCH 07/17] - Small code cleaning - Updated the README file(Added explanation how to get the library from maven central). --- .idea/misc.xml | 2 +- README.md | 18 +- app/app.iml | 39 +++-- app/build.gradle | 24 ++- .../tutorialviewapp/ApplicationTest.java | 13 -- .../tutorialviewapp/MainActivityTest.java | 155 ++++++++++++++++++ .../tutorialviewapp/MainActivity.java | 6 +- build.gradle | 12 +- gradle.properties | 18 +- tutorial_view/build.gradle | 6 +- .../tutorialview/TutorialInterface.java | 21 ++- .../object/TutorialIntentBuilder.java | 7 +- .../view/AbstractTutorialView.java | 2 +- tutorial_view/tutorial_view.iml | 25 +-- 14 files changed, 290 insertions(+), 58 deletions(-) delete mode 100644 app/src/androidTest/java/com/braunster/tutorialviewapp/ApplicationTest.java create mode 100644 app/src/androidTest/java/com/braunster/tutorialviewapp/MainActivityTest.java diff --git a/.idea/misc.xml b/.idea/misc.xml index e284b1d..e4a5fa4 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -13,7 +13,7 @@ - + diff --git a/README.md b/README.md index 7c46093..a00920b 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,12 @@ [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-TutorialView-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/1408) -##TutorialView +[![Release](https://img.shields.io/github/release/itzikBraun/TutorialView.svg?label=JitPack)](https://jitpack.io/#itzikBraun/TutorialView) + +TutorialView +=============== [![Join the chat at https://gitter.im/itzikBraun/TutorialView](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/itzikBraun/TutorialView?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Release](https://img.shields.io/github/release/itzikBraun/TutorialView.svg?label=JitPack)](https://jitpack.io/#itzikBraun/TutorialView) ![alt tag](http://raw.github.com/ItzikBraun/TutorialView/master/screen_shots/example.gif) An Android library project providing `Activity` with an explanation about views in your app. @@ -91,7 +95,17 @@ overridePendingTransition(R.anim.dummy, R.anim.dummy); ``` ###INCLUDING IN YOUR PROJECT -Import the "tutorial_view" module to your project, Then in your build.gradle file add this.(You probably already have the *dependencies* so just add the "*compile project(':tutorial_view')*" ). +######From Maven Central + +Add as a dependency to your build.gradle: + +dependencies{ + compile 'com.github.itzikbraun:TutorialView:0.8.1' +} + +######Downloading the source code +Import the "tutorial_view" module to your project, +Then in your build.gradle file add this.(You probably already have the *dependencies* so just add the "*compile project(':tutorial_view')*" ). ``` dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) diff --git a/app/app.iml b/app/app.iml index bdf7878..9d99127 100644 --- a/app/app.iml +++ b/app/app.iml @@ -13,9 +13,9 @@ - + @@ -35,12 +35,12 @@ - - - - - - + + + + + + @@ -69,6 +69,11 @@ + + + + + @@ -86,6 +91,20 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 21aa771..cb670c2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,23 +3,43 @@ apply plugin: 'com.android.application' def versionMajor = 0 def versionMinor = 8 def versionPatch = 2 -def versionBuild = 0 // bump for dogfood builds, public betas, etc. +def versionBuild = 2 // bump for dogfood builds, public betas, etc. android { compileSdkVersion 22 - buildToolsVersion "21.1.2" + buildToolsVersion "22.0.1" defaultConfig { applicationId "com.braunster.tutorialviewapp" minSdkVersion 15 targetSdkVersion 22 + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + + versionCode versionMajor * 1000000 + versionMinor * 10000 + versionPatch * 100 + versionBuild versionName "${versionMajor}.${versionMinor}.${versionPatch}" } + + packagingOptions { + + exclude 'META-INF/LICENSE.txt' + exclude 'LICENSE.txt' + } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile project(':tutorial_view') + + + // App dependencies + compile 'com.android.support:support-annotations:22.1.0' + + androidTestCompile 'com.android.support:support-annotations:22.1.0' + + // Testing-only dependencies + androidTestCompile 'com.android.support.test:runner:0.2' + androidTestCompile 'com.android.support.test:rules:0.2' + androidTestCompile 'com.android.support.test.espresso:espresso-core:2.1' } diff --git a/app/src/androidTest/java/com/braunster/tutorialviewapp/ApplicationTest.java b/app/src/androidTest/java/com/braunster/tutorialviewapp/ApplicationTest.java deleted file mode 100644 index 577d1ac..0000000 --- a/app/src/androidTest/java/com/braunster/tutorialviewapp/ApplicationTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.braunster.tutorialviewapp; - -import android.app.Application; -import android.test.ApplicationTestCase; - -/** - * Testing Fundamentals - */ -public class ApplicationTest extends ApplicationTestCase { - public ApplicationTest() { - super(Application.class); - } -} \ No newline at end of file diff --git a/app/src/androidTest/java/com/braunster/tutorialviewapp/MainActivityTest.java b/app/src/androidTest/java/com/braunster/tutorialviewapp/MainActivityTest.java new file mode 100644 index 0000000..f663087 --- /dev/null +++ b/app/src/androidTest/java/com/braunster/tutorialviewapp/MainActivityTest.java @@ -0,0 +1,155 @@ +package com.braunster.tutorialviewapp; + +import android.content.Intent; +import android.graphics.Color; +import android.test.ActivityInstrumentationTestCase2; +import android.test.TouchUtils; +import android.test.suitebuilder.annotation.SmallTest; +import android.view.View; + +import com.braunster.tutorialview.TutorialActivity; +import com.braunster.tutorialview.object.Tutorial; +import com.braunster.tutorialview.object.TutorialBuilder; +import com.braunster.tutorialview.object.TutorialIntentBuilder; + +import java.util.Random; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; + +/** + * Created by braunster on 08.05.15. + */ +public class MainActivityTest extends ActivityInstrumentationTestCase2 { + + MainActivity activity; + + TutorialActivity tutorialActivity; + + private boolean startTutorialForResult = false; + + public MainActivityTest() { + super(MainActivity.class); + } + + @Override + public void setUp() throws Exception { + super.setUp(); + + activity = getActivity(); + } + + @SmallTest + public void testWalkThrough(){ + + assertNotNull(activity); + + onView(withText("T")).check(matches(isDisplayed())); + + startWalkThrough(); + + checkWalkThroughOpen(); + } + + @SmallTest + public void testClick(){ + TouchUtils.clickView(this, activity.findViewById(R.id.view_almost_top_right)); + + + onView(withId(R.id.view_almost_top_right)).check(doesNotExist()); + } + + + + + public void checkWalkThroughOpen(){ + + // Tutorial should be open thus the button should not exist. + onView(withText("T")).check(doesNotExist()); + + assertNotNull(tutorialActivity); + + try { + runTestOnUiThread(new Runnable() { + @Override + public void run() { + getInstrumentation().callActivityOnDestroy(tutorialActivity); + + getInstrumentation().callActivityOnResume(activity); + + onView(withText("T")).check(matches(isDisplayed())); + } + }); + } catch (Throwable throwable) { + throwable.printStackTrace(); + } + + } + + public void startWalkThrough(){ + + + Tutorial t1 = getBasicBuilderForTest(activity.findViewById(R.id.view_bottom_left)) + .setTutorialInfoTextPosition(Tutorial.InfoPosition.ABOVE) + .setTutorialGotItPosition(Tutorial.GotItPosition.BOTTOM) + .build(); + + Tutorial t2 = getBasicBuilderForTest(activity.findViewById(R.id.view_top_right)) + .setTutorialInfoTextPosition(Tutorial.InfoPosition.LEFT_OF) + .build(); + + Tutorial t3 = getBasicBuilderForTest(activity.findViewById(R.id.view_almost_top_right)) + .setTutorialInfoTextPosition(Tutorial.InfoPosition.RIGHT_OF) + .build(); + + Tutorial t4 = getBasicBuilderForTest(activity.findViewById(R.id.view_top_left)) + .setTutorialInfoTextPosition(Tutorial.InfoPosition.BELOW) + .build(); + + Tutorial t5 = getBasicBuilderForTest(activity.findViewById(R.id.view_center)) + .setTutorialInfoTextPosition(Tutorial.InfoPosition.BELOW) + .setTutorialGotItPosition(Tutorial.GotItPosition.BOTTOM) + .build(); + + + final TutorialIntentBuilder builder = new TutorialIntentBuilder(activity); + + // if true the status bar and navigation bar will be colored on Lollipop devices. + builder.changeSystemUiColor(true); + + builder.setWalkThroughList(t1, t2, t3, t4, t5); + + final Intent intent = builder.getIntent(); + intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); + + tutorialActivity = (TutorialActivity) getInstrumentation().startActivitySync(intent); + + assertNotNull(tutorialActivity); + + assertEquals(tutorialActivity.getClass(), TutorialActivity.class); + } + + private TutorialBuilder getBasicBuilderForTest(View v){ + TutorialBuilder tBuilder = new TutorialBuilder(); + + tBuilder.setTitle("The Title") + .setViewToSurround(v) + .setInfoText("This is the explanation about the view.") + .setBackgroundColor(randomColor()) + .setTutorialTextColor(Color.WHITE) + .setTutorialTextTypeFaceName("fonts/olivier.ttf") + .setTutorialTextSize(30) + .setAnimationDuration(500); + + return tBuilder; + } + + private int randomColor(){ + Random rnd = new Random(); + return Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256)); + } +} diff --git a/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java b/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java index bfc913d..8d2f0d4 100644 --- a/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java +++ b/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java @@ -69,8 +69,8 @@ protected void onCreate(Bundle savedInstanceState) { tutorialView.setTutorialText("This is some general text that is not that long but also not so short."); // Only show the walk through when the activity is first created. - if (savedInstanceState == null) - startWalkThrough(); +// if (savedInstanceState == null) +// startWalkThrough(); } @Override @@ -199,7 +199,7 @@ public void onClick(View v) { overridePendingTransition(R.anim.dummy, R.anim.dummy); } - private void startWalkThrough(){ + public void startWalkThrough(){ // Running a walk through as the activity is opened, Tutorial // building should be wrapped in a runnable that is posted so diff --git a/build.gradle b/build.gradle index 6356aab..05e2bc1 100644 --- a/build.gradle +++ b/build.gradle @@ -3,17 +3,21 @@ buildscript { repositories { jcenter() + mavenCentral() + } dependencies { - classpath 'com.android.tools.build:gradle:1.0.0' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files + classpath 'com.android.tools.build:gradle:1.2.3' } } + allprojects { + repositories { jcenter() + mavenCentral() } } + + diff --git a/gradle.properties b/gradle.properties index 1d3591c..a33f991 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,4 +15,20 @@ # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true \ No newline at end of file +# org.gradle.parallel=true + + +VERSION_NAME=0.8.2 +VERSION_CODE=82 +GROUP=com.github.itzikbraun + +POM_DESCRIPTION=A showcase library +POM_URL=https://github.com/itzikBraun/TutorialView +POM_SCM_URL=https://github.com/itzikBraun/TutorialView +POM_SCM_CONNECTION=scm:git@github.com:itzikbraun/TutorialView.git +POM_SCM_DEV_CONNECTION=scm:git@github.com:itzikbraun/TutorialView.git +POM_LICENCE_NAME=The Apache Software License, Version 2.0 +POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt +POM_LICENCE_DIST=repo +POM_DEVELOPER_ID=ItzikBraun +POM_DEVELOPER_NAME=Itzik Braun diff --git a/tutorial_view/build.gradle b/tutorial_view/build.gradle index e1d0d53..57251eb 100644 --- a/tutorial_view/build.gradle +++ b/tutorial_view/build.gradle @@ -5,6 +5,7 @@ def versionMinor = 8 def versionPatch = 1 def versionBuild = 0 // bump for dogfood builds, public betas, etc. +version = "${versionMajor}.${versionMinor}.${versionPatch}" android { compileSdkVersion 22 @@ -15,7 +16,7 @@ android { targetSdkVersion 22 versionCode versionMajor * 1000000 + versionMinor * 10000 + versionPatch * 100 + versionBuild - versionName "${versionMajor}.${versionMinor}.${versionPatch}" + versionName version } buildTypes { @@ -25,6 +26,9 @@ android { } } + dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) } + +apply from: 'https://raw.github.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle' diff --git a/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialInterface.java b/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialInterface.java index 9ce2d03..22434e8 100644 --- a/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialInterface.java +++ b/tutorial_view/src/main/java/com/braunster/tutorialview/TutorialInterface.java @@ -10,6 +10,8 @@ public interface TutorialInterface { /** * The Layout id of the view that will be used to show the tutorial text or information. + * + * @param tutorialInfoLayoutId the id of the layout that should be used for the info text. * */ public void setTutorialInfoLayoutId(int tutorialInfoLayoutId); @@ -17,6 +19,8 @@ public interface TutorialInterface { /** * The background color for the tutorial. + * + * @param mTutorialBackgroundColor the backgrond color to use for the background * */ public void setTutorialBackgroundColor(int mTutorialBackgroundColor); @@ -24,7 +28,9 @@ public interface TutorialInterface { /** * The text that will be used for the {@link com.braunster.tutorialview.view.TutorialView#mTutorialInfoView mTutorialInfoView}. - * Only if the layout that is used is the default layout ({@link com.braunster.tutorialview.R.layout#tutorial_text tutorial_text}). + * Only if the layout that is used is the default layout com.braunster.tutorialview.R.layout#tutorial_text. + * + * @param tutorialText The explenation text about the view. * * @see com.braunster.tutorialview.view.TutorialView#setTutorialTextTypeFace(String) * @see com.braunster.tutorialview.view.TutorialView#setTutorialTextColor(int) @@ -39,6 +45,8 @@ public interface TutorialInterface { * Set the size that will be used for the default info view text view. * The size of the title and other button won't be changed. * + * @param mTutorialTextSize the size that would be used for the info text. + * * @see com.braunster.tutorialview.view.TutorialView#setTutorialText(String) * @see com.braunster.tutorialview.view.TutorialView#setTutorialTextColor(int) * @see com.braunster.tutorialview.view.TutorialView#setTutorialTextTypeFace(String) @@ -49,10 +57,11 @@ public interface TutorialInterface { public int getTutorialTextSize(); /** - * Set the color that will be used for the default info view text view. + * @param mTutorialTextColor the color that will be used for the default info view text view. * * This color will also be used for the "Got It" button. * + * * @see com.braunster.tutorialview.view.TutorialView#setTutorialTextSize(int) * @see com.braunster.tutorialview.view.TutorialView#setTutorialText(String) * @see com.braunster.tutorialview.view.TutorialView#setTutorialTextTypeFace(String) @@ -63,7 +72,7 @@ public interface TutorialInterface { public int getTutorialTextColor(); /** - * Set the typeface that will be used for the default info view text view. + * @param tutorialTextTypeFaceName the typeface name that will be used for the default info view text view. * * @see com.braunster.tutorialview.view.TutorialView#setTutorialTextSize(int) * @see com.braunster.tutorialview.view.TutorialView#setTutorialText(String) @@ -75,14 +84,14 @@ public interface TutorialInterface { public String getTutorialTextTypeFace(); /** - * Setting the animation type that will be used to show and hide the tutorial. + * @param animationType the animation type that will be used to show and hide the tutorial. * */ - public void setAnimationType(AbstractTutorialView.AnimationType mAnimationType); + public void setAnimationType(AbstractTutorialView.AnimationType animationType); public AbstractTutorialView.AnimationType getAnimationType(); /** - * Set the time that will be used for the animation + * @param duration the time that will be used for the animation * */ public void setAnimationDuration(long duration); diff --git a/tutorial_view/src/main/java/com/braunster/tutorialview/object/TutorialIntentBuilder.java b/tutorial_view/src/main/java/com/braunster/tutorialview/object/TutorialIntentBuilder.java index ef5c872..6246eee 100644 --- a/tutorial_view/src/main/java/com/braunster/tutorialview/object/TutorialIntentBuilder.java +++ b/tutorial_view/src/main/java/com/braunster/tutorialview/object/TutorialIntentBuilder.java @@ -17,8 +17,8 @@ */ public class TutorialIntentBuilder { - public static final String TAG = TutorialIntentBuilder.class.getSimpleName(); - public static final boolean DEBUG = Debug.TutorialIntentBuilder; + private static final String TAG = TutorialIntentBuilder.class.getSimpleName(); + private static final boolean DEBUG = Debug.TutorialIntentBuilder; private static final String TUTORIAL_OBJ = "tutorial_obj"; @@ -46,7 +46,8 @@ public TutorialIntentBuilder(Intent intent){ } /** - * Change the color of the status and navigation bars on devices running API 21 (Lollipop) and up. + * @param change if true changes the color of the status and navigation + * bars on devices running API 21 (Lollipop) and up. * * * */ public TutorialIntentBuilder changeSystemUiColor(boolean change){ intent.putExtra(CHANGE_SYSTEM_UI_COLOR, change); diff --git a/tutorial_view/src/main/java/com/braunster/tutorialview/view/AbstractTutorialView.java b/tutorial_view/src/main/java/com/braunster/tutorialview/view/AbstractTutorialView.java index 2898a28..b54f20c 100644 --- a/tutorial_view/src/main/java/com/braunster/tutorialview/view/AbstractTutorialView.java +++ b/tutorial_view/src/main/java/com/braunster/tutorialview/view/AbstractTutorialView.java @@ -626,7 +626,7 @@ public void setHasActionBar(boolean hasActionBar){ /** * The text that will be used for the {@link TutorialView#mTutorialInfoView mTutorialInfoView}. - * Only if the layout that is used is the default layout ({@link com.braunster.tutorialview.R.layout#tutorial_text tutorial_text}). + * Only if the layout that is used is the default layout R.layout.tutorial_text. * * @see TutorialView#setTutorialTextTypeFace(String) * @see TutorialView#setTutorialTextColor(int) diff --git a/tutorial_view/tutorial_view.iml b/tutorial_view/tutorial_view.iml index a7141ce..632620d 100644 --- a/tutorial_view/tutorial_view.iml +++ b/tutorial_view/tutorial_view.iml @@ -1,5 +1,5 @@ - + @@ -13,9 +13,9 @@ - + @@ -36,12 +36,12 @@ - - - - - - + + + + + + @@ -63,6 +63,7 @@ + @@ -82,7 +83,9 @@ + + From da8a1bf61d3155daf38f46fdd8b756956cf5f35f Mon Sep 17 00:00:00 2001 From: ItzikBraun Date: Tue, 9 Jun 2015 14:22:33 +0200 Subject: [PATCH 08/17] - Removed double jitPack badge --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index a00920b..069121d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,6 @@ TutorialView =============== [![Join the chat at https://gitter.im/itzikBraun/TutorialView](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/itzikBraun/TutorialView?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Release](https://img.shields.io/github/release/itzikBraun/TutorialView.svg?label=JitPack)](https://jitpack.io/#itzikBraun/TutorialView) ![alt tag](http://raw.github.com/ItzikBraun/TutorialView/master/screen_shots/example.gif) An Android library project providing `Activity` with an explanation about views in your app. From c9e7a0e230642cd6fc4df5b4e07e21f78b51ba89 Mon Sep 17 00:00:00 2001 From: Itzik Braun Date: Thu, 11 Jun 2015 09:45:28 +0200 Subject: [PATCH 09/17] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 069121d..676fc31 100644 --- a/README.md +++ b/README.md @@ -98,9 +98,11 @@ overridePendingTransition(R.anim.dummy, R.anim.dummy); Add as a dependency to your build.gradle: +```` dependencies{ compile 'com.github.itzikbraun:TutorialView:0.8.1' } +```` ######Downloading the source code Import the "tutorial_view" module to your project, From 6f8a82ddeafe288e18789c371f2cb4b02e9f5ac4 Mon Sep 17 00:00:00 2001 From: ibraun Date: Wed, 26 Aug 2015 19:54:20 +0200 Subject: [PATCH 10/17] - Fixed issue #11, now (should have been done before) checking for null typeface --- .../main/java/com/braunster/tutorialviewapp/MainActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java b/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java index 8d2f0d4..04bd6d1 100644 --- a/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java +++ b/app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java @@ -135,7 +135,7 @@ private TutorialBuilder getBasicBuilderForTest(View v){ .setInfoText("This is the explanation about the view.") .setBackgroundColor(randomColor()) .setTutorialTextColor(Color.WHITE) - .setTutorialTextTypeFaceName("fonts/olivier.ttf") +// .setTutorialTextTypeFaceName("fonts/roboto_light.ttf") .setTutorialTextSize(30) .setAnimationDuration(500); From 7b79eceb9132c1f955972ec6a2c2f9dcfbe646c4 Mon Sep 17 00:00:00 2001 From: Michael Basil Date: Wed, 26 Aug 2015 19:19:51 +0100 Subject: [PATCH 11/17] Remove Android Studio files --- .gitignore | 48 +++++++++++ .idea/.name | 1 - .idea/compiler.xml | 22 ------ .idea/copyright/profiles_settings.xml | 3 - .idea/dictionaries/braunster.xml | 9 --- .idea/gradle.xml | 20 ----- .idea/misc.xml | 22 ------ .idea/modules.xml | 10 --- .idea/vcs.xml | 6 -- TutorialView.iml | 19 ----- TutorialViewApp.iml | 21 ----- app/app.iml | 110 -------------------------- tutorial_view/tutorial_view.iml | 94 ---------------------- 13 files changed, 48 insertions(+), 337 deletions(-) delete mode 100644 .idea/.name delete mode 100644 .idea/compiler.xml delete mode 100644 .idea/copyright/profiles_settings.xml delete mode 100644 .idea/dictionaries/braunster.xml delete mode 100644 .idea/gradle.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml delete mode 100644 TutorialView.iml delete mode 100644 TutorialViewApp.iml delete mode 100644 app/app.iml delete mode 100644 tutorial_view/tutorial_view.iml diff --git a/.gitignore b/.gitignore index afbdab3..50f0b56 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,51 @@ /.idea/libraries .DS_Store /build + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio + +*.iml + +## Directory-based project format: +.idea/ +# if you remove the above rule, at least ignore the following: + +# User-specific stuff: +# .idea/workspace.xml +# .idea/tasks.xml +# .idea/dictionaries + +# Sensitive or high-churn files: +# .idea/dataSources.ids +# .idea/dataSources.xml +# .idea/sqlDataSources.xml +# .idea/dynamic.xml +# .idea/uiDesigner.xml + +# Gradle: +# .idea/gradle.xml +# .idea/libraries + +# Mongo Explorer plugin: +# .idea/mongoSettings.xml + +## File-based project format: +*.ipr +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index 9c740f3..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -TutorialView \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index 96cc43e..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml deleted file mode 100644 index e7bedf3..0000000 --- a/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/.idea/dictionaries/braunster.xml b/.idea/dictionaries/braunster.xml deleted file mode 100644 index ddc8d0a..0000000 --- a/.idea/dictionaries/braunster.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - braunster - stackoverflow - walkthrough - - - \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index c7e984d..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index e4a5fa4..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 59b16af..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/TutorialView.iml b/TutorialView.iml deleted file mode 100644 index 746a30d..0000000 --- a/TutorialView.iml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/TutorialViewApp.iml b/TutorialViewApp.iml deleted file mode 100644 index 5550340..0000000 --- a/TutorialViewApp.iml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/app/app.iml b/app/app.iml deleted file mode 100644 index 9d99127..0000000 --- a/app/app.iml +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tutorial_view/tutorial_view.iml b/tutorial_view/tutorial_view.iml deleted file mode 100644 index 632620d..0000000 --- a/tutorial_view/tutorial_view.iml +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 70f0a6eaedd10a836f62127b250a9703409e6e43 Mon Sep 17 00:00:00 2001 From: Michael Basil Date: Wed, 26 Aug 2015 19:21:18 +0100 Subject: [PATCH 12/17] Move TutorialActivity declaration into the library --- app/src/main/AndroidManifest.xml | 3 --- tutorial_view/src/main/AndroidManifest.xml | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9e0eee0..21b5f7e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -17,9 +17,6 @@ - - diff --git a/tutorial_view/src/main/AndroidManifest.xml b/tutorial_view/src/main/AndroidManifest.xml index 8e63cac..69e1a15 100644 --- a/tutorial_view/src/main/AndroidManifest.xml +++ b/tutorial_view/src/main/AndroidManifest.xml @@ -3,6 +3,9 @@ + + From 4fe18cc1abc91dab801665699bfd4b96e08b7dfe Mon Sep 17 00:00:00 2001 From: Michael Basil Date: Wed, 26 Aug 2015 19:24:49 +0100 Subject: [PATCH 13/17] Remove resources that shouldn't be in a library --- tutorial_view/src/main/AndroidManifest.xml | 3 +-- .../src/main/res/drawable-hdpi/ic_launcher.png | Bin 9397 -> 0 bytes .../src/main/res/drawable-mdpi/ic_launcher.png | Bin 5237 -> 0 bytes .../src/main/res/drawable-xhdpi/ic_launcher.png | Bin 14383 -> 0 bytes .../main/res/drawable-xxhdpi/ic_launcher.png | Bin 19388 -> 0 bytes tutorial_view/src/main/res/values/strings.xml | 1 - 6 files changed, 1 insertion(+), 3 deletions(-) delete mode 100644 tutorial_view/src/main/res/drawable-hdpi/ic_launcher.png delete mode 100644 tutorial_view/src/main/res/drawable-mdpi/ic_launcher.png delete mode 100644 tutorial_view/src/main/res/drawable-xhdpi/ic_launcher.png delete mode 100644 tutorial_view/src/main/res/drawable-xxhdpi/ic_launcher.png diff --git a/tutorial_view/src/main/AndroidManifest.xml b/tutorial_view/src/main/AndroidManifest.xml index 69e1a15..f720c10 100644 --- a/tutorial_view/src/main/AndroidManifest.xml +++ b/tutorial_view/src/main/AndroidManifest.xml @@ -1,8 +1,7 @@ - + diff --git a/tutorial_view/src/main/res/drawable-hdpi/ic_launcher.png b/tutorial_view/src/main/res/drawable-hdpi/ic_launcher.png deleted file mode 100644 index 96a442e5b8e9394ccf50bab9988cb2316026245d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9397 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 diff --git a/tutorial_view/src/main/res/drawable-xhdpi/ic_launcher.png b/tutorial_view/src/main/res/drawable-xhdpi/ic_launcher.png deleted file mode 100644 index 71c6d760f05183ef8a47c614d8d13380c8528499..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14383 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 diff --git a/tutorial_view/src/main/res/drawable-xxhdpi/ic_launcher.png b/tutorial_view/src/main/res/drawable-xxhdpi/ic_launcher.png deleted file mode 100644 index 4df18946442ed763bd52cf3adca31617848656fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19388 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 diff --git a/tutorial_view/src/main/res/values/strings.xml b/tutorial_view/src/main/res/values/strings.xml index d3c349f..3b38fc7 100644 --- a/tutorial_view/src/main/res/values/strings.xml +++ b/tutorial_view/src/main/res/values/strings.xml @@ -1,5 +1,4 @@ - TutorialView Got It Skip From 1a74a1ac81f3c86ee8d9d10da97b56abbc9a38b1 Mon Sep 17 00:00:00 2001 From: ibraun Date: Mon, 7 Sep 2015 20:25:45 +0200 Subject: [PATCH 14/17] Fixed issue #11 NPE when not setting the typeface --- app/.gitignore | 53 +++++++++++++++++++ app/build.gradle | 12 ++--- .../tutorialviewapp/MainActivityTest.java | 2 +- build.gradle | 5 ++ tutorial_view/.gitignore | 53 +++++++++++++++++++ tutorial_view/build.gradle | 10 ++-- .../view/AbstractTutorialView.java | 44 +++++++-------- 7 files changed, 144 insertions(+), 35 deletions(-) diff --git a/app/.gitignore b/app/.gitignore index 796b96d..50f0b56 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -1 +1,54 @@ +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store /build + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio + +*.iml + +## Directory-based project format: +.idea/ +# if you remove the above rule, at least ignore the following: + +# User-specific stuff: +# .idea/workspace.xml +# .idea/tasks.xml +# .idea/dictionaries + +# Sensitive or high-churn files: +# .idea/dataSources.ids +# .idea/dataSources.xml +# .idea/sqlDataSources.xml +# .idea/dynamic.xml +# .idea/uiDesigner.xml + +# Gradle: +# .idea/gradle.xml +# .idea/libraries + +# Mongo Explorer plugin: +# .idea/mongoSettings.xml + +## File-based project format: +*.ipr +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties diff --git a/app/build.gradle b/app/build.gradle index cb670c2..bdde61c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,13 +6,13 @@ def versionPatch = 2 def versionBuild = 2 // bump for dogfood builds, public betas, etc. android { - compileSdkVersion 22 - buildToolsVersion "22.0.1" + compileSdkVersion 23 + buildToolsVersion "23.0.0" defaultConfig { applicationId "com.braunster.tutorialviewapp" minSdkVersion 15 - targetSdkVersion 22 + targetSdkVersion 23 testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" @@ -32,12 +32,6 @@ dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile project(':tutorial_view') - - // App dependencies - compile 'com.android.support:support-annotations:22.1.0' - - androidTestCompile 'com.android.support:support-annotations:22.1.0' - // Testing-only dependencies androidTestCompile 'com.android.support.test:runner:0.2' androidTestCompile 'com.android.support.test:rules:0.2' diff --git a/app/src/androidTest/java/com/braunster/tutorialviewapp/MainActivityTest.java b/app/src/androidTest/java/com/braunster/tutorialviewapp/MainActivityTest.java index f663087..326f47c 100644 --- a/app/src/androidTest/java/com/braunster/tutorialviewapp/MainActivityTest.java +++ b/app/src/androidTest/java/com/braunster/tutorialviewapp/MainActivityTest.java @@ -141,7 +141,7 @@ private TutorialBuilder getBasicBuilderForTest(View v){ .setInfoText("This is the explanation about the view.") .setBackgroundColor(randomColor()) .setTutorialTextColor(Color.WHITE) - .setTutorialTextTypeFaceName("fonts/olivier.ttf") + .setTutorialTextTypeFaceName("fonts/roboto-light.ttf") .setTutorialTextSize(30) .setAnimationDuration(500); diff --git a/build.gradle b/build.gradle index 05e2bc1..1da0039 100644 --- a/build.gradle +++ b/build.gradle @@ -17,6 +17,11 @@ allprojects { repositories { jcenter() mavenCentral() + + } + // Fix for a conflict with support library that included with espresso + configurations.all { + resolutionStrategy.force 'com.android.support:support-annotations:23.0.0' } } diff --git a/tutorial_view/.gitignore b/tutorial_view/.gitignore index 796b96d..50f0b56 100644 --- a/tutorial_view/.gitignore +++ b/tutorial_view/.gitignore @@ -1 +1,54 @@ +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store /build + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio + +*.iml + +## Directory-based project format: +.idea/ +# if you remove the above rule, at least ignore the following: + +# User-specific stuff: +# .idea/workspace.xml +# .idea/tasks.xml +# .idea/dictionaries + +# Sensitive or high-churn files: +# .idea/dataSources.ids +# .idea/dataSources.xml +# .idea/sqlDataSources.xml +# .idea/dynamic.xml +# .idea/uiDesigner.xml + +# Gradle: +# .idea/gradle.xml +# .idea/libraries + +# Mongo Explorer plugin: +# .idea/mongoSettings.xml + +## File-based project format: +*.ipr +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties diff --git a/tutorial_view/build.gradle b/tutorial_view/build.gradle index 57251eb..b8dc1c6 100644 --- a/tutorial_view/build.gradle +++ b/tutorial_view/build.gradle @@ -8,12 +8,12 @@ def versionBuild = 0 // bump for dogfood builds, public betas, etc. version = "${versionMajor}.${versionMinor}.${versionPatch}" android { - compileSdkVersion 22 - buildToolsVersion "21.1.2" + compileSdkVersion 23 + buildToolsVersion "23.0.0" defaultConfig { minSdkVersion 15 - targetSdkVersion 22 + targetSdkVersion 23 versionCode versionMajor * 1000000 + versionMinor * 10000 + versionPatch * 100 + versionBuild versionName version @@ -29,6 +29,8 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) + + compile 'com.android.support:support-annotations:23.0.0' } -apply from: 'https://raw.github.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle' +//apply from: 'https://raw.github.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle' diff --git a/tutorial_view/src/main/java/com/braunster/tutorialview/view/AbstractTutorialView.java b/tutorial_view/src/main/java/com/braunster/tutorialview/view/AbstractTutorialView.java index b54f20c..c75c05a 100644 --- a/tutorial_view/src/main/java/com/braunster/tutorialview/view/AbstractTutorialView.java +++ b/tutorial_view/src/main/java/com/braunster/tutorialview/view/AbstractTutorialView.java @@ -8,6 +8,8 @@ import android.graphics.RectF; import android.graphics.Typeface; import android.graphics.drawable.ColorDrawable; +import android.support.annotation.NonNull; +import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; @@ -154,7 +156,7 @@ public AbstractTutorialView(Context context, AttributeSet attrs, int defStyleAtt } public interface TutorialClosedListener{ - public void onClosed(); + void onClosed(); } public abstract void closeTutorial(); @@ -292,8 +294,8 @@ public void setTutorial(Tutorial tutorial, boolean show){ protected void onDraw(Canvas canvas) { super.onDraw(canvas); - if (isInEditMode()) - return; + /*if (isInEditMode()) + return;*/ /* // No need to draw if does not have any view to surround, // Or the view size is null (in case we do not use a view but only its coordinates). @@ -342,10 +344,9 @@ protected void inflateTutorialInfo(){ // Inflating the "Got It" button. mGotItButton = inflate(getContext(), R.layout.got_it_button_view, null); ((TextView) mGotItButton).setTextColor(mTutorial.getTutorialTextColor()); - if (mTutorialTextTypeFace != null) - { - ((TextView) mGotItButton).setTypeface(mTutorialTextTypeFace); - } + + + setTypeFaceOnTextView(((TextView) mGotItButton)); // Adding skip button if the tutorial is a part of a Walkthrough. if (isWalkThrough()) @@ -353,10 +354,8 @@ protected void inflateTutorialInfo(){ // Inflating the "Skip" button. mSkipButton = inflate(getContext(), R.layout.skip_button_view, null); ((TextView) mSkipButton).setTextColor(mTutorial.getTutorialTextColor()); - if (mTutorialTextTypeFace != null) - { - ((TextView) mSkipButton).setTypeface(mTutorialTextTypeFace); - } + + setTypeFaceOnTextView(((TextView) mSkipButton)); } // Inflating the Title for the tutorial if has any. @@ -365,11 +364,8 @@ protected void inflateTutorialInfo(){ mTitleView = inflate(getContext(), R.layout.title_view, null); ((TextView) mTitleView).setTextColor(mTutorial.getTutorialTextColor()); ((TextView) mTitleView).setText(mTutorial.getTitle()); - - if (mTutorialTextTypeFace != null) - { - ((TextView) mTitleView).setTypeface(mTutorialTextTypeFace); - } + + setTypeFaceOnTextView(((TextView) mTitleView)); } mTutorialInfoView.post(tutorialInfoViewPost); @@ -401,10 +397,7 @@ private void checkTutorialDefault(){ txtTutorial.setTextColor(mTutorial.getTutorialTextColor()); - if (mTutorialTextTypeFace != null) - { - txtTutorial.setTypeface(mTutorialTextTypeFace); - } + setTypeFaceOnTextView((txtTutorial)); } } @@ -463,7 +456,10 @@ protected void dispatchTutorialClosed(){ * Initialize the type face object from the mTutorial object type face name. ***/ protected void initTypeFace (){ - mTutorialTextTypeFace = Typeface.createFromAsset(getResources().getAssets(), mTutorial.getTutorialTextTypeFace()); + if (!TextUtils.isEmpty(mTutorial.getTutorialTextTypeFace())){ + mTutorialTextTypeFace = + Typeface.createFromAsset(getResources().getAssets(), mTutorial.getTutorialTextTypeFace()); + } } protected void initActionBar(String title){ @@ -1015,4 +1011,10 @@ private void animate(){ animation.start(); } }; + + private void setTypeFaceOnTextView(@NonNull TextView textView){ + if (mTutorialTextTypeFace != null){ + textView.setTypeface(mTutorialTextTypeFace); + } + } } From de5ab6271135abdb27143d14d7ad74ff62dd577a Mon Sep 17 00:00:00 2001 From: Itzik Braun Date: Mon, 7 Sep 2015 20:37:20 +0200 Subject: [PATCH 15/17] Delete olivier.ttf Removed unused font, Can use Roboto for testing --- tutorial_view/src/main/assets/fonts/olivier.ttf | Bin 61220 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tutorial_view/src/main/assets/fonts/olivier.ttf diff --git a/tutorial_view/src/main/assets/fonts/olivier.ttf b/tutorial_view/src/main/assets/fonts/olivier.ttf deleted file mode 100644 index 6d56f7113dab265b80a4fc6971edb5181163863b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61220 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 hlK$DX>%r&Ur{90a^X|Uy_S^1w?hEdC-W_ Date: Tue, 27 Oct 2015 10:58:58 +0100 Subject: [PATCH 16/17] [DEBUG] Place information view above below to surround if in top half of screen --- .../com/braunster/tutorialview/view/AbstractTutorialView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorial_view/src/main/java/com/braunster/tutorialview/view/AbstractTutorialView.java b/tutorial_view/src/main/java/com/braunster/tutorialview/view/AbstractTutorialView.java index c75c05a..4f134e9 100644 --- a/tutorial_view/src/main/java/com/braunster/tutorialview/view/AbstractTutorialView.java +++ b/tutorial_view/src/main/java/com/braunster/tutorialview/view/AbstractTutorialView.java @@ -909,7 +909,7 @@ private void autoInfoPosition(){ // The view to surround is in the top half of the screen so the info will be below it. if (isTopHalf) { - placeInfoAbove(); + placeInfoBelow(); } // The view to surround is in the bottom half of the screen. else { From 0a1c35649c79d878da6c1ddb09082abb6908c1df Mon Sep 17 00:00:00 2001 From: Santiago Castro Date: Sun, 16 Apr 2017 20:57:40 -0300 Subject: [PATCH 17/17] Fix broken Markdown headings --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 676fc31..97ce610 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,8 @@ If you use any kind of analytics to track your user behavior in your app you can so when it returns you can collect the data whether the user skipped the tutorials or watched it fully. You can also retrieve the amount of tutorials the user have viewed before skipping the walkthrough using `TutorialActivity.VIEWED_TUTORIALS`. -###Usage -####Tutorial +### Usage +#### Tutorial The tutorial object holds the tutorial info and attributes. You can create a Tutorial by using the `TutorialBuilder`. You can customize the following: * Title - Will appear on the top of the view, If the view that is surrounded is on top it will be shown below it. @@ -40,7 +40,7 @@ TutorialIntentBuilder builder = new TutorialIntentBuilder(MainActivity.this); builder.changeSystemUiColor(false); ``` -######Example of creating a simple tutorial. +###### Example of creating a simple tutorial. ``` java TutorialIntentBuilder builder = new TutorialIntentBuilder(MainActivity.this); @@ -64,7 +64,7 @@ startActivity(builder.getIntent()); // This will allow the nice wrapping of the view by the tutorial activity. overridePendingTransition(R.anim.dummy, R.anim.dummy); ``` -######Example of creating a walk through from two Tutorials. +###### Example of creating a walk through from two Tutorials. ```java ArrayList tutorials = new ArrayList<>(); @@ -82,7 +82,7 @@ startActivity(builder.getIntent()); overridePendingTransition(R.anim.dummy, R.anim.dummy); ``` -####Important! +#### Important! You should override the `Activity` pending transition animation like this, If you wont override it the `TutorialActivity` would animate itself in and will ruin the view animation. (Call it after you call `startActivity(Intent)` ). @@ -93,8 +93,8 @@ overridePendingTransition(R.anim.dummy, R.anim.dummy); ``` -###INCLUDING IN YOUR PROJECT -######From Maven Central +### INCLUDING IN YOUR PROJECT +###### From Maven Central Add as a dependency to your build.gradle: @@ -104,7 +104,7 @@ dependencies{ } ```` -######Downloading the source code +###### Downloading the source code Import the "tutorial_view" module to your project, Then in your build.gradle file add this.(You probably already have the *dependencies* so just add the "*compile project(':tutorial_view')*" ). ``` @@ -120,14 +120,14 @@ You can also copy past it to your project and before adding it to your dependenc include':tutorial_view' ``` -###TODO: +### TODO: * add the roboto font family to the app assets so it will work on lower versions * Make a sample app and publish it on Google Play -###Author +### Author [Itzik Braun - Google+](https://plus.google.com/+ItzikBraunster) -###LICENSE +### LICENSE Copyright (C) 2014 Itzik Braun This program is free software: you can redistribute it and/or modify