TapTargetView for Android Tutorial

Make sure your users don’t miss new features in your app by learning how to highlight them using the TapTargetView library for Android. By Abdalla Ali.

Leave a rating/review
Download materials
Save for later
Share

Releasing a new feature for your app sounds exciting, and you can’t wait to have your users use it. But what if your users didn’t use that feature at all, or worst case they don’t even know that the feature exists in your app. That sounds pretty scary, right?

You don’t have to be afraid though because today you will learn how you can highlight that new feature with an explanation. Your users will understand what the feature is and what its function is, and this will help you build a positive relationship with them.

You will be using a third party library named TapTargetView. You can use this library to help you to better highlight your app features to your users. You will build an app called What2eat where you will learn the following things:

  • How to add the TapTargetView library to your project.
  • How you can use the TapTargetView library to highlight menu items on the Android Toolbar, AlertDialog buttons, and standard Android buttons.
  • How you can highlight a feature to your users only once so that you don’t annoy them every time they use your app.

Prerequisites: This tutorial assumes that you have the basics of Android development with Kotlin under your belt. If you’re new to Android Development, please go through Beginning Android Development with Kotlin to understand the basics. If you’re new to Kotlin, please check out this introduction to Kotlin tutorial.

Getting Started

Download the starter project using the download button at the top or bottom of the tutorial. Open up Android Studio 3.0.1 or later, select the second option Open an existing Android Studio project and navigate to and select the starter project folder.

Android studio welcome page

Once the initial Gradle build is complete, build and run the app to see the current state of the app.

The first screen shows you a list of yummy food inside a RecyclerView.

what2eat screen

Note: If you’re new to Android Recyclerview, please go through Android RecyclerView Tutorial with Kotlin to understand the basics.

You have a Settings screen that you can access from the app menu that shows the app icon and version:

what2eat setting page

Tap a food item on the first screen to show a detail screen:

what2eat screen

From the detail screen, you can share the food item or tap on “Visit Store” to open your device browser to this link: https://www.freshdirect.com/index.jsp

what2eat intent chooser

what2eat visit store

Adding the TapTargetView Dependency

Open the build.gradle (Module:app) file to add the TapTargetView library dependency.

dependencies {
  ...
  implementation 'com.getkeepsafe.taptargetview:taptargetview:1.11.0'
}

Click on Sync now to sync your project Gradle files and so you’re able to use these libraries.

Android studio project sync

Now let’s get started working with TapTargetView.

Working with TapTargetView

In this section, you will learn how you can use the library with Toolbar, AlertDialog, and ImageView items.

TapTargetView with a Toolbar

First you’ll learn how you can use TapTargetView to highlight menu items on a Toolbar.

Open up MainActivity and add the following code below this line

recyclerView.adapter = FoodAdapter(this, foodName, foodImage)
// 1
TapTargetView.showFor(this,
    // 2
    TapTarget.forToolbarOverflow(toolbar, getString(R.string.label_app_settings),
        getString(R.string.description_app_setting))
        // 3
        .cancelable(false)
        // 4
        .tintTarget(true),
    // 5
    object : TapTargetView.Listener() {
      override fun onTargetClick(view: TapTargetView) {
        super.onTargetClick(view)
        view.dismiss(true)
      }
    })

Use Alt+Enter on PC or Option+Return on Mac to pull in the necessary imports.

Let’s go through this code step by step:

  1. TapTargetView.showFor: You always start with this, and you pass the current Context as the first argument.
  2. TapTarget.forToolbarOverflow: Here you choose to highlight the overflow menu item by passing these three arguments: the Toolbar that has the overflow menu item, the title of the menu item, and a simple description about the function of the menu item.
  3. cancelable(boolean): You pass a boolean value (true) if you want to dismiss the highlight circle when tapping on an empty area or (false) to prevent that from happening.
  4. tintTarget(boolean): You pass a boolean value (true) if you want to tint the view’s icon color or (false) if you want to make it white.
  5. TapTargetView.Listener: Here is where you write the logic that you want to execute when you tap on the overflow menu item. Otherwise you can dismiss the highlight circle using view.dismiss(true)

Build and run the app to TapTargetView in action on the Toolbar.

what2eat overflow highlight

It looks cool right! :]

Now go ahead and create a highlight circle for the search menu item by adding the following code below the highlight circle for the overflow menu item.

TapTargetView.showFor(this, TapTarget.forToolbarMenuItem(toolbar, R.id.action_search,
    getString(R.string.label_search), getString(R.string.description_search))
    .cancelable(false).tintTarget(true), object : TapTargetView.Listener() {
  override fun onTargetClick(view: TapTargetView) {
    super.onTargetClick(view)
    view.dismiss(true)
  }
})

