├── .gitignore
├── AndroidManifest.xml
├── README.md
├── ant.properties
├── assets
└── fonts
│ ├── roboto_light.ttf
│ └── roboto_regular.ttf
├── build.xml
├── gen
└── com
│ └── eluleci
│ └── appintroduction
│ ├── BuildConfig.java
│ ├── Manifest.java
│ └── R.java
├── local.properties
├── proguard-project.txt
├── project.properties
├── res
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-ldpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── drawable-xhdpi
│ └── ic_launcher.png
├── drawable
│ ├── arrow_alizarin.png
│ ├── arrow_amethyst.png
│ ├── arrow_asbestos.png
│ ├── arrow_belize_hole.png
│ ├── arrow_carrot.png
│ ├── arrow_clouds.png
│ ├── arrow_concrete.png
│ ├── arrow_emerald.png
│ ├── arrow_green_sea.png
│ ├── arrow_midnight_blue.png
│ ├── arrow_neprhitis.png
│ ├── arrow_orange.png
│ ├── arrow_peter_river.png
│ ├── arrow_pomegranate.png
│ ├── arrow_pumpkin.png
│ ├── arrow_silver.png
│ ├── arrow_sunflower.png
│ ├── arrow_turquoise.png
│ ├── arrow_wet_asphalt.png
│ └── arrow_wisteria.png
├── layout
│ └── main.xml
└── values
│ ├── colors.xml
│ └── strings.xml
├── screenshots
├── 1.png
├── 10.png
├── 2.png
├── 3.png
├── 4.png
├── 5.png
├── 6.png
├── 7.png
├── 8.png
├── 9.png
└── flatuicolors.png
└── src
└── com
└── eluleci
└── appintroduction
├── AppIntroduction.java
├── Step.java
├── TextBaloon.java
├── listeners
├── StepActionListener.java
└── UserActionListener.java
└── views
├── DynamicDrawable.java
├── TextViewLight.java
└── TextViewRegular.java
/.gitignore:
--------------------------------------------------------------------------------
1 | # built application files
2 | *.apk
3 | *.ap_
4 |
5 | # files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # generated files
12 | bin/
13 | gen/
14 |
15 | # Local configuration file (sdk path, etc)
16 | local.properties
17 |
18 | # Eclipse project files
19 | .classpath
20 | .project
21 |
22 | # Proguard folder generated by Eclipse
23 | proguard/
24 |
25 | # Intellij project files
26 | *.iml
27 | *.ipr
28 | *.iws
29 | .idea/
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | App Introduction
2 | ===================
3 |
4 | App Introduction is a library that helps to create introduction menu for users.
5 |
6 | Only thing that you need to do is giving the id of the element to show (if you want to point an element) and
7 | write the message. You can choose pointing type like vertical or horizontal. Then the rest is done by library.
8 |
9 | The messages that you add to same AppIntroduction object are stored and showed to the user one by one.
10 | When user sees messages of an Activity once, they will not be shown again. You can select one of the 20 themes.
11 | You can create listeners for doing some actions before and after each step, so you can have full control on steps.
12 | Also you can create a listener to know when user dismisses the AppIntroduction.
13 |
14 | Features included
15 | -----------------
16 | * Showing the message in the middle.
17 | * Showing the message with horizontal pointer.
18 | * Showing the message with vertical pointer.
19 | * Remembering past (not showing messages if already shown).
20 | * Changing theme (Selecting one of the colors in http://flatuicolors.com).
21 | * Creating listeners for before/after events for each step.
22 | * Creating listeners for user dismiss.
23 |
24 | Screenshots
25 | -----------
26 |
27 | ![Message in the middle][1].![Message with vertical pointer][2].![Message with horizontal pointer][3].![Message with vertical pointer again.][4]
28 |
29 |
30 | Theme Screenshots
31 | -----------
32 |
33 | ![Orange][5].![Wet Asphalt][6].![Turquoise][7].![Asbestos][8].![Wisteria][9].![Pomegranate][10]
34 |
35 |
36 | Colors
37 | -----------
38 |
39 | ![colors][11]
40 |
41 | [1]: https://raw.github.com/eluleci/appintroduction/master/screenshots/1.png
42 | [2]: https://raw.github.com/eluleci/appintroduction/master/screenshots/2.png
43 | [3]: https://raw.github.com/eluleci/appintroduction/master/screenshots/3.png
44 | [4]: https://raw.github.com/eluleci/appintroduction/master/screenshots/4.png
45 | [5]: https://raw.github.com/eluleci/appintroduction/master/screenshots/5.png
46 | [6]: https://raw.github.com/eluleci/appintroduction/master/screenshots/6.png
47 | [7]: https://raw.github.com/eluleci/appintroduction/master/screenshots/7.png
48 | [8]: https://raw.github.com/eluleci/appintroduction/master/screenshots/8.png
49 | [9]: https://raw.github.com/eluleci/appintroduction/master/screenshots/9.png
50 | [10]: https://raw.github.com/eluleci/appintroduction/master/screenshots/10.png
51 | [11]: https://raw.github.com/eluleci/appintroduction/master/screenshots/flatuicolors.png
52 |
53 | ## Usage
54 |
55 | For using this library in Android Studio (IntelliJ IDEA) you need to activate including assets from dependencies.
56 | - Open project structure (Right Click on Project -> 'Open Module Settings')
57 | - Select 'Facets' from left menu
58 | - Select 'Compiler' tab at right
59 | - Activate 'Include assets from dependencies into APK' beneath 'Resources Packaging'
60 |
61 | ```java
62 |
63 | AppIntroduction appIntroduction = new AppIntroduction(this);
64 |
65 | // remembering past. not showing again if already shown before
66 | appIntroduction.rememberPast(true);
67 |
68 | // changing theme. selecting one of the colors
69 | appIntroduction.setTheme(AppIntroduction.TURQUOISE);
70 |
71 |
72 |
73 | // adding message into middle
74 | appIntroduction.addStep(new Step(getResources().getString(R.string.uc_main_1)));
75 |
76 | // adding message with vertical pointer
77 | appIntroduction.addStep(new Step(R.id.search,
78 | getResources().getString(R.string.uc_main_3), AppIntroduction.SIDE_VERTICAL));
79 |
80 | // adding message with horizontal pointer
81 | appIntroduction.addStep(new Step(R.id.next,
82 | getResources().getString(R.string.uc_shuffle_3), AppIntroduction.SIDE_HORIZONTAL));
83 |
84 |
85 |
86 | // constructing AppIntroduction for listening dismiss of the user
87 | appIntroduction = new AppIntroduction(this) {
88 | @Override
89 | public void onDismiss() {
90 | super.onDismiss();
91 | // handle user's dismiss
92 | }
93 | };
94 |
95 |
96 |
97 | // listeners for steps. you can do some changes before or after a step
98 | appIntroduction.addStep(new Step(R.id.second_language,
99 | getResources().getString(R.string.uc_shuffle_11), AppIntroduction.SIDE_VERTICAL, new StepActionListener() {
100 | @Override
101 | public void beforeMessageShown() {
102 | // do something before showing message
103 | }
104 |
105 | @Override
106 | public void afterMessageShown() {
107 | // do something after showing message
108 | }
109 | }));
110 |
111 | // starting introduction. you CANNOT call this in onCreate method of activity.
112 | // because the content view of activity won't be ready in onCreate
113 | appIntroduction.start();
114 |
115 | // starting introduction. you can call this in onCreate method in activity.
116 | // it will wait for 0.5 seconds for content view to be ready.
117 | appIntroduction.startWithDelay();
118 |
119 | ```
120 |
121 |
--------------------------------------------------------------------------------
/ant.properties:
--------------------------------------------------------------------------------
1 | # This file is used to override default values used by the Ant build system.
2 | #
3 | # This file must be checked into Version Control Systems, as it is
4 | # integral to the build system of your project.
5 |
6 | # This file is only used by the Ant script.
7 |
8 | # You can use this to override default values such as
9 | # 'source.dir' for the location of your java source folder and
10 | # 'out.dir' for the location of your output folder.
11 |
12 | # You can also use it define how the release builds are signed by declaring
13 | # the following properties:
14 | # 'key.store' for the location of your keystore and
15 | # 'key.alias' for the name of the key to use.
16 | # The password will be asked during the build when you use the 'release' target.
17 |
18 |
--------------------------------------------------------------------------------
/assets/fonts/roboto_light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/assets/fonts/roboto_light.ttf
--------------------------------------------------------------------------------
/assets/fonts/roboto_regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/assets/fonts/roboto_regular.ttf
--------------------------------------------------------------------------------
/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
29 |
30 |
31 |
35 |
36 |
37 |
38 |
39 |
40 |
49 |
50 |
51 |
52 |
56 |
57 |
69 |
70 |
71 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/gen/com/eluleci/appintroduction/BuildConfig.java:
--------------------------------------------------------------------------------
1 | /*___Generated_by_IDEA___*/
2 |
3 | /** Automatically generated file. DO NOT MODIFY */
4 | package com.eluleci.appintroduction;
5 |
6 | public final class BuildConfig {
7 | public final static boolean DEBUG = true;
8 | }
--------------------------------------------------------------------------------
/gen/com/eluleci/appintroduction/Manifest.java:
--------------------------------------------------------------------------------
1 | /*___Generated_by_IDEA___*/
2 |
3 | package com.eluleci.appintroduction;
4 |
5 | /* This stub is for using by IDE only. It is NOT the Manifest class actually packed into APK */
6 | public final class Manifest {
7 | }
--------------------------------------------------------------------------------
/gen/com/eluleci/appintroduction/R.java:
--------------------------------------------------------------------------------
1 | /*___Generated_by_IDEA___*/
2 |
3 | package com.eluleci.appintroduction;
4 |
5 | /* This stub is for using by IDE only. It is NOT the R class actually packed into APK */
6 | public final class R {
7 | }
--------------------------------------------------------------------------------
/local.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must *NOT* be checked into Version Control Systems,
5 | # as it contains information specific to your local configuration.
6 |
7 | # location of the SDK. This is only used by Ant
8 | # For customization when using a Version Control System, please read the
9 | # header note.
10 | sdk.dir=C:\\Program Files\\Android\\android-sdk
11 |
--------------------------------------------------------------------------------
/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | android.library=true
14 | # Project target.
15 | target=Google Inc.:Google APIs:16
16 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable/arrow_alizarin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_alizarin.png
--------------------------------------------------------------------------------
/res/drawable/arrow_amethyst.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_amethyst.png
--------------------------------------------------------------------------------
/res/drawable/arrow_asbestos.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_asbestos.png
--------------------------------------------------------------------------------
/res/drawable/arrow_belize_hole.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_belize_hole.png
--------------------------------------------------------------------------------
/res/drawable/arrow_carrot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_carrot.png
--------------------------------------------------------------------------------
/res/drawable/arrow_clouds.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_clouds.png
--------------------------------------------------------------------------------
/res/drawable/arrow_concrete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_concrete.png
--------------------------------------------------------------------------------
/res/drawable/arrow_emerald.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_emerald.png
--------------------------------------------------------------------------------
/res/drawable/arrow_green_sea.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_green_sea.png
--------------------------------------------------------------------------------
/res/drawable/arrow_midnight_blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_midnight_blue.png
--------------------------------------------------------------------------------
/res/drawable/arrow_neprhitis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_neprhitis.png
--------------------------------------------------------------------------------
/res/drawable/arrow_orange.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_orange.png
--------------------------------------------------------------------------------
/res/drawable/arrow_peter_river.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_peter_river.png
--------------------------------------------------------------------------------
/res/drawable/arrow_pomegranate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_pomegranate.png
--------------------------------------------------------------------------------
/res/drawable/arrow_pumpkin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_pumpkin.png
--------------------------------------------------------------------------------
/res/drawable/arrow_silver.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_silver.png
--------------------------------------------------------------------------------
/res/drawable/arrow_sunflower.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_sunflower.png
--------------------------------------------------------------------------------
/res/drawable/arrow_turquoise.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_turquoise.png
--------------------------------------------------------------------------------
/res/drawable/arrow_wet_asphalt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_wet_asphalt.png
--------------------------------------------------------------------------------
/res/drawable/arrow_wisteria.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/res/drawable/arrow_wisteria.png
--------------------------------------------------------------------------------
/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #1abc9c
5 | #2ecc71
6 | #3498db
7 | #9b59b6
8 | #34495e
9 | #16a085
10 | #27ae60
11 | #2980b9
12 | #8e44ad
13 | #2c3e50
14 | #f1c40f
15 | #e67e22
16 | #e74c3c
17 | #ecf0f1
18 | #95a5a6
19 | #f39c12
20 | #d35400
21 | #c0392b
22 | #bdc3c7
23 | #7f8c8d
24 |
25 |
26 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | ACTIVITY_ENTRY_NAME
4 |
5 |
--------------------------------------------------------------------------------
/screenshots/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/screenshots/1.png
--------------------------------------------------------------------------------
/screenshots/10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/screenshots/10.png
--------------------------------------------------------------------------------
/screenshots/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/screenshots/2.png
--------------------------------------------------------------------------------
/screenshots/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/screenshots/3.png
--------------------------------------------------------------------------------
/screenshots/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/screenshots/4.png
--------------------------------------------------------------------------------
/screenshots/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/screenshots/5.png
--------------------------------------------------------------------------------
/screenshots/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/screenshots/6.png
--------------------------------------------------------------------------------
/screenshots/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/screenshots/7.png
--------------------------------------------------------------------------------
/screenshots/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/screenshots/8.png
--------------------------------------------------------------------------------
/screenshots/9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/screenshots/9.png
--------------------------------------------------------------------------------
/screenshots/flatuicolors.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eluleci/appintroduction/17178a4d56e9138bf48f6e04fc0663f2e7acdd6c/screenshots/flatuicolors.png
--------------------------------------------------------------------------------
/src/com/eluleci/appintroduction/AppIntroduction.java:
--------------------------------------------------------------------------------
1 | package com.eluleci.appintroduction;
2 |
3 | import android.app.Activity;
4 | import android.content.SharedPreferences;
5 | import com.eluleci.appintroduction.listeners.UserActionListener;
6 |
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | /**
11 | * Created with IntelliJ IDEA.
12 | * User: eluleci
13 | * Date: 08.08.2013
14 | * Time: 22:21
15 | */
16 | public class AppIntroduction implements UserActionListener {
17 |
18 | public static final int TURQUOISE = 1;
19 | public static final int EMERALD = 2;
20 | public static final int PETER_RIVER = 3;
21 | public static final int AMETHYST = 4;
22 | public static final int WET_ASPHALT = 5;
23 | public static final int GREEN_SEA = 6;
24 | public static final int NEPHRITIS = 7;
25 | public static final int BELIZE_HOLE = 8;
26 | public static final int WISTERIA = 9;
27 | public static final int MIDNIGHT_BLUE = 10;
28 | public static final int SUN_FLOWER = 11;
29 | public static final int CARROT = 12;
30 | public static final int ALIZARIN = 13;
31 | public static final int CLOUDS = 14;
32 | public static final int CONCRETE = 15;
33 | public static final int ORANGE = 16;
34 | public static final int PUMPKIN = 17;
35 | public static final int POMEGRANATE = 18;
36 | public static final int SILVER = 19;
37 | public static final int ASBESTOS = 20;
38 |
39 | public static final int SIDE_HORIZONTAL = 0;
40 | public static final int SIDE_VERTICAL = 1;
41 | public static final int SIDE_NONE = -1;
42 | public static final int NO_VIEW = -5;
43 | private static final String PREF_NAME = "AppIntroductionPreferences";
44 | private boolean checkUsersChoice = false;
45 | private Activity mContext;
46 | private TextBaloon textBaloon;
47 | private List steps = new ArrayList();
48 | private int currentElement = -1;
49 | private boolean isOver = false;
50 | private boolean isActive = false;
51 |
52 | public AppIntroduction(Activity activity) {
53 | mContext = activity;
54 | textBaloon = new TextBaloon(activity, this);
55 | }
56 |
57 | public void addStep(Step step) {
58 | steps.add(step);
59 | }
60 |
61 | public void start() {
62 |
63 | // don't start if shown before
64 | if (isShownBefore() && checkUsersChoice) return;
65 |
66 | SharedPreferences settings = mContext.getSharedPreferences(PREF_NAME, 0);
67 | SharedPreferences.Editor editor = settings.edit();
68 | editor.putBoolean(mContext.getLocalClassName(), true);
69 | editor.commit();
70 |
71 | onNextClicked();
72 | isActive = true;
73 | }
74 |
75 | public void startWithDelay() {
76 | Thread changeTextThread = new Thread() {
77 | @Override
78 | public void run() {
79 | try {
80 | Thread.sleep(500);
81 | } catch (InterruptedException e) {
82 | }
83 |
84 | mContext.runOnUiThread(new Runnable() {
85 | @Override
86 | public void run() {
87 | AppIntroduction.this.start();
88 | }
89 | });
90 | }
91 | };
92 | changeTextThread.start();
93 | }
94 |
95 | public void rememberPast(boolean remember) {
96 | checkUsersChoice = remember;
97 | }
98 |
99 | public void setTheme(int theme){
100 | textBaloon.setTheme(theme);
101 | }
102 |
103 | public boolean isShownBefore() {
104 | SharedPreferences settings = mContext.getSharedPreferences(PREF_NAME, 0);
105 |
106 | boolean isShownBefore = settings.getBoolean(mContext.getLocalClassName(), false);
107 | return isShownBefore;
108 | }
109 |
110 | public void next() {
111 | if (isActive())
112 | onNextClicked();
113 | }
114 |
115 | @Override
116 | public void onNextClicked() {
117 |
118 | if (isOver) return;
119 |
120 | if (currentElement != -1)
121 | steps.get(currentElement).getStepActionListener().afterMessageShown();
122 |
123 | if (++currentElement == steps.size()) {
124 | textBaloon.hide();
125 | isOver = true;
126 | return;
127 | }
128 |
129 | steps.get(currentElement).getStepActionListener().beforeMessageShown();
130 | textBaloon.changeElement(steps.get(currentElement));
131 | }
132 |
133 | @Override
134 | public void onDismiss() {
135 | textBaloon.hide();
136 | }
137 |
138 | public boolean isActive() {
139 | return isActive;
140 | }
141 |
142 | public TextBaloon getTextBaloon() {
143 | return textBaloon;
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/src/com/eluleci/appintroduction/Step.java:
--------------------------------------------------------------------------------
1 | package com.eluleci.appintroduction;
2 |
3 | import com.eluleci.appintroduction.listeners.StepActionListener;
4 |
5 | /**
6 | * Created with IntelliJ IDEA.
7 | * User: eluleci
8 | * Date: 19.09.2013
9 | * Time: 23:21
10 | */
11 | public class Step {
12 |
13 | private int viewId;
14 | private String message;
15 | private int side;
16 |
17 | private StepActionListener stepActionListener = new StepActionListener() {
18 | @Override
19 | public void beforeMessageShown() {
20 | }
21 |
22 | @Override
23 | public void afterMessageShown() {
24 | }
25 | };
26 |
27 | public Step(String message) {
28 | this.viewId = AppIntroduction.NO_VIEW;
29 | this.message = message;
30 | this.side = AppIntroduction.SIDE_NONE;
31 | }
32 |
33 | public Step(String message, StepActionListener stepActionListener) {
34 | this.viewId = AppIntroduction.NO_VIEW;
35 | this.message = message;
36 | this.side = AppIntroduction.SIDE_NONE;
37 | this.stepActionListener = stepActionListener;
38 | }
39 |
40 | public Step(int viewId, String message, int side) {
41 | this.viewId = viewId;
42 | this.message = message;
43 | this.side = side;
44 | }
45 |
46 | public Step(int viewId, String message, int side, StepActionListener stepActionListener) {
47 | this.viewId = viewId;
48 | this.message = message;
49 | this.side = side;
50 | this.stepActionListener = stepActionListener;
51 | }
52 |
53 | public int getViewId() {
54 | return viewId;
55 | }
56 |
57 | public String getMessage() {
58 | return message;
59 | }
60 |
61 | public int getSide() {
62 | return side;
63 | }
64 |
65 | public void setStepActionListener(StepActionListener stepActionListener) {
66 | this.stepActionListener = stepActionListener;
67 | }
68 |
69 | public StepActionListener getStepActionListener() {
70 | return stepActionListener;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/com/eluleci/appintroduction/TextBaloon.java:
--------------------------------------------------------------------------------
1 | package com.eluleci.appintroduction;
2 |
3 | import android.app.Activity;
4 | import android.graphics.Color;
5 | import android.graphics.drawable.Drawable;
6 | import android.util.Log;
7 | import android.view.Display;
8 | import android.view.Gravity;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.view.animation.AlphaAnimation;
12 | import android.view.animation.RotateAnimation;
13 | import android.widget.*;
14 | import com.eluleci.appintroduction.listeners.UserActionListener;
15 | import com.eluleci.appintroduction.views.DynamicDrawable;
16 | import com.eluleci.appintroduction.views.TextViewLight;
17 | import com.eluleci.appintroduction.views.TextViewRegular;
18 |
19 | /**
20 | * Created with IntelliJ IDEA.
21 | * User: eluleci
22 | * Date: 08.08.2013
23 | * Time: 22:19
24 | */
25 | public class TextBaloon extends RelativeLayout {
26 |
27 | private final int indicatorSize = 50;
28 | private final int containerMargin = 10;
29 | private final int textPadding = 10;
30 | private Activity mContext;
31 | private UserActionListener userActionListener;
32 | private View backgroundLayer;
33 | private TextView explanationTextView;
34 | private LinearLayout container;
35 | private RelativeLayout footerContainer;
36 | private ImageView indicator;
37 | private TextView exit;
38 | private TextView next;
39 | private AlphaAnimation showAnim;
40 | private AlphaAnimation hideAnim;
41 | private int animDuration = 100;
42 | private int screenWidth;
43 | private int screenHeight;
44 | private int textSize = 20;
45 | private View element;
46 |
47 | public TextBaloon(Activity activity, UserActionListener ual) {
48 | super(activity);
49 | mContext = activity;
50 | userActionListener = ual;
51 |
52 | setVisibility(GONE);
53 |
54 | Display display = activity.getWindowManager().getDefaultDisplay();
55 | screenWidth = display.getWidth();
56 | screenHeight = display.getHeight();
57 |
58 | ViewGroup root = (ViewGroup) activity.getWindow().getDecorView().findViewById(android.R.id.content);
59 |
60 | // adding a layer to the background to avoid the clicks to other views
61 | backgroundLayer = new View(mContext);
62 | backgroundLayer.setVisibility(GONE);
63 | root.addView(backgroundLayer);
64 | backgroundLayer.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
65 | ViewGroup.LayoutParams.MATCH_PARENT));
66 | //backgroundLayer.setBackgroundColor(Color.parseColor("#11000000"));
67 | backgroundLayer.setOnClickListener(new OnClickListener() {
68 | @Override
69 | public void onClick(View v) {
70 | }
71 | });
72 |
73 |
74 | this.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
75 | ViewGroup.LayoutParams.MATCH_PARENT));
76 |
77 | root.addView(this);
78 |
79 | indicator = new ImageView(activity);
80 | this.addView(indicator);
81 | indicator.setLayoutParams(new LayoutParams(indicatorSize, indicatorSize));
82 |
83 | container = new LinearLayout(activity);
84 | container.setOrientation(LinearLayout.VERTICAL);
85 | this.addView(container);
86 | container.setLayoutParams(new LayoutParams(screenWidth, ViewGroup.LayoutParams.WRAP_CONTENT));
87 |
88 | setTheme(AppIntroduction.PETER_RIVER);
89 |
90 | explanationTextView = new TextViewLight(activity);
91 | explanationTextView.setTextColor(Color.WHITE);
92 | explanationTextView.setGravity(Gravity.CENTER);
93 | explanationTextView.setPadding(textPadding, textPadding * 2, textPadding, textPadding * 2);
94 | explanationTextView.setTextSize(textSize);
95 | container.addView(explanationTextView);
96 | explanationTextView.setLayoutParams(new LinearLayout.LayoutParams(
97 | ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
98 |
99 | footerContainer = new RelativeLayout(activity);
100 | footerContainer.setAlpha(0.6f);
101 | container.addView(footerContainer);
102 | footerContainer.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
103 | ViewGroup.LayoutParams.WRAP_CONTENT));
104 |
105 | LayoutParams nextButtonParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
106 | ViewGroup.LayoutParams.WRAP_CONTENT);
107 | nextButtonParams.addRule(ALIGN_PARENT_RIGHT, -1);
108 |
109 | next = new TextViewRegular(activity);
110 | next.setTextColor(Color.WHITE);
111 | next.setText("NEXT");
112 | next.setTextSize(textSize);
113 | next.setPadding(textPadding, textPadding, textPadding * 2, textPadding);
114 | footerContainer.addView(next);
115 | next.setLayoutParams(nextButtonParams);
116 |
117 | exit = new TextViewRegular(activity);
118 | exit.setTextColor(Color.WHITE);
119 | exit.setText("CANCEL");
120 | exit.setTextSize(textSize);
121 | exit.setPadding(textPadding * 2, textPadding, textPadding, textPadding);
122 | footerContainer.addView(exit);
123 | exit.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
124 | ViewGroup.LayoutParams.WRAP_CONTENT));
125 |
126 | hideAnim = new AlphaAnimation(1f, 0f);
127 | hideAnim.setDuration(animDuration);
128 | hideAnim.setFillAfter(true);
129 |
130 | showAnim = new AlphaAnimation(0f, 1f);
131 | showAnim.setDuration(animDuration);
132 | showAnim.setFillAfter(true);
133 | showAnim.setStartOffset(animDuration);
134 |
135 |
136 | next.setOnClickListener(new OnClickListener() {
137 | @Override
138 | public void onClick(View v) {
139 | userActionListener.onNextClicked();
140 | }
141 | });
142 |
143 | exit.setOnClickListener(new OnClickListener() {
144 | @Override
145 | public void onClick(View v) {
146 | userActionListener.onDismiss();
147 | }
148 | });
149 | }
150 |
151 | protected void setTheme(int theme){
152 |
153 | int indicatorDrawableId = R.drawable.arrow_peter_river;
154 | int containerBackDrawableId = R.color.peter_river;
155 |
156 | switch (theme){
157 | case AppIntroduction.TURQUOISE:
158 | indicatorDrawableId = R.drawable.arrow_turquoise;
159 | containerBackDrawableId = R.color.turquoise;
160 | break;
161 | case AppIntroduction.EMERALD:
162 | indicatorDrawableId = R.drawable.arrow_emerald;
163 | containerBackDrawableId = R.color.emerald;
164 | break;
165 | case AppIntroduction.PETER_RIVER:
166 | indicatorDrawableId = R.drawable.arrow_peter_river;
167 | containerBackDrawableId = R.color.peter_river;
168 | break;
169 | case AppIntroduction.AMETHYST:
170 | indicatorDrawableId = R.drawable.arrow_amethyst;
171 | containerBackDrawableId = R.color.amethyst;
172 | break;
173 | case AppIntroduction.WET_ASPHALT:
174 | indicatorDrawableId = R.drawable.arrow_wet_asphalt;
175 | containerBackDrawableId = R.color.wet_asphalt;
176 | break;
177 | case AppIntroduction.GREEN_SEA:
178 | indicatorDrawableId = R.drawable.arrow_green_sea;
179 | containerBackDrawableId = R.color.green_sea;
180 | break;
181 | case AppIntroduction.NEPHRITIS:
182 | indicatorDrawableId = R.drawable.arrow_neprhitis;
183 | containerBackDrawableId = R.color.nephritis;
184 | break;
185 | case AppIntroduction.BELIZE_HOLE:
186 | indicatorDrawableId = R.drawable.arrow_belize_hole;
187 | containerBackDrawableId = R.color.belize_hole;
188 | break;
189 | case AppIntroduction.WISTERIA:
190 | indicatorDrawableId = R.drawable.arrow_wisteria;
191 | containerBackDrawableId = R.color.wisteria;
192 | break;
193 | case AppIntroduction.MIDNIGHT_BLUE:
194 | indicatorDrawableId = R.drawable.arrow_midnight_blue;
195 | containerBackDrawableId = R.color.midnight_blue;
196 | break;
197 | case AppIntroduction.SUN_FLOWER:
198 | indicatorDrawableId = R.drawable.arrow_sunflower;
199 | containerBackDrawableId = R.color.sun_flower;
200 | break;
201 | case AppIntroduction.CARROT:
202 | indicatorDrawableId = R.drawable.arrow_carrot;
203 | containerBackDrawableId = R.color.carrot;
204 | break;
205 | case AppIntroduction.ALIZARIN:
206 | indicatorDrawableId = R.drawable.arrow_alizarin;
207 | containerBackDrawableId = R.color.alizarin;
208 | break;
209 | case AppIntroduction.CLOUDS:
210 | indicatorDrawableId = R.drawable.arrow_clouds;
211 | containerBackDrawableId = R.color.clouds;
212 | break;
213 | case AppIntroduction.CONCRETE:
214 | indicatorDrawableId = R.drawable.arrow_concrete;
215 | containerBackDrawableId = R.color.concrete;
216 | break;
217 | case AppIntroduction.ORANGE:
218 | indicatorDrawableId = R.drawable.arrow_orange;
219 | containerBackDrawableId = R.color.orange;
220 | break;
221 | case AppIntroduction.PUMPKIN:
222 | indicatorDrawableId = R.drawable.arrow_pumpkin;
223 | containerBackDrawableId = R.color.pumpkin;
224 | break;
225 | case AppIntroduction.POMEGRANATE:
226 | indicatorDrawableId = R.drawable.arrow_pomegranate;
227 | containerBackDrawableId = R.color.pomegranate;
228 | break;
229 | case AppIntroduction.SILVER:
230 | indicatorDrawableId = R.drawable.arrow_silver;
231 | containerBackDrawableId = R.color.silver;
232 | break;
233 | case AppIntroduction.ASBESTOS:
234 | indicatorDrawableId = R.drawable.arrow_asbestos;
235 | containerBackDrawableId = R.color.asbestos;
236 | break;
237 | }
238 |
239 |
240 | Drawable indicatorDrawable = mContext.getResources().getDrawable(indicatorDrawableId);
241 | DynamicDrawable containerBackDrawable= new DynamicDrawable(
242 | mContext.getResources().getColor(containerBackDrawableId), 4);
243 |
244 | indicator.setImageDrawable(indicatorDrawable);
245 | if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) {
246 | container.setBackgroundDrawable(containerBackDrawable);
247 | } else {
248 | container.setBackground(containerBackDrawable);
249 | }
250 | }
251 |
252 | protected void changeElement(final Step step) {
253 |
254 | if (step.getViewId() != AppIntroduction.NO_VIEW)
255 | element = mContext.findViewById(step.getViewId());
256 | else
257 | element = null;
258 |
259 | hide();
260 |
261 | // This thread is used to wait for the hide animation.
262 | Thread changeTextThread = new Thread() {
263 | @Override
264 | public void run() {
265 | try {
266 | Thread.sleep(animDuration);
267 | } catch (InterruptedException e) {
268 | }
269 |
270 | mContext.runOnUiThread(new Runnable() {
271 | @Override
272 | public void run() {
273 | explanationTextView.setText(step.getMessage());
274 | }
275 | });
276 | }
277 | };
278 | changeTextThread.start();
279 |
280 | // This thread is used for waiting the size change of the container.
281 | // The size is not changed directly after changing the text.
282 | // So we need to wait a while.
283 | Thread setSizeThread = new
284 |
285 | Thread() {
286 | @Override
287 | public void run() {
288 | try {
289 | Thread.sleep(animDuration + 50);
290 | } catch (InterruptedException e) {
291 | }
292 |
293 | mContext.runOnUiThread(new Runnable() {
294 | @Override
295 | public void run() {
296 |
297 | setVisibility(VISIBLE);
298 |
299 | if (step.getSide() == AppIntroduction.SIDE_NONE) {
300 | // if side is none, the message is shown in the middle of the screen
301 | showMessageInCenter();
302 | return;
303 | }
304 |
305 | int elementWidth = element.getWidth();
306 | int elementHeight = element.getHeight();
307 | int elementTop = getRelativeTop(element) - elementHeight / 2;
308 | int elementLeft = getRelativeLeft(element);
309 |
310 | int indicatorLeft;
311 | int indicatorTop;
312 |
313 | container.setLayoutParams(new LayoutParams(screenWidth,
314 | ViewGroup.LayoutParams.WRAP_CONTENT));
315 |
316 | if (step.getSide() == AppIntroduction.SIDE_VERTICAL) {
317 | int indicatorHorizontalCenter = elementLeft + elementWidth / 2;
318 |
319 | indicatorLeft = indicatorHorizontalCenter - indicatorSize / 2;
320 | indicatorTop = elementHeight + elementTop;
321 | if (elementTop + elementHeight > screenHeight / 2) {
322 | // indicator looking down
323 | indicatorTop -= (elementHeight + indicatorSize);
324 | rotate(0);
325 |
326 | LayoutParams layoutParams = (LayoutParams) container.getLayoutParams();
327 | layoutParams.setMargins(containerMargin, indicatorTop - container.getHeight() +
328 | (indicatorSize / 16 * 6), containerMargin, 0);
329 | container.setLayoutParams(layoutParams);
330 | } else {
331 | // indicator looking up
332 | rotate(180);
333 |
334 | LayoutParams layoutParams = (LayoutParams) container.getLayoutParams();
335 | layoutParams.setMargins(containerMargin, indicatorTop +
336 | (indicatorSize / 16 * 10), containerMargin, 0);
337 | container.setLayoutParams(layoutParams);
338 | }
339 |
340 | } else {
341 |
342 | Log.e("predict", "side is HORIZONTAL");
343 |
344 | int elementRight = elementLeft + elementWidth;
345 |
346 | int indicatorVerticalCenter = elementTop + elementHeight / 2;
347 | indicatorLeft = elementLeft + elementWidth;
348 | indicatorTop = indicatorVerticalCenter - indicatorSize / 2;
349 |
350 | if (elementRight > screenWidth / 2) {
351 |
352 | // indicator looking right
353 | indicatorLeft -= (elementWidth + indicatorSize);
354 | rotate(270);
355 |
356 | int containerRight = screenWidth - indicatorLeft - (indicatorSize / 16 * 6);
357 | int containerTop = indicatorVerticalCenter - indicatorSize / 3 * 2;
358 |
359 | if (containerTop + container.getHeight() > screenHeight)
360 | containerTop -= (container.getHeight() - indicatorSize / 3 * 4);
361 |
362 | LayoutParams layoutParams = (LayoutParams) container.getLayoutParams();
363 | layoutParams.setMargins(containerMargin, containerTop, containerRight, 0);
364 | container.setLayoutParams(layoutParams);
365 | } else {
366 |
367 | // indicator looking left
368 | rotate(90);
369 |
370 | Log.e("predict", "element is at left. ch: " + container.getHeight());
371 |
372 | int containerLeft = indicatorLeft + indicatorSize - (indicatorSize / 16 * 6);
373 | int containerTop = indicatorVerticalCenter - indicatorSize / 3 * 2;
374 |
375 | if (containerTop + container.getHeight() > screenHeight)
376 | containerTop -= (container.getHeight() - indicatorSize / 3 * 4);
377 |
378 | LayoutParams layoutParams = (LayoutParams) container.getLayoutParams();
379 | layoutParams.setMargins(containerLeft, containerTop,
380 | containerMargin, 0);
381 | container.setLayoutParams(layoutParams);
382 | }
383 | }
384 |
385 | LayoutParams layoutParams = (LayoutParams) indicator.getLayoutParams();
386 | layoutParams.setMargins(indicatorLeft, indicatorTop, indicatorLeft + indicatorSize,
387 | indicatorTop + indicatorSize);
388 | indicator.setLayoutParams(layoutParams);
389 |
390 | show();
391 | }
392 | });
393 | }
394 | };
395 | setSizeThread.start();
396 |
397 | }
398 |
399 | private void showMessageInCenter() {
400 |
401 | LayoutParams layoutParams = (LayoutParams) container.getLayoutParams();
402 | layoutParams.setMargins(containerMargin, 0, containerMargin, 0);
403 | layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, -1);
404 | container.setLayoutParams(layoutParams);
405 |
406 | // putting indicator out of the screen
407 | // otherwise it is shown after applying animation
408 | LayoutParams layoutParams2 = (LayoutParams) indicator.getLayoutParams();
409 | layoutParams2.setMargins(screenWidth, screenHeight, 0, 0);
410 | indicator.setLayoutParams(layoutParams2);
411 |
412 | show();
413 | }
414 |
415 | // not working yet
416 | public void setColor(int colorCode) {
417 | //LayerDrawable cld = (LayerDrawable) container.getBackground();
418 | //cld.get
419 | //((ShapeDrawable) container.getBackground()).getPaint().setColor(getResources().getColor(R.color.amethyst));
420 | //LayerDrawable bgDrawable = (LayerDrawable) container.getBackground();
421 | //final GradientDrawable shape = (GradientDrawable) bgDrawable.findDrawableByLayerId(R.id.border_radius_shape);
422 | //shape.setColor(Color.parseColor("#e67e22"));
423 | }
424 |
425 | protected void hide() {
426 | startAnimation(hideAnim);
427 | backgroundLayer.setVisibility(GONE);
428 | }
429 |
430 | protected void show() {
431 | startAnimation(showAnim);
432 | backgroundLayer.setVisibility(VISIBLE);
433 | }
434 |
435 | private void rotate(float degree) {
436 | final RotateAnimation rotateAnim = new RotateAnimation(0.0f, degree,
437 | RotateAnimation.RELATIVE_TO_SELF, 0.5f,
438 | RotateAnimation.RELATIVE_TO_SELF, 0.5f);
439 |
440 | rotateAnim.setDuration(0);
441 | rotateAnim.setFillAfter(true);
442 | indicator.startAnimation(rotateAnim);
443 | }
444 |
445 | private int getRelativeLeft(View myView) {
446 | if (myView.getParent() == myView.getRootView())
447 | return myView.getLeft();
448 | else
449 | return myView.getLeft() + getRelativeLeft((View) myView.getParent());
450 | }
451 |
452 | private int getRelativeTop(View myView) {
453 | if (myView.getParent() == myView.getRootView())
454 | return myView.getTop();
455 | else
456 | return myView.getTop() + getRelativeTop((View) myView.getParent());
457 | }
458 |
459 | }
460 |
--------------------------------------------------------------------------------
/src/com/eluleci/appintroduction/listeners/StepActionListener.java:
--------------------------------------------------------------------------------
1 | package com.eluleci.appintroduction.listeners;
2 |
3 | /**
4 | * Created with IntelliJ IDEA.
5 | * User: eluleci
6 | * Date: 19.09.2013
7 | * Time: 23:19
8 | */
9 | public interface StepActionListener {
10 |
11 | void beforeMessageShown();
12 |
13 | void afterMessageShown();
14 | }
15 |
--------------------------------------------------------------------------------
/src/com/eluleci/appintroduction/listeners/UserActionListener.java:
--------------------------------------------------------------------------------
1 | package com.eluleci.appintroduction.listeners;
2 |
3 | /**
4 | * Created with IntelliJ IDEA.
5 | * User: eluleci
6 | * Date: 08.08.2013
7 | * Time: 22:29
8 | */
9 | public interface UserActionListener {
10 | void onNextClicked();
11 |
12 | void onDismiss();
13 | }
14 |
--------------------------------------------------------------------------------
/src/com/eluleci/appintroduction/views/DynamicDrawable.java:
--------------------------------------------------------------------------------
1 | package com.eluleci.appintroduction.views;
2 |
3 | import android.graphics.drawable.GradientDrawable;
4 |
5 | /**
6 | * Created with IntelliJ IDEA.
7 | * User: eluleci
8 | * Date: 21.10.2013
9 | * Time: 14:23
10 | */
11 | public class DynamicDrawable extends GradientDrawable {
12 |
13 | public DynamicDrawable(int pStartColor, int pCenterColor, int pEndColor, int pStrokeWidth, int pStrokeColor, float cornerRadius) {
14 | super(Orientation.BOTTOM_TOP,new int[]{pStartColor,pCenterColor,pEndColor});
15 | setStroke(pStrokeWidth,pStrokeColor);
16 | setShape(GradientDrawable.RECTANGLE);
17 | setCornerRadius(cornerRadius);
18 | }
19 |
20 | public DynamicDrawable(int color, float cornerRadius) {
21 | super(Orientation.BOTTOM_TOP,new int[]{color,color,color});
22 | setStroke(1,color);
23 | setShape(GradientDrawable.RECTANGLE);
24 | setCornerRadius(cornerRadius);
25 | }
26 | }
--------------------------------------------------------------------------------
/src/com/eluleci/appintroduction/views/TextViewLight.java:
--------------------------------------------------------------------------------
1 | package com.eluleci.appintroduction.views;
2 |
3 | import android.content.Context;
4 | import android.graphics.Typeface;
5 | import android.util.AttributeSet;
6 | import android.widget.TextView;
7 |
8 | /**
9 | * Created with IntelliJ IDEA.
10 | * User: eluleci
11 | * Date: 7/07/13
12 | * Time: 1:43 PM
13 | */
14 | public class TextViewLight extends TextView {
15 |
16 | public TextViewLight(Context context, AttributeSet attrs, int defStyle) {
17 | super(context, attrs, defStyle);
18 | init();
19 | }
20 |
21 | public TextViewLight(Context context, AttributeSet attrs) {
22 | super(context, attrs);
23 | init();
24 | }
25 |
26 | public TextViewLight(Context context) {
27 | super(context);
28 | init();
29 | }
30 |
31 | private void init() {
32 | Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "fonts/roboto_light.ttf");
33 | setTypeface(tf);
34 | }
35 |
36 | }
--------------------------------------------------------------------------------
/src/com/eluleci/appintroduction/views/TextViewRegular.java:
--------------------------------------------------------------------------------
1 | package com.eluleci.appintroduction.views;
2 |
3 | import android.content.Context;
4 | import android.graphics.Typeface;
5 | import android.util.AttributeSet;
6 | import android.widget.TextView;
7 |
8 | /**
9 | * Created with IntelliJ IDEA.
10 | * User: eluleci
11 | * Date: 7/07/13
12 | * Time: 1:43 PM
13 | */
14 | public class TextViewRegular extends TextView {
15 |
16 | public TextViewRegular(Context context, AttributeSet attrs, int defStyle) {
17 | super(context, attrs, defStyle);
18 | init();
19 | }
20 |
21 | public TextViewRegular(Context context, AttributeSet attrs) {
22 | super(context, attrs);
23 | init();
24 | }
25 |
26 | public TextViewRegular(Context context) {
27 | super(context);
28 | init();
29 | }
30 |
31 | private void init() {
32 | Typeface tf = Typeface.createFromAsset(getContext().getAssets(), "fonts/roboto_regular.ttf");
33 | setTypeface(tf);
34 | }
35 |
36 | }
--------------------------------------------------------------------------------