Skip to main content

Android Material Showcase View - Part 1

In this series, I'll be talking about a library which is used by a lot of android developers for showcasing their in-app content, MaterialShowcaseView.

I used this library sometime back for my work and had to modify it to fit my needs. In this process, I ended up digging it a lot and would like to share what I learned.

The original library offers a fix set of features, which are demonstrated by the screenshots in the README.

Let's jump on the technicalities right away.

The original library offers two things :

1) highlighting a view ( see the README to know what I mean by highlighting here)
2) showing a content box that tells user what the highlighted view is about.

Here's how it does this :

The library adds a direct view child (this class) in the window decor view, so that it's drawn on top of your activity's view (here). Then, for drawing the overlay and highlighting our view, it overrides the `onDraw()` method of this view and uses android's Canvas class. The overlay should be such that it masks the whole view except the view that we want to showcase/highlight. It achieves this by drawing the color in two iterations :
1) draw the mask color over the whole view using the default PorterDuff Mode.
2) clears that the mask color over the active view using CLEAR PorterDuff Mode.

For doing the second step it needs the bounds of that highlighted view, which is maintained by this interface.

The second thing this library does is displaying a content box which has the title and description of our active view (can be set using this and this method) and a button to dismiss the showcase. This is the xml file that's used to inflate that view. For showing this view, it needs to decide whether it should show this content box above or below the active view. This is decided by doing some calculations on the layout bounds our highlighted view, the content view and our window. This is the function that does this.

There are some other things such as handling the touch behaviour on the view which has been handled by overriding the `onTouch` callback here.

IMO, this is the basic information that you need to know to get started with using, rather modifying this library according to your needs.

I've added some more functionalities to this library in my fork github, which I'll explaining in next post.

Feel free to comment/mail me in case you need any help with using this library.

Cheers !


Comments

Popular posts from this blog

Android : AbsSavedState cannot be cast to $SavedState

Android AbsSavedState cannot be cast to <View>$SavedState I came across a strange crash today. This is the stacktrace : Fatal Exception: java.lang.ClassCastException: android.view.AbsSavedState$1 cannot be cast to android.widget.ScrollView$SavedState at android.widget.ScrollView.onRestoreInstanceState(ScrollView.java:1810) at android.view.View.dispatchRestoreInstanceState(View.java:14768) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3123) at android.view.View.restoreHierarchyState(View.java:14746) at android.support.v4.app.Fragment.restoreViewState(SourceFile:470) at android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1326) at android.support.v4.app.FragmentManagerImpl.moveFragmentsToInvisible(SourceFile:2323) at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(SourceFile:2136) at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(SourceFile:2092)

Android Tip : Handling back button in Fragments

Android Tip : Handling hardware back button in Fragment and DialogFragment This post explains how to handle hardware back button in a Fragment OR DialogFragment . In DialogFragment, it’s quiet straight forward to achieve this. You’ve to get the dialog instance and set onKeyListener on it : if (getDialog() != null ) { getDialog().setOnKeyListener( new DialogInterface.OnKeyListener() { @Override public boolean onKey (DialogInterface dialog, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { Timber.i( "hardware back button pressed" ); } } }); } This can be done in the onViewCreated callback. For fragments, this method doesn’t work and fragments doesn’t have a direct callback to catch this event. So in this case, the approach that we follow is : You

DialogFragment : NullPointerException (support library)

Another weird crash this time ! Here’s the stack trace : Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{<activity.fully.qualified.path>}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.Dialog.setContentView(android.view.View)' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2659) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2724) at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4524) at android.app.ActivityThread.-wrap19(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1479) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6123) at java.lang.reflect.Method.invoke(Method.java) at com.android