Here you use TapTarget.forToolbarMenuItem because you want the highlight circle to appear on the search menu icon. When you tap on the search menu icon you will dismiss the highlight circle.

Build and run the app to see the output.

what2eat search highlight

TapTargetView with an AlertDialog

In this section, you will learn how you can use TapTargetView to show a highlight circle inside an AlertDialog.

Open up MainActivity and add the following method below onCreate().

override fun onBackPressed() {
  // 1
  val alertDialog = AlertDialog.Builder(this).create()
  // 2
  alertDialog.setMessage("Are you sure you want to exit ${resources.getString(R.string.app_name)}")
  // 3
  alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, getString(R.string.label_ok),
      { _, _ ->
        val intent = Intent(Intent.ACTION_MAIN)
        intent.addCategory(Intent.CATEGORY_HOME)
        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
        startActivity(intent)
      })
  // 4
  alertDialog.setButton(AlertDialog.BUTTON_NEGATIVE, getString(R.string.label_no),
      { dialogInterface, _ ->
        dialogInterface.dismiss()
      })
  // 5
  alertDialog.show()
  // 6
  TapTargetView.showFor(alertDialog,
      // 7
      TapTarget.forView(alertDialog.getButton(DialogInterface.BUTTON_POSITIVE),
          getString(R.string.label_exit_app),
          getString(R.string.description_exit))
          .cancelable(false).tintTarget(false), object : TapTargetView.Listener() {
    // 8        
    override fun onTargetClick(view: TapTargetView) {
      super.onTargetClick(view)
      view.dismiss(true)
    }
  })
}

Here’s a step-by-step breakdown:

You’ve overridden onBackPressed(), so that when you tap on your device physical back button, it will show an AlertDialog with the highlight circle.

  1. val alertDialog: You define an AlertDialog.
  2. alertDialog.setMessage: You give the AlertDialog a message.
  3. alertDialog.setButton: You give the AlertDialog a positive button, once you tap on that button you will exit the app.
  4. alertDialog.setButton: You give the AlertDialog a negative button, and once you tap on that button, you will dismiss the dialog.
  5. alertDialog.show(): You need to call show() for the dialog to appear on the device screen.
  6. TapTargetView.showFor: Here you want to show the highlight circle on the AlertDialog.
  7. TapTarget.forView: You use this method to show the highlight circle on the positive button of the AlertDialog.
  8. override fun onTargetClick(...): You dismiss the highlight circle on the first tap of the positive button.

Build and run the app, then tap on the physical device back button to see the new highlight circle.

what2eat dialog highlight

TapTargetView with an ImageView

In this section, you will learn how you can use TapTargetView to show a highlight circle on an ImageView.

Open up SettingsActivity and add the following code at the bottom of the onCreate() function.

TapTargetView.showFor(this, TapTarget.forView(ivAppIcon, getString(R.string.label_icon),
    "This is the icon that is currently being used for ${tvAppName.text}").
    tintTarget(false).cancelable(false), object : TapTargetView.Listener() {
  override fun onTargetClick(view: TapTargetView) {
    super.onTargetClick(view)
    view.dismiss(true)
  }
})

Here you show the highlight circle on ivAppIcon, and you can dismiss the highlight circle once you tap on it.

Build and run the app and go to the Settings screen to see the result.

what2eat setting highlight

TapTargetSequence on Multiple items

In this section, you will learn how to use a new class from the TapTargetView library, called TapTargetSequence. You can use this class when you want to show the highlight circle on many views one-by-one in a sequential fashion.

Open up FoodDetailActivity and add the following codes at the bottom of onCreate().

// 1
TapTargetSequence(this)
    // 2
    .targets(
        TapTarget.forView(btnShare, getString(R.string.label_share_food),
            getString(R.string.description_share_food))
            .cancelable(false).transparentTarget(true).targetRadius(70),
        TapTarget.forView(btnStore, getString(R.string.label_buy_food),
            getString(R.string.description_buy_food)).cancelable(false).
            transparentTarget(true).targetRadius(70),
        TapTarget.forToolbarNavigationIcon(toolbar, getString(R.string.label_back_arrow),
        getString(R.string.description_back_arrow)).cancelable(false)
            .tintTarget(true))
    // 3
    .listener(object : TapTargetSequence.Listener {
      override fun onSequenceStep(lastTarget: TapTarget?, targetClicked: Boolean) {
       }
      // 4
      override fun onSequenceFinish() {
        Toast.makeText(this@FoodDetailActivity, getString(R.string.msg_tutorial_complete),
            Toast.LENGTH_LONG).show()
      }
      // 5
      override fun onSequenceCanceled(lastTarget: TapTarget) {
      }
    })
    // 6
    .start()

