Libraries

Android Creating App Walkthrough : Feature Discovery

android material design guide feature discovery
Written by Yasir Ameen

As Google introducing many new design concept time to time , one of them is “Feature Discovery” which is available with different names on internet like “Material Tap Target Prompt“, “Tap TargetView” and others. Feature Discovery prompt about different features available in app by showing you a nice circular animation. 

Installing A Library

Create a blank project name it whatever you want and paste following in your build.gradle file.

    repositories { 
        jcenter()
   }

   dependencies {
         compile 'com.getkeepsafe.taptargetview:taptargetview:1.4.1'
   }

 

Let’s See How Its Look Like

 

Understanding How Feature Discovery Works!

So before starting implementation, keep in mind that there are two ways you can use this feature, which is

  1. Single Prompt Feature Discovery
    Single prompt is that, you only want to show prompt once on a single view.

  2. Prompting With Sequence (One after another)
    Sequence is like that, you have multiple feature in your app and you want to tell about these to the user one by one.

 

Designing A Layout For Single Target View

Create two activity in your project, one is for single tap target which will be our landing acitivity and second one for dashboard activity, in which will demonstrate sequence prompting behaviour.

Layout For activity_main.xml file.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="invision.app.appwalkthrough.MainActivity">

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:src="@drawable/ic_add_white_24dp"
        android:layout_margin="16dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"/>

    <TextView
        android:text="Single Tap Target View"
        android:textColor="#000"
        android:textSize="28sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="113dp"
        android:id="@+id/textView3"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />

    <TextView
        android:text="Just Demonstrating a Single Tap Behaviour"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView3"
        android:layout_marginTop="5dp"
        android:layout_centerHorizontal="true"
        android:id="@+id/textView4" />

</RelativeLayout>

above xml code will display follwing result

android tap target material desing feature discovery

 

 

Implementing Single Tap Target

Open MainActivity.java and paste following code. The code itself is very easy but i wll make it clear for you.
You use Tap Target for single view with TapTargetView.showfor(…) method. You also specify onTargetClickListener() for doing something when user clicks.

Tip : Use onTargetClickListener() for save boolean into sharedPreference to make sure its not start again when app launch second time.

 


public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        SharedPreferences sharedPref = this.getSharedPreferences("SINGLE_TAP_TARGET", Context.MODE_PRIVATE);
        final SharedPreferences.Editor editor = sharedPref.edit();


        boolean isSingleTapFinished = sharedPref.getBoolean("isFinished",false);
        if(!isSingleTapFinished) {


            TapTargetView.showFor(this,
                    TapTarget.forView(findViewById(R.id.fab),
                            "This is a single tap target",
                            "You can access your dashboard anytime by tapping this button.")
                            .transparentTarget(true),
                    new TapTargetView.Listener() {          // The listener can listen for regular clicks, long clicks or cancels
                        @Override
                        public void onTargetClick(TapTargetView view) {
                            super.onTargetClick(view);      // This call is optional

                            editor.putBoolean("isFinished",true);
                            editor.commit();
                        }
                    });

        }
        
        findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                startActivity(new Intent(MainActivity.this,DashboardActivity.class));
            }
        });
    }
}

Designing A Layout For Sequence

