How do I create a help overlay like you see in a few Android apps and ICS?
Asked Answered
P

4

95

I am wanting to create help overlays like the ones you see when ICS loads for the first time or in apps like ES File Explorer or Apex Launcher (there are more, but I can't think of them right now). Is this just a relative layout with one view sitting on top of the other? I haven't been able to find any sample code for doing such a thing. Anyone know how this is done or have any ideas?

ES File Explorer ES File Explorer

Purim answered 18/4, 2012 at 19:52 Comment(0)
A
80

"Coach mark" is "Help overlay" in UX talk :-)

coach_mark.xml is your coach mark layout

coach_mark_master_view is the id of the top most view (root) in coach_mark.xml

public void onCoachMark(){

    final Dialog dialog = new Dialog(this);
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
    dialog.setContentView(R.layout.coach_mark);
    dialog.setCanceledOnTouchOutside(true);
    //for dismissing anywhere you touch
    View masterView = dialog.findViewById(R.id.coach_mark_master_view);
    masterView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            dialog.dismiss();
        }
    });
    dialog.show();
}

Adding sample of coach_mark.xml (to this excellent solution given by Oded Breiner), so its easy for ppl to copy & paste to see working example quickly.

Sample of coach_mark.xml here, change the -> drawable/coach_marks to your image:

coach_mark.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id="@+id/coach_mark_master_view">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
         <ImageView
             android:id="@+id/coach_marks_image"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_centerInParent="true"
             android:layout_gravity="center_horizontal"
             android:src="@drawable/coach_marks" />
    </RelativeLayout>
</LinearLayout>

And optionally use this theme to remove padding:

<style name="WalkthroughTheme" parent="Theme.AppCompat">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:backgroundDimEnabled">false</item>
</style>
Archeology answered 13/6, 2013 at 15:49 Comment(9)
Hello, how can you stretch this Dialog to match the screen? From the documentation, A dialog is a small window that prompts [...]. A dialog does not fill the screen and is normally used for modal events [...].. If I use this code, I get my master view compressed in a small portion of the screen. If i set android:layout_width="640dp" android:layout_height="480dp" (that is, the actual values of the screen I'm testing with), it works correctly. (of course this is not a feasible solution)Sturges
@Sturges : the above example should be full screen because of match_parent and Window.FEATURE_NO_TITLEArcheology
Then there must be some other problem, because I'm seeing it in a different waySturges
I know this is at least a few months old but did that full screen question ever get figured out?Patchwork
@Patchwork - Maybe it's the theme, which theme are you using?Archeology
@oded which theme you are using?Eusebioeusebius
To those that do not know how to set the theme of the dialog, just instantiate the dialog like so: new Dialog(getContext(), R.style.WalkthroughTheme);Winker
Process: com.mintwalk, PID: 3207 java.lang.OutOfMemoryError: Failed to allocate a 1489584 byte allocation with 144144 free bytes and 140KB until OOM at dalvik.system.VMRuntime.newNonMovableArray(Native Method)Bombsight
@RameshM.Bhati looks like you might be loading images that are too big, try using smaller images or use an image loading library like: square.github.io/picassoArcheology
H
85

Let's assume you ordinarily would call setContentView(R.layout.main), but on first run, you want to have this overlay.

Step #1: Create a FrameLayout in Java code and pass that to setContentView().

Step #2: Use LayoutInflater to inflate R.layout.main into the FrameLayout.

Step #3: Use LayoutInflater to inflate the overlay into the FrameLayout.

Step #4: When the user taps the button (or whatever) to dismiss the overlay, call removeView() to remove the overlay from the FrameLayout.

Since the overlay is a later child of the FrameLayout, it will float over top of the contents of R.layout.main.

Helotry answered 18/4, 2012 at 19:59 Comment(14)
@ssuperz28: Yeah, well, except for the hand-drawn arrowheads and bubble. You're on your own for those. :-)Helotry
I don't know if you managed to do what you wanted, but here is another alternative. #8841740 If you mantain the solution given by CommonsWare, the only thing that occurs me in order to set the arrows, is to define the FrameLayout of instructions with a resourceImage or backgroundImage already with the image with the arrows (and transparency).Gualterio
Is there a way to do this but doing it relative to the children's position who are below from the FrameLayout?Solicitous
@Helotry - sir this would work regardless of whichever device it may be ?Beanery
@Rat-a-tat-a-tatRatatouille: It should. I cannot rule out some device manufacturer doing something strange, but that "strange" would probably break other things as well.Helotry
alright il try it and then get back with positive results i believe :)..thank u @HelotryBeanery
@Helotry - sir it worked well :) .. i mean irrespective of whichever device it is, 10" or 7" or 3.5" ..Beanery
Unfortunately this method generates a view for the coach marks that does not cover the action bar of a 4.x style designed app.Endurant
I have a question. I am assuming on the images above that these are text views (with compound drawable) and or image views. My question is, doesn't the arrows where they are pointing to displace as you increase density? (devices with bigger screen) How do you go about solving thisContrapuntal
@user3364963: Dynamically adjust the positions of things. My answer was somewhat simplified. I assume that they determine the position of the to-be-highlighted elements and adjust coordinates of the "coach marks". A custom ViewGroup for the "coach marks" layer could handle that, and there are libraries (e.g., ShowcaseView) that offer canned implementations of that pattern.Helotry
@Helotry thanks for the advice. I cannot use the ShowcaseView because I am targeting API 8.Contrapuntal
I'm using a coordinator layout and it has an appbar included. Is there a way to bring view above toolbar using coordinator layout?Asha
@AkashRaghav: I have no idea. You may want to ask a separate Stack Overflow question regarding that.Helotry
I have asked a new question. Here is the link - #45217012Asha
A
80