Here’s a step-by-step breakdown:

  1. TapTargetSequence(this): Here you define a TapTargetSequence by passing Context as an argument.
  2. targets(): Here is where you include the views that you want the highlight circle to appear on them. You will pass the view name, title, and description.
  3. onSequenceStep: You can perform a certain action once you complete a sequence such as showing a Toast message.
  4. onSequenceFinish: Once you complete all the steps in the sequence you can show a Toast message indicating that the sequence is complete.
  5. onSequenceCanceled: Called when you try to cancel a sequence such as tapping on an empty area to dismiss the highlight circle.
  6. start(): This is the final part that you need to call for the highlight circle sequence to appear on the screen. Otherwise the sequence won’t appear.

Build and run the app and go to a detail screen to see the result.

what2eat gif

Preventing Multiple Highlights

It seems that the highlight circle sequence appears every time you navigate to the FoodDetailActivity screen, how can you prevent that from happening?

One solution is to use a persistence mechanism like SharedPreferences to save whether or not the highlighting has been seen.

Create a new Kotlin file in the base app package and name it StatusUtils. Add the following code inside the file:

object StatusUtils {
  // 1
  fun storeTutorialStatus(context: Context, show: Boolean) {
    val preferences = context.getSharedPreferences("showTutorial", Context.MODE_PRIVATE)
    val editor = preferences.edit()
    editor.putBoolean("show", show)
    editor.apply()
  }

  // 2
  fun getTutorialStatus(context: Context): Boolean {
    val preferences = context.getSharedPreferences("showTutorial", Context.MODE_PRIVATE)
    return preferences.getBoolean("show", true)
  }
}

Here’s a step-by-step breakdown of the code in the new file:

  1. storeTutorialStatus(): This function takes two parameters: a Context and a Boolean. You use this function to store the status of the highlight circle sequence inside SharedPreferences.
  2. getTutorialStatus(): This function takes a Context as an argument, and you use this function to determine whether to show or hide the highlight circle sequence based on the boolean value that you stored using storeTutorialStatus().

Open up FoodDetailActivity.kt file and change TapTargetSequence to include the two functions from StatusUtils:

if (StatusUtils.getTutorialStatus(this)) {
  TapTargetSequence(this)
      .targets(
          TapTarget.forView(btnShare, getString(R.string.label_share_food),
              getString(R.string.description_share_food))
              .cancelable(false).transparentTarget(true).targetRadius(70),
          TapTarget.forView(btnStore, getString(R.string.label_buy_food),
              getString(R.string.description_buy_food)).cancelable(false).transparentTarget(true).targetRadius(70),
          TapTarget.forToolbarNavigationIcon(toolbar, getString(R.string.label_back_arrow),
              getString(R.string.description_back_arrow)).cancelable(false)
              .tintTarget(true)).listener(object : TapTargetSequence.Listener {
        override fun onSequenceStep(lastTarget: TapTarget?, targetClicked: Boolean) {
        }

        override fun onSequenceFinish() {
          Toast.makeText(this@FoodDetailActivity, getString(R.string.msg_tutorial_complete),
              Toast.LENGTH_LONG).show()
          StatusUtils.storeTutorialStatus(this@FoodDetailActivity, false)
        }

        override fun onSequenceCanceled(lastTarget: TapTarget) {
        }
      }).start()
}

Here you first check the status of the highlight circle sequence. If the status is true the sequence will start, and you then store the status of the sequence as false once it reaches onSequenceFinish().

If the status in SharedPreferences is false, you will not see the highlight circle sequence anymore when you navigate to the FoodDetailActivity screen.

Build and run the app to see the result. The first time you navigate to a detail screen, you will see the highlight sequence. Subsequent visits will not show the highlight sequence.

what2eat gif

You can use a similar technique with SharedPreferences to determine whether or not to show the other highlights in the app once your user has seen them one or more times.

Where To Go From Here?

You can download the completed sample project using the download button at the top or bottom of the tutorial.

Be sure to check out TapTargetView GitHub documentation to find out all the things you can do to customize highlight circles to better match your app requirements.

We hope you enjoyed this tutorial on TapTargetView, and if you have any questions or comments, please join the forum discussion below!