Create an empty acitivty and name it Dashboard Activity, open its xml file and paste following code.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_dashboard"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="invision.app.appwalkthrough.DashboardActivity">

    <RelativeLayout
        android:id="@+id/custom_appbar"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:background="@drawable/background_blue">

        <LinearLayout
            android:layout_margin="10dp"
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:gravity="center"
            android:layout_height="56dp">
            
            <ImageView
                android:id="@+id/drawaer"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight=".1"
                android:tint="#fff"
                android:src="@drawable/ic_reorder_white_24dp"/>
            
            <View
                android:layout_width="0dp"
                android:layout_weight=".7"
                android:layout_height="wrap_content"/>
            
            <ImageView
                android:layout_width="0dp"
                android:layout_weight=".1"
                android:tint="#fff"
                android:id="@+id/search"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_search_white_24dp"/>
            
            <ImageView
                android:layout_width="0dp"
                android:layout_weight=".1"
                android:tint="#fff"
                android:id="@+id/more"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_more_vert_black_24dp"/>
            
        </LinearLayout>
        

    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/layer_blue"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:padding="10dp"
        android:layout_below="@id/custom_appbar"
        android:background="@color/blueAccent">


        <TextView
            android:text="Demo of Tap Target View"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/colorWhite"
            android:textSize="14sp"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:id="@+id/textView" />

        <TextView
            android:text="This is an example of feature discovery by Google"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_marginTop="18dp"
            android:textSize="12sp"
            android:textColor="@color/colorWhite"
            android:id="@+id/textView2" />
        
    </RelativeLayout>

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="8dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_below="@id/layer_blue" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:src="@drawable/ic_add_white_24dp"
        android:layout_margin="16dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"/>
    

</RelativeLayout>

 

This is the result of above xml.

android tap target material desing feature discovery

 

Implementing Sequence Tap Target On Views

Open DasboardActivity.java and paste following code.You use Sequence Targets for views by instantiating TapTargetSequence() class. The .targets() method takes views as argument by TapTarget.forView() including with other options. You also specify onSequenceFinish() Listener .

Tip : Use onSequenceFinish() for save boolean into sharedPreference to make sure its not start again when app launch second time.

 

public class DashboardActivity extends AppCompatActivity {

    TapTargetSequence sequence;
    private ListView lv;
    String[] data = {

            "Sput Hockey Fantasy",
            "Happy Birthday Balls",
            "Got Spotify Premium",
            "Any Rockers On Tonight",
            "Friends of Distinction",
            "Life In Your Way",
            "The Marshall Tucker Band",
            "The Temptations",
            "Bruce Springsteen",
            "Simon and Garfunkel"
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dashboard);

        SharedPreferences sharedPref = this.getSharedPreferences("SEQUENCE_TAP_TARGET", Context.MODE_PRIVATE);
        final SharedPreferences.Editor editor = sharedPref.edit();
        getSupportActionBar().hide();

        
        lv = (ListView) findViewById(R.id.list);
        lv.setAdapter(new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,data));


         sequence = new TapTargetSequence(this)
                .targets(

                      TapTarget.forView(findViewById(R.id.drawaer),"This is an app drawer","You can access others menu items here.")
                        .outerCircleColor(R.color.coloSky)
                        .targetCircleColor(R.color.coloBlack)
                        .titleTextColor(R.color.coloBlack)
                        .transparentTarget(true),
                      TapTarget.forView(findViewById(R.id.search),"Searching songs","You can find number of songs available in your library.")
                              .outerCircleColor(R.color.colorWhite)
                              .targetCircleColor(R.color.colorPrimary)
                              .titleTextColor(R.color.coloBlack),
                      TapTarget.forView(findViewById(R.id.more),"More menus","This will give you quick access to perform useful actions."),
                      TapTarget.forView(findViewById(R.id.fab),"Adding a song","You can add songs to your library by tapping this button")
                        .transparentTarget(true)
                        .outerCircleColor(R.color.colorAccent)

                ).listener(new TapTargetSequence.Listener() {
                    @Override
                    public void onSequenceFinish() {

                        editor.putBoolean("finished",true);
                        editor.commit();

                    }

                    @Override
                    public void onSequenceCanceled() {

                        editor.putBoolean("finished",true);
                        editor.commit();
                    }
                });

        boolean isSequenceFinished = sharedPref.getBoolean("finished",false);

        if(!isSequenceFinished) {

            sequence.start();

        }
        
    }
}

Its all done, run the app and see the results.

-InvisionCustomSolution.

 

 

About the author

Yasir Ameen

I'm a programmer, teacher, and speaker. I work out of my home in Pakistan, Karachi for the Mobile, especially Android Platform. I discuss about technology, gadgets, codes, the devices we’re going and we’ve been. I’m excited about community, social equity, and media.

Leave a Comment