Skip to content

Commit

Permalink
- Added an option to get a result from the tutorial, The result will …
Browse files Browse the repository at this point in the history
…proved feedback of how the user handled the tutorial or walkthrough.

- Updated the README file.
  • Loading branch information
itzikBraun committed May 7, 2015
1 parent 5df0cbb commit 72d0705
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 15 deletions.
1 change: 1 addition & 0 deletions .idea/dictionaries/braunster.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
59 changes: 57 additions & 2 deletions app/src/main/java/com/braunster/tutorialviewapp/MainActivity.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;

Expand All @@ -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);
Expand All @@ -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();
}
});

Expand Down Expand Up @@ -130,12 +135,12 @@ public void onNextTutorialShown(Tutorial tutorial) {

@Override
public void onWalkTroughSkipped() {
finish();
resultSkipped();
}

@Override
public void onWalkThroughDone() {
finish();
resultDone();
}
});
}
Expand Down Expand Up @@ -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(){
Expand Down Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
* */
Expand Down

0 comments on commit 72d0705

Please sign in to comment.