"Coach mark" is "Help overlay" in UX talk :-)

coach_mark.xml is your coach mark layout

coach_mark_master_view is the id of the top most view (root) in coach_mark.xml

public void onCoachMark(){

    final Dialog dialog = new Dialog(this);
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
    dialog.setContentView(R.layout.coach_mark);
    dialog.setCanceledOnTouchOutside(true);
    //for dismissing anywhere you touch
    View masterView = dialog.findViewById(R.id.coach_mark_master_view);
    masterView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            dialog.dismiss();
        }
    });
    dialog.show();
}

Adding sample of coach_mark.xml (to this excellent solution given by Oded Breiner), so its easy for ppl to copy & paste to see working example quickly.

Sample of coach_mark.xml here, change the -> drawable/coach_marks to your image:

coach_mark.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id="@+id/coach_mark_master_view">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
         <ImageView
             android:id="@+id/coach_marks_image"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_centerInParent="true"
             android:layout_gravity="center_horizontal"
             android:src="@drawable/coach_marks" />
    </RelativeLayout>
</LinearLayout>

And optionally use this theme to remove padding:

<style name="WalkthroughTheme" parent="Theme.AppCompat">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:backgroundDimEnabled">false</item>
</style>
Archeology answered 13/6, 2013 at 15:49 Comment(9)
Hello, how can you stretch this Dialog to match the screen? From the documentation, A dialog is a small window that prompts [...]. A dialog does not fill the screen and is normally used for modal events [...].. If I use this code, I get my master view compressed in a small portion of the screen. If i set android:layout_width="640dp" android:layout_height="480dp" (that is, the actual values of the screen I'm testing with), it works correctly. (of course this is not a feasible solution)Sturges
@Sturges : the above example should be full screen because of match_parent and Window.FEATURE_NO_TITLEArcheology
Then there must be some other problem, because I'm seeing it in a different waySturges
I know this is at least a few months old but did that full screen question ever get figured out?Patchwork
@Patchwork - Maybe it's the theme, which theme are you using?Archeology
@oded which theme you are using?Eusebioeusebius
To those that do not know how to set the theme of the dialog, just instantiate the dialog like so: new Dialog(getContext(), R.style.WalkthroughTheme);Winker
Process: com.mintwalk, PID: 3207 java.lang.OutOfMemoryError: Failed to allocate a 1489584 byte allocation with 144144 free bytes and 140KB until OOM at dalvik.system.VMRuntime.newNonMovableArray(Native Method)Bombsight
@RameshM.Bhati looks like you might be loading images that are too big, try using smaller images or use an image loading library like: square.github.io/picassoArcheology
S
4

You can do that pretty quickly. You add, for exemple a LinearLayout where you put a picture with alpha which correspond to your help information and what do you want to draw like an overlay. In you xml of your activity you put this layout in a RelativeLayout after the layout of your activity with the Gone visibility. When you want to draw the help information, you just neeed to set this visibility to visible.

I hope, I'm clear, if you have any question,I'm be please to answer them.

Singlefoot answered 18/4, 2012 at 19:59 Comment(1)
Thanks for your input. This is how I pictured it being done. I have to give credit to the answer below though as that is the way I'm going to build it. It seems more manageable and I don't have to alter my main activity layout.Purim
S
1

See my another answer how programmatically show an overlay layout on top of the current activity. Activity's layout.xml does not need to know anything about the overlay skin. You can put overlay semi-transparent, cover only part of the screen, one or more textview and buttons on it... How to overlay a button programmically?

  • create res/layout/paused.xml RelativeLayout template or use any layout toplevel
  • create a function to show overlay skin
  • key is to get handle to layout.xml, use LayoutInflater class to parse xml to view object, add overlay view to current layout structure
  • My example uses a timer to destroy overlay object by completely removing it from the view structure. This is probably what you want as well to get rid of it without a trace.

My goal was that main activities are not aware of any overlay skin, overlays come and go, many different overlays, still able to use overlay1.xml text files as a template, and content should programmatically be updated. I do pretty much what CommonsWare told us my post shows the actual program code to get started.

disclaimer: OPs "Thanks for your input. This is how I pictured it being done. I have to give credit to the answer below" comment does not mean my answer but CommonsWare answer. Stackoverflow have changed post orderings.

Stoke answered 12/1, 2013 at 19:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.