├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── dictionaries │ └── Chandru_MacBook.xml ├── gradle.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── AppIntroAnimation.iml ├── LICENSE.txt ├── README.md ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── takeoffandroid │ │ └── appintroanimation │ │ ├── CirclePageIndicator.java │ │ ├── ColorShades.java │ │ └── MainActivity.java │ └── res │ ├── drawable │ ├── calendar.png │ ├── email.png │ ├── round_rectangle_semi_transparent.xml │ ├── shopping.png │ └── socialnetwork.png │ ├── layout │ ├── activity_main.xml │ └── viewpager_item.xml │ ├── menu │ └── menu_main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── values-hdpi │ └── dimens.xml │ ├── values-large-mdpi │ └── dimens.xml │ ├── values-mdpi │ └── dimens.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── arrays.xml │ ├── color.xml │ ├── dimens.xml │ ├── strings.xml │ ├── styles.xml │ ├── vpi__attrs.xml │ ├── vpi__colors.xml │ └── vpi__defaults.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | /captures 8 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | AppIntroAnimation -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/dictionaries/Chandru_MacBook.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Android 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 38 | 39 | 40 | 41 | 42 | 1.7 43 | 44 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /AppIntroAnimation.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Chandrasekar K 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so without any conditions and terms. 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-AppIntroAnimation-brightgreen.svg?style=flat)](http://android-arsenal.com/details/3/2226) 2 | 3 | 4 | # AppIntroAnimation 5 | AppIntroAnimation is a set of code snippets to make cool intro screen for your app with special Image Translation and Transformation animation effects. It is very easy to use and customize without adding third party library integrations. 6 | 7 | Demo I | Demo II 8 | -------- | --- 9 | ![appintro1](https://cloud.githubusercontent.com/assets/11768239/9027657/600244d6-397b-11e5-916f-409d4ab3de28.gif) | ![appintro2](https://cloud.githubusercontent.com/assets/11768239/9027658/6009bae0-397b-11e5-9377-78abe437ff7d.gif) 10 | 11 | > **Demo I** Enable `private boolean isSliderAnimation = false;` in `MainActivity.java` to apply this background pager transformation animation with Image translation effect.. 12 | 13 | > **Demo II** Enable `private boolean isSliderAnimation = true;` in `MainActivity.java` to apply this background pager transformation animation without Image translation effect.. 14 | 15 | 16 | 17 | How to use 18 | ---------- 19 | 20 | **STEP 1**: 21 | 22 | Download the code and open `arrays.xml`. 23 | 24 | 25 | 26 | @color/light_green 27 | @color/light_purple 28 | @color/light_orange 29 | @color/light_cyan 30 | 31 | 32 | 33 | @drawable/email 34 | @drawable/calendar 35 | @drawable/shopping 36 | @drawable/socialnetwork 37 | 38 | 39 | 40 | @string/email 41 | @string/calender 42 | @string/shopping 43 | @string/social_network 44 | 45 | 46 | 47 | @string/email_hint 48 | @string/calender_hint 49 | @string/shopping_hint 50 | @string/social_network_hint 51 | 52 | 53 | Here I have added 4 slides with images, titles and title hints. You can update your png's, text content in above arrays.xml as per your project need and requirement. 54 | 55 | 56 | > **Note:** The array count of images, titles and title hints should be of same count to avoid IndexBoundException. 57 | 58 | 59 | 60 | **STEP 2**: 61 | 62 | Drop all your images that are to be used for making AppIntro's into drawable folders. To get exact output for multiple resolution and sizes, add scaled images seperately for drawable-xxxhdpi, drawable-xxhdpi, drawable-xhdpi, drawable-hdpi, drawable-mdpi etc., and fix the height and width of ImageView in `viewpager_item.xml` 63 | 64 | Customization 65 | ------------- 66 | 67 | To customize pager attributes like indicator stroke size, stroke color, solid color, solid size, solid color, selected color and unselected color, please open `vpi_defaults.xml` and customize according to your wish. 68 | 69 | Following are the attributes that I have used in my project demo, you can also customize your own. 70 | 71 | 72 | true 73 | #FFFFFFFF 74 | #40FFFFFF 75 | 0 76 | 3dp 77 | false 78 | #40FFFFFF 79 | 1dp 80 | 81 | 82 | The app which inspired me to create this repos 83 | 84 | > - Background color transformation animation used in [Google Inbox][1] intro screen. 85 | > - Image translation animation used in [Duolingo][2] intro screen. 86 | 87 | [1]: https://play.google.com/store/apps/details?id=com.google.android.apps.inbox 88 | [2]: https://play.google.com/store/apps/details?id=com.duolingo 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "22.0.1" 6 | 7 | defaultConfig { 8 | applicationId "com.takeoffandroid.appintroanimation" 9 | minSdkVersion 8 10 | targetSdkVersion 22 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | compile 'com.android.support:appcompat-v7:22.2.0' 25 | compile 'com.android.support:support-v4:22.2.0' 26 | } 27 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/Chandru-MacBook/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/takeoffandroid/appintroanimation/CirclePageIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Patrik Akerfeldt 3 | * Copyright (C) 2011 Jake Wharton 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.takeoffandroid.appintroanimation; 18 | 19 | 20 | import android.content.Context; 21 | import android.content.res.Resources; 22 | import android.content.res.TypedArray; 23 | import android.graphics.Canvas; 24 | import android.graphics.Paint; 25 | import android.graphics.Paint.Style; 26 | import android.graphics.drawable.Drawable; 27 | import android.os.Parcel; 28 | import android.os.Parcelable; 29 | import android.support.v4.view.MotionEventCompat; 30 | import android.support.v4.view.ViewConfigurationCompat; 31 | import android.support.v4.view.ViewPager; 32 | import android.util.AttributeSet; 33 | import android.view.MotionEvent; 34 | import android.view.View; 35 | import android.view.ViewConfiguration; 36 | 37 | import static android.graphics.Paint.ANTI_ALIAS_FLAG; 38 | import static android.widget.LinearLayout.HORIZONTAL; 39 | import static android.widget.LinearLayout.VERTICAL; 40 | 41 | 42 | /** 43 | * Draws circles (one for each view). The current view position is filled and 44 | * others are only stroked. 45 | */ 46 | public class CirclePageIndicator extends View implements PageIndicator { 47 | 48 | private static final int INVALID_POINTER = -1; 49 | 50 | private float mRadius; 51 | private final Paint mPaintPageFill = new Paint(ANTI_ALIAS_FLAG); 52 | private final Paint mPaintStroke = new Paint(ANTI_ALIAS_FLAG); 53 | private final Paint mPaintFill = new Paint(ANTI_ALIAS_FLAG); 54 | private ViewPager mViewPager; 55 | private ViewPager.OnPageChangeListener mListener; 56 | private int mCurrentPage; 57 | private int mSnapPage; 58 | private float mPageOffset; 59 | private int mScrollState; 60 | private int mOrientation; 61 | private boolean mCentered; 62 | private boolean mSnap; 63 | 64 | private int mTouchSlop; 65 | private float mLastMotionX = -1; 66 | private int mActivePointerId = INVALID_POINTER; 67 | private boolean mIsDragging; 68 | 69 | 70 | public CirclePageIndicator(Context context) { 71 | this(context, null); 72 | } 73 | 74 | public CirclePageIndicator(Context context, AttributeSet attrs) { 75 | this(context, attrs, R.attr.vpiCirclePageIndicatorStyle); 76 | } 77 | 78 | public CirclePageIndicator(Context context, AttributeSet attrs, int defStyle) { 79 | super(context, attrs, defStyle); 80 | if (isInEditMode()) return; 81 | 82 | //Load defaults from resources 83 | final Resources res = getResources(); 84 | final int defaultPageColor = res.getColor(R.color.default_circle_indicator_page_color); 85 | final int defaultFillColor = res.getColor(R.color.default_circle_indicator_fill_color); 86 | final int defaultOrientation = res.getInteger(R.integer.default_circle_indicator_orientation); 87 | final int defaultStrokeColor = res.getColor(R.color.default_circle_indicator_stroke_color); 88 | final float defaultStrokeWidth = res.getDimension(R.dimen.default_circle_indicator_stroke_width); 89 | final float defaultRadius = res.getDimension(R.dimen.viewpager_circleindicator_radius); 90 | final boolean defaultCentered = res.getBoolean(R.bool.default_circle_indicator_centered); 91 | final boolean defaultSnap = res.getBoolean(R.bool.default_circle_indicator_snap); 92 | 93 | //Retrieve styles attributes 94 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CirclePageIndicator, defStyle, 0); 95 | 96 | mCentered = a.getBoolean(R.styleable.CirclePageIndicator_centered, defaultCentered); 97 | mOrientation = a.getInt(R.styleable.CirclePageIndicator_android_orientation, defaultOrientation); 98 | mPaintPageFill.setStyle(Style.FILL); 99 | mPaintPageFill.setColor(a.getColor(R.styleable.CirclePageIndicator_pageColor, defaultPageColor)); 100 | mPaintStroke.setStyle(Style.STROKE); 101 | mPaintStroke.setColor(a.getColor(R.styleable.CirclePageIndicator_strokeColor, defaultStrokeColor)); 102 | mPaintStroke.setStrokeWidth(a.getDimension(R.styleable.CirclePageIndicator_strokeWidth, defaultStrokeWidth)); 103 | mPaintFill.setStyle(Style.FILL); 104 | mPaintFill.setColor(a.getColor(R.styleable.CirclePageIndicator_fillColor, defaultFillColor)); 105 | mRadius = a.getDimension(R.styleable.CirclePageIndicator_radius, defaultRadius); 106 | mSnap = a.getBoolean(R.styleable.CirclePageIndicator_snap, defaultSnap); 107 | 108 | Drawable background = a.getDrawable(R.styleable.CirclePageIndicator_android_background); 109 | if (background != null) { 110 | setBackgroundDrawable(background); 111 | } 112 | 113 | a.recycle(); 114 | 115 | final ViewConfiguration configuration = ViewConfiguration.get(context); 116 | mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); 117 | } 118 | 119 | 120 | public void setCentered(boolean centered) { 121 | mCentered = centered; 122 | invalidate(); 123 | } 124 | 125 | public boolean isCentered() { 126 | return mCentered; 127 | } 128 | 129 | public void setPageColor(int pageColor) { 130 | mPaintPageFill.setColor(pageColor); 131 | invalidate(); 132 | } 133 | 134 | public int getPageColor() { 135 | return mPaintPageFill.getColor(); 136 | } 137 | 138 | public void setFillColor(int fillColor) { 139 | mPaintFill.setColor(fillColor); 140 | invalidate(); 141 | } 142 | 143 | public int getFillColor() { 144 | return mPaintFill.getColor(); 145 | } 146 | 147 | public void setOrientation(int orientation) { 148 | switch (orientation) { 149 | case HORIZONTAL: 150 | case VERTICAL: 151 | mOrientation = orientation; 152 | requestLayout(); 153 | break; 154 | 155 | default: 156 | throw new IllegalArgumentException("Orientation must be either HORIZONTAL or VERTICAL."); 157 | } 158 | } 159 | 160 | public int getOrientation() { 161 | return mOrientation; 162 | } 163 | 164 | public void setStrokeColor(int strokeColor) { 165 | mPaintStroke.setColor(strokeColor); 166 | invalidate(); 167 | } 168 | 169 | public int getStrokeColor() { 170 | return mPaintStroke.getColor(); 171 | } 172 | 173 | public void setStrokeWidth(float strokeWidth) { 174 | mPaintStroke.setStrokeWidth(strokeWidth); 175 | invalidate(); 176 | } 177 | 178 | public float getStrokeWidth() { 179 | return mPaintStroke.getStrokeWidth(); 180 | } 181 | 182 | public void setRadius(float radius) { 183 | mRadius = radius; 184 | invalidate(); 185 | } 186 | 187 | public float getRadius() { 188 | return mRadius; 189 | } 190 | 191 | public void setSnap(boolean snap) { 192 | mSnap = snap; 193 | invalidate(); 194 | } 195 | 196 | public boolean isSnap() { 197 | return mSnap; 198 | } 199 | 200 | @Override 201 | protected void onDraw(Canvas canvas) { 202 | super.onDraw(canvas); 203 | 204 | if (mViewPager == null) { 205 | return; 206 | } 207 | final int count = mViewPager.getAdapter().getCount(); 208 | if (count == 0) { 209 | return; 210 | } 211 | 212 | if (mCurrentPage >= count) { 213 | setCurrentItem(count - 1); 214 | return; 215 | } 216 | 217 | int longSize; 218 | int longPaddingBefore; 219 | int longPaddingAfter; 220 | int shortPaddingBefore; 221 | if (mOrientation == HORIZONTAL) { 222 | longSize = getWidth(); 223 | longPaddingBefore = getPaddingLeft(); 224 | longPaddingAfter = getPaddingRight(); 225 | shortPaddingBefore = getPaddingTop(); 226 | } else { 227 | longSize = getHeight(); 228 | longPaddingBefore = getPaddingTop(); 229 | longPaddingAfter = getPaddingBottom(); 230 | shortPaddingBefore = getPaddingLeft(); 231 | } 232 | 233 | final float threeRadius = mRadius * 3; 234 | final float shortOffset = shortPaddingBefore + mRadius; 235 | float longOffset = longPaddingBefore + mRadius; 236 | if (mCentered) { 237 | longOffset += ((longSize - longPaddingBefore - longPaddingAfter) / 2.0f) - ((count * threeRadius) / 2.0f); 238 | } 239 | 240 | float dX; 241 | float dY; 242 | 243 | float pageFillRadius = mRadius; 244 | if (mPaintStroke.getStrokeWidth() > 0) { 245 | pageFillRadius -= mPaintStroke.getStrokeWidth() / 2.0f; 246 | } 247 | 248 | //Draw stroked circles 249 | for (int iLoop = 0; iLoop < count; iLoop++) { 250 | float drawLong = longOffset + (iLoop * threeRadius); 251 | if (mOrientation == HORIZONTAL) { 252 | dX = drawLong; 253 | dY = shortOffset; 254 | } else { 255 | dX = shortOffset; 256 | dY = drawLong; 257 | } 258 | // Only paint fill if not completely transparent 259 | if (mPaintPageFill.getAlpha() > 0) { 260 | canvas.drawCircle(dX, dY, pageFillRadius, mPaintPageFill); 261 | } 262 | 263 | // Only paint stroke if a stroke width was non-zero 264 | if (pageFillRadius != mRadius) { 265 | canvas.drawCircle(dX, dY, mRadius, mPaintStroke); 266 | } 267 | } 268 | 269 | //Draw the filled circle according to the current scroll 270 | float cx = (mSnap ? mSnapPage : mCurrentPage) * threeRadius; 271 | if (!mSnap) { 272 | cx += mPageOffset * threeRadius; 273 | } 274 | if (mOrientation == HORIZONTAL) { 275 | dX = longOffset + cx; 276 | dY = shortOffset; 277 | } else { 278 | dX = shortOffset; 279 | dY = longOffset + cx; 280 | } 281 | canvas.drawCircle(dX, dY, mRadius, mPaintFill); 282 | } 283 | 284 | public boolean onTouchEvent(MotionEvent ev) { 285 | if (super.onTouchEvent(ev)) { 286 | return true; 287 | } 288 | if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) { 289 | return false; 290 | } 291 | 292 | final int action = ev.getAction() & MotionEventCompat.ACTION_MASK; 293 | switch (action) { 294 | case MotionEvent.ACTION_DOWN: 295 | mActivePointerId = MotionEventCompat.getPointerId(ev, 0); 296 | mLastMotionX = ev.getX(); 297 | break; 298 | 299 | case MotionEvent.ACTION_MOVE: { 300 | final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); 301 | final float x = MotionEventCompat.getX(ev, activePointerIndex); 302 | final float deltaX = x - mLastMotionX; 303 | 304 | if (!mIsDragging) { 305 | if (Math.abs(deltaX) > mTouchSlop) { 306 | mIsDragging = true; 307 | } 308 | } 309 | 310 | if (mIsDragging) { 311 | mLastMotionX = x; 312 | if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) { 313 | mViewPager.fakeDragBy(deltaX); 314 | } 315 | } 316 | 317 | break; 318 | } 319 | 320 | case MotionEvent.ACTION_CANCEL: 321 | case MotionEvent.ACTION_UP: 322 | if (!mIsDragging) { 323 | final int count = mViewPager.getAdapter().getCount(); 324 | final int width = getWidth(); 325 | final float halfWidth = width / 2f; 326 | final float sixthWidth = width / 6f; 327 | 328 | if ((mCurrentPage > 0) && (ev.getX() < halfWidth - sixthWidth)) { 329 | if (action != MotionEvent.ACTION_CANCEL) { 330 | mViewPager.setCurrentItem(mCurrentPage - 1); 331 | } 332 | return true; 333 | } else if ((mCurrentPage < count - 1) && (ev.getX() > halfWidth + sixthWidth)) { 334 | if (action != MotionEvent.ACTION_CANCEL) { 335 | mViewPager.setCurrentItem(mCurrentPage + 1); 336 | } 337 | return true; 338 | } 339 | } 340 | 341 | mIsDragging = false; 342 | mActivePointerId = INVALID_POINTER; 343 | if (mViewPager.isFakeDragging()) mViewPager.endFakeDrag(); 344 | break; 345 | 346 | case MotionEventCompat.ACTION_POINTER_DOWN: { 347 | final int index = MotionEventCompat.getActionIndex(ev); 348 | mLastMotionX = MotionEventCompat.getX(ev, index); 349 | mActivePointerId = MotionEventCompat.getPointerId(ev, index); 350 | break; 351 | } 352 | 353 | case MotionEventCompat.ACTION_POINTER_UP: 354 | final int pointerIndex = MotionEventCompat.getActionIndex(ev); 355 | final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); 356 | if (pointerId == mActivePointerId) { 357 | final int newPointerIndex = pointerIndex == 0 ? 1 : 0; 358 | mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); 359 | } 360 | mLastMotionX = MotionEventCompat.getX(ev, MotionEventCompat.findPointerIndex(ev, mActivePointerId)); 361 | break; 362 | } 363 | 364 | return true; 365 | } 366 | 367 | @Override 368 | public void setViewPager(ViewPager view) { 369 | if (mViewPager == view) { 370 | return; 371 | } 372 | if (mViewPager != null) { 373 | mViewPager.setOnPageChangeListener(null); 374 | } 375 | if (view.getAdapter() == null) { 376 | throw new IllegalStateException("ViewPager does not have adapter instance."); 377 | } 378 | mViewPager = view; 379 | mViewPager.setOnPageChangeListener(this); 380 | invalidate(); 381 | } 382 | 383 | @Override 384 | public void setViewPager(ViewPager view, int initialPosition) { 385 | setViewPager(view); 386 | setCurrentItem(initialPosition); 387 | } 388 | 389 | @Override 390 | public void setCurrentItem(int item) { 391 | if (mViewPager == null) { 392 | throw new IllegalStateException("ViewPager has not been bound."); 393 | } 394 | mViewPager.setCurrentItem(item); 395 | mCurrentPage = item; 396 | invalidate(); 397 | } 398 | 399 | @Override 400 | public void notifyDataSetChanged() { 401 | invalidate(); 402 | } 403 | 404 | @Override 405 | public void onPageScrollStateChanged(int state) { 406 | mScrollState = state; 407 | 408 | if (mListener != null) { 409 | mListener.onPageScrollStateChanged(state); 410 | } 411 | } 412 | 413 | @Override 414 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 415 | mCurrentPage = position; 416 | mPageOffset = positionOffset; 417 | invalidate(); 418 | 419 | if (mListener != null) { 420 | mListener.onPageScrolled(position, positionOffset, positionOffsetPixels); 421 | } 422 | } 423 | 424 | @Override 425 | public void onPageSelected(int position) { 426 | if (mSnap || mScrollState == ViewPager.SCROLL_STATE_IDLE) { 427 | mCurrentPage = position; 428 | mSnapPage = position; 429 | invalidate(); 430 | } 431 | 432 | if (mListener != null) { 433 | mListener.onPageSelected(position); 434 | } 435 | } 436 | 437 | @Override 438 | public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { 439 | mListener = listener; 440 | } 441 | 442 | /* 443 | * (non-Javadoc) 444 | * 445 | * @see android.view.View#onMeasure(int, int) 446 | */ 447 | @Override 448 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 449 | if (mOrientation == HORIZONTAL) { 450 | setMeasuredDimension(measureLong(widthMeasureSpec), measureShort(heightMeasureSpec)); 451 | } else { 452 | setMeasuredDimension(measureShort(widthMeasureSpec), measureLong(heightMeasureSpec)); 453 | } 454 | } 455 | 456 | /** 457 | * Determines the width of this view 458 | * 459 | * @param measureSpec 460 | * A measureSpec packed into an int 461 | * @return The width of the view, honoring constraints from measureSpec 462 | */ 463 | private int measureLong(int measureSpec) { 464 | int result; 465 | int specMode = MeasureSpec.getMode(measureSpec); 466 | int specSize = MeasureSpec.getSize(measureSpec); 467 | 468 | if ((specMode == MeasureSpec.EXACTLY) || (mViewPager == null)) { 469 | //We were told how big to be 470 | result = specSize; 471 | } else { 472 | //Calculate the width according the views count 473 | final int count = mViewPager.getAdapter().getCount(); 474 | result = (int)(getPaddingLeft() + getPaddingRight() 475 | + (count * 2 * mRadius) + (count - 1) * mRadius + 1); 476 | //Respect AT_MOST value if that was what is called for by measureSpec 477 | if (specMode == MeasureSpec.AT_MOST) { 478 | result = Math.min(result, specSize); 479 | } 480 | } 481 | return result; 482 | } 483 | 484 | /** 485 | * Determines the height of this view 486 | * 487 | * @param measureSpec 488 | * A measureSpec packed into an int 489 | * @return The height of the view, honoring constraints from measureSpec 490 | */ 491 | private int measureShort(int measureSpec) { 492 | int result; 493 | int specMode = MeasureSpec.getMode(measureSpec); 494 | int specSize = MeasureSpec.getSize(measureSpec); 495 | 496 | if (specMode == MeasureSpec.EXACTLY) { 497 | //We were told how big to be 498 | result = specSize; 499 | } else { 500 | //Measure the height 501 | result = (int)(2 * mRadius + getPaddingTop() + getPaddingBottom() + 1); 502 | //Respect AT_MOST value if that was what is called for by measureSpec 503 | if (specMode == MeasureSpec.AT_MOST) { 504 | result = Math.min(result, specSize); 505 | } 506 | } 507 | return result; 508 | } 509 | 510 | @Override 511 | public void onRestoreInstanceState(Parcelable state) { 512 | SavedState savedState = (SavedState)state; 513 | super.onRestoreInstanceState(savedState.getSuperState()); 514 | mCurrentPage = savedState.currentPage; 515 | mSnapPage = savedState.currentPage; 516 | requestLayout(); 517 | } 518 | 519 | @Override 520 | public Parcelable onSaveInstanceState() { 521 | Parcelable superState = super.onSaveInstanceState(); 522 | SavedState savedState = new SavedState(superState); 523 | savedState.currentPage = mCurrentPage; 524 | return savedState; 525 | } 526 | 527 | static class SavedState extends BaseSavedState { 528 | int currentPage; 529 | 530 | public SavedState(Parcelable superState) { 531 | super(superState); 532 | } 533 | 534 | private SavedState(Parcel in) { 535 | super(in); 536 | currentPage = in.readInt(); 537 | } 538 | 539 | @Override 540 | public void writeToParcel(Parcel dest, int flags) { 541 | super.writeToParcel(dest, flags); 542 | dest.writeInt(currentPage); 543 | } 544 | 545 | @SuppressWarnings("UnusedDeclaration") 546 | public static final Creator CREATOR = new Creator() { 547 | @Override 548 | public SavedState createFromParcel(Parcel in) { 549 | return new SavedState(in); 550 | } 551 | 552 | @Override 553 | public SavedState[] newArray(int size) { 554 | return new SavedState[size]; 555 | } 556 | }; 557 | } 558 | } 559 | 560 | interface PageIndicator extends ViewPager.OnPageChangeListener { 561 | /** 562 | * Bind the indicator to a ViewPager. 563 | * 564 | * @param view 565 | */ 566 | void setViewPager(ViewPager view); 567 | 568 | /** 569 | * Bind the indicator to a ViewPager. 570 | * 571 | * @param view 572 | * @param initialPosition 573 | */ 574 | void setViewPager(ViewPager view, int initialPosition); 575 | 576 | /** 577 | *

Set the current page of both the ViewPager and indicator.

578 | * 579 | *

This must be used if you need to set the page before 580 | * the views are drawn on screen (e.g., default start page).

581 | * 582 | * @param item 583 | */ 584 | void setCurrentItem(int item); 585 | 586 | /** 587 | * Set a page change listener which will receive forwarded events. 588 | * 589 | * @param listener 590 | */ 591 | void setOnPageChangeListener(ViewPager.OnPageChangeListener listener); 592 | 593 | /** 594 | * Notify the indicator that the fragment list has changed. 595 | */ 596 | void notifyDataSetChanged(); 597 | } 598 | -------------------------------------------------------------------------------- /app/src/main/java/com/takeoffandroid/appintroanimation/ColorShades.java: -------------------------------------------------------------------------------- 1 | package com.takeoffandroid.appintroanimation; 2 | 3 | import android.graphics.Color; 4 | 5 | 6 | /** 7 | * 8 | * Source from : https://gist.github.com/cooltechworks/4f37021b1216f773daf8 9 | * Color shades will provide all the intermediate colors between two colors. It just requires a decimal value between 0.0 to 1.0 10 | * and it provides the exact shade combination of the two color with this shade value. 11 | * 12 | * Textual explanation : 13 | * 14 | * |===============|===============|===============|===============| 15 | * White LtGray Gray DkGray Black 16 | * 17 | * 0 0.25 0.5 0.75 1 18 | * 19 | * Given two colors as White and Black, 20 | * and shade 21 | * as 0 gives White 22 | * as 0.25 gives Light gray 23 | * as 0.5 gives Gray 24 | * as 0.75 gives Dark gray 25 | * as 1 gives Black. 26 | * 27 | */ 28 | public class ColorShades { 29 | 30 | private int mFromColor; 31 | private int mToColor; 32 | private float mShade; 33 | 34 | public ColorShades setFromColor(int fromColor) { 35 | this.mFromColor = fromColor; 36 | return this; 37 | } 38 | 39 | public ColorShades setToColor(int toColor) { 40 | this.mToColor = toColor; 41 | return this; 42 | } 43 | 44 | public ColorShades setFromColor(String fromColor) { 45 | 46 | this.mFromColor = Color.parseColor(fromColor); 47 | return this; 48 | } 49 | 50 | public ColorShades setToColor(String toColor) { 51 | this.mToColor = Color.parseColor(toColor); 52 | return this; 53 | } 54 | 55 | public ColorShades forLightShade(int color) { 56 | setFromColor(Color.WHITE); 57 | setToColor(color); 58 | return this; 59 | } 60 | 61 | public ColorShades forDarkShare(int color) { 62 | setFromColor(color); 63 | setToColor(Color.BLACK); 64 | return this; 65 | } 66 | 67 | public ColorShades setShade(float mShade) { 68 | this.mShade = mShade; 69 | return this; 70 | } 71 | 72 | 73 | /** 74 | * Generates the shade for the given color. 75 | * @return the int value of the shade. 76 | */ 77 | public int generate() { 78 | 79 | int fromR = (Color.red(mFromColor)); 80 | int fromG = (Color.green(mFromColor)); 81 | int fromB = (Color.blue(mFromColor)); 82 | 83 | int toR = (Color.red(mToColor)); 84 | int toG = (Color.green(mToColor)); 85 | int toB = (Color.blue(mToColor)); 86 | 87 | int diffR = toR - fromR; 88 | int diffG = toG - fromG; 89 | int diffB = toB - fromB; 90 | 91 | 92 | 93 | int R = fromR + (int) (( diffR * mShade)); 94 | int G = fromG + (int) (( diffG * mShade)); 95 | int B = fromB + (int) (( diffB * mShade)); 96 | 97 | return Color.rgb(R, G, B); 98 | 99 | } 100 | 101 | 102 | /** 103 | * Assumes the from and to color are inverted before generating the shade. 104 | * @return the int value of the inverted shade. 105 | */ 106 | public int generateInverted() { 107 | 108 | int fromR = (Color.red(mFromColor)); 109 | int fromG = (Color.green(mFromColor)); 110 | int fromB = (Color.blue(mFromColor)); 111 | 112 | int toR = (Color.red(mToColor)); 113 | int toG = (Color.green(mToColor)); 114 | int toB = (Color.blue(mToColor)); 115 | 116 | 117 | int diffR = toR - fromR; 118 | int diffG = toG - fromG; 119 | int diffB = toB - fromB; 120 | 121 | int R = toR - (int) (( diffR * mShade)); 122 | int G = toG - (int) (( diffG * mShade)); 123 | int B = toB - (int) (( diffB * mShade)); 124 | 125 | return Color.rgb(R, G, B); 126 | 127 | } 128 | 129 | /** 130 | * Gets the String equivalent of the generated shade 131 | * @return String value of the shade 132 | */ 133 | public String generateInvertedString() { 134 | return String.format("#%06X", 0xFFFFFF & generateInverted()); 135 | } 136 | 137 | /** 138 | * Gets the inverted String equivalent of the generated shade 139 | * @return String value of the shade 140 | */ 141 | public String generateString() { 142 | return String.format("#%06X", 0xFFFFFF & generate()); 143 | } 144 | 145 | } -------------------------------------------------------------------------------- /app/src/main/java/com/takeoffandroid/appintroanimation/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.takeoffandroid.appintroanimation; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.graphics.drawable.Drawable; 6 | import android.os.Build; 7 | import android.os.Bundle; 8 | import android.support.v4.view.PagerAdapter; 9 | import android.support.v4.view.ViewPager; 10 | import android.support.v7.app.AppCompatActivity; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.view.Window; 14 | import android.view.WindowManager; 15 | import android.widget.ImageView; 16 | import android.widget.RelativeLayout; 17 | import android.widget.TextView; 18 | 19 | 20 | public class MainActivity extends AppCompatActivity{ 21 | 22 | private static final String SAVING_STATE_SLIDER_ANIMATION = "SliderAnimationSavingState"; 23 | private boolean isSliderAnimation = false; 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | 29 | Window window = getWindow(); 30 | window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 31 | setContentView(R.layout.activity_main); 32 | 33 | ViewPager viewPager = (ViewPager) findViewById(R.id.pager); 34 | 35 | viewPager.setAdapter(new ViewPagerAdapter(R.array.icons, R.array.titles, R.array.hints)); 36 | 37 | CirclePageIndicator mIndicator = (CirclePageIndicator) findViewById(R.id.indicator); 38 | mIndicator.setViewPager(viewPager); 39 | 40 | 41 | 42 | viewPager.setPageTransformer(true, new CustomPageTransformer()); 43 | 44 | viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { 45 | @Override 46 | public void onPageScrolled(final int position, float positionOffset, int positionOffsetPixels) { 47 | 48 | View landingBGView = findViewById(R.id.landing_backgrond); 49 | int colorBg[] = getResources().getIntArray(R.array.landing_bg); 50 | 51 | 52 | ColorShades shades = new ColorShades(); 53 | shades.setFromColor(colorBg[position % colorBg.length]) 54 | .setToColor(colorBg[(position + 1) % colorBg.length]) 55 | .setShade(positionOffset); 56 | 57 | landingBGView.setBackgroundColor(shades.generate()); 58 | 59 | } 60 | 61 | public void onPageSelected(int position) { 62 | 63 | } 64 | 65 | public void onPageScrollStateChanged(int state) { 66 | } 67 | }); 68 | 69 | 70 | } 71 | 72 | public class ViewPagerAdapter extends PagerAdapter { 73 | 74 | private int iconResId, titleArrayResId, hintArrayResId; 75 | 76 | public ViewPagerAdapter(int iconResId, int titleArrayResId, int hintArrayResId) { 77 | 78 | this.iconResId = iconResId; 79 | this.titleArrayResId = titleArrayResId; 80 | this.hintArrayResId = hintArrayResId; 81 | } 82 | 83 | @Override 84 | public int getCount() { 85 | return getResources().getIntArray(iconResId).length; 86 | } 87 | 88 | @Override 89 | public boolean isViewFromObject(View view, Object object) { 90 | return view == object; 91 | } 92 | 93 | @Override 94 | public Object instantiateItem(ViewGroup container, int position) { 95 | 96 | Drawable icon = getResources().obtainTypedArray(iconResId).getDrawable(position); 97 | String title = getResources().getStringArray(titleArrayResId)[position]; 98 | String hint = getResources().getStringArray(hintArrayResId)[position]; 99 | 100 | 101 | View itemView = getLayoutInflater().inflate(R.layout.viewpager_item, container, false); 102 | 103 | 104 | ImageView iconView = (ImageView) itemView.findViewById(R.id.landing_img_slide); 105 | TextView titleView = (TextView)itemView.findViewById(R.id.landing_txt_title); 106 | TextView hintView = (TextView)itemView.findViewById(R.id.landing_txt_hint); 107 | 108 | 109 | iconView.setImageDrawable(icon); 110 | titleView.setText(title); 111 | hintView.setText(hint); 112 | 113 | container.addView(itemView); 114 | 115 | return itemView; 116 | } 117 | 118 | @Override 119 | public void destroyItem(ViewGroup container, int position, Object object) { 120 | container.removeView((RelativeLayout) object); 121 | 122 | } 123 | } 124 | 125 | public class CustomPageTransformer implements ViewPager.PageTransformer { 126 | 127 | 128 | public void transformPage(View view, float position) { 129 | int pageWidth = view.getWidth(); 130 | 131 | View imageView = view.findViewById(R.id.landing_img_slide); 132 | View contentView = view.findViewById(R.id.landing_txt_hint); 133 | View txt_title = view.findViewById(R.id.landing_txt_title); 134 | 135 | if (position < -1) { // [-Infinity,-1) 136 | // This page is way off-screen to the left 137 | } else if (position <= 0) { // [-1,0] 138 | // This page is moving out to the left 139 | 140 | // Counteract the default swipe 141 | setTranslationX(view,pageWidth * -position); 142 | if (contentView != null) { 143 | // But swipe the contentView 144 | setTranslationX(contentView,pageWidth * position); 145 | setTranslationX(txt_title,pageWidth * position); 146 | 147 | setAlpha(contentView,1 + position); 148 | setAlpha(txt_title,1 + position); 149 | } 150 | 151 | if (imageView != null) { 152 | // Fade the image in 153 | setAlpha(imageView,1 + position); 154 | } 155 | 156 | } else if (position <= 1) { // (0,1] 157 | // This page is moving in from the right 158 | 159 | // Counteract the default swipe 160 | setTranslationX(view, pageWidth * -position); 161 | if (contentView != null) { 162 | // But swipe the contentView 163 | setTranslationX(contentView,pageWidth * position); 164 | setTranslationX(txt_title,pageWidth * position); 165 | 166 | setAlpha(contentView, 1 - position); 167 | setAlpha(txt_title, 1 - position); 168 | 169 | } 170 | if (imageView != null) { 171 | // Fade the image out 172 | setAlpha(imageView,1 - position); 173 | } 174 | 175 | } 176 | } 177 | } 178 | 179 | /** 180 | * Sets the alpha for the view. The alpha will be applied only if the running android device OS is greater than honeycomb. 181 | * @param view - view to which alpha to be applied. 182 | * @param alpha - alpha value. 183 | */ 184 | private void setAlpha(View view, float alpha) { 185 | 186 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && ! isSliderAnimation) { 187 | view.setAlpha(alpha); 188 | } 189 | } 190 | 191 | /** 192 | * Sets the translationX for the view. The translation value will be applied only if the running android device OS is greater than honeycomb. 193 | * @param view - view to which alpha to be applied. 194 | * @param translationX - translationX value. 195 | */ 196 | private void setTranslationX(View view, float translationX) { 197 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && ! isSliderAnimation) { 198 | view.setTranslationX(translationX); 199 | } 200 | } 201 | 202 | public void onSaveInstanceState(Bundle outstate) { 203 | 204 | if(outstate != null) { 205 | outstate.putBoolean(SAVING_STATE_SLIDER_ANIMATION,isSliderAnimation); 206 | } 207 | 208 | super.onSaveInstanceState(outstate); 209 | } 210 | 211 | public void onRestoreInstanceState(Bundle inState) { 212 | 213 | if(inState != null) { 214 | isSliderAnimation = inState.getBoolean(SAVING_STATE_SLIDER_ANIMATION,false); 215 | } 216 | super.onRestoreInstanceState(inState); 217 | 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/calendar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharish/AppIntroAnimation/8c96cbf6e79e794d5e6ce1f7c7b4c6ac6d3bfc42/app/src/main/res/drawable/calendar.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharish/AppIntroAnimation/8c96cbf6e79e794d5e6ce1f7c7b4c6ac6d3bfc42/app/src/main/res/drawable/email.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/round_rectangle_semi_transparent.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shopping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharish/AppIntroAnimation/8c96cbf6e79e794d5e6ce1f7c7b4c6ac6d3bfc42/app/src/main/res/drawable/shopping.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/socialnetwork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharish/AppIntroAnimation/8c96cbf6e79e794d5e6ce1f7c7b4c6ac6d3bfc42/app/src/main/res/drawable/socialnetwork.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/viewpager_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 14 | 15 | 21 | 22 | 32 | 33 | 43 | 44 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharish/AppIntroAnimation/8c96cbf6e79e794d5e6ce1f7c7b4c6ac6d3bfc42/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharish/AppIntroAnimation/8c96cbf6e79e794d5e6ce1f7c7b4c6ac6d3bfc42/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharish/AppIntroAnimation/8c96cbf6e79e794d5e6ce1f7c7b4c6ac6d3bfc42/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharish/AppIntroAnimation/8c96cbf6e79e794d5e6ce1f7c7b4c6ac6d3bfc42/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-hdpi/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10sp 7 | 16sp 8 | 18sp 9 | 20sp 10 | 12sp 11 | 10sp 12 | 14sp 13 | 180dp 14 | 5dp 15 | 10dp 16 | 15dp 17 | 20dp 18 | 25dp 19 | 30dp 20 | 35dp 21 | 40dp 22 | 50dp 23 | 60dp 24 | 48.65dip 25 | 70dp 26 | 80dp 27 | 90dp 28 | 101.25dip 29 | 30 | 31 | 32 | 200dp 33 | 4.5dp 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/values-large-mdpi/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 16sp 6 | 26sp 7 | 30sp 8 | 33sp 9 | 20sp 10 | 16sp 11 | 23sp 12 | 300dp 13 | 8dp 14 | 16dp 15 | 25dp 16 | 33dp 17 | 41dp 18 | 50dp 19 | 58dp 20 | 66.5dip 21 | 83dp 22 | 100dp 23 | 81dip 24 | 116.6dip 25 | 133.3dip 26 | 150dp 27 | 168.75dip 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/values-mdpi/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10sp 7 | 16sp 8 | 18sp 9 | 20sp 10 | 12sp 11 | 10sp 12 | 14sp 13 | 180dp 14 | 5dp 15 | 10dp 16 | 15dp 17 | 20dp 18 | 25dp 19 | 30dp 20 | 35dp 21 | 40dp 22 | 50dp 23 | 60dp 24 | 48.65dip 25 | 70dp 26 | 80dp 27 | 90dp 28 | 101.25dip 29 | 30 | 31 | 32 | 33 | 200dp 34 | 4.5dp 35 | 36 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | @color/light_green 6 | @color/light_purple 7 | @color/light_orange 8 | @color/light_cyan 9 | 10 | 11 | 12 | 13 | @drawable/email 14 | @drawable/calendar 15 | @drawable/shopping 16 | @drawable/socialnetwork 17 | 18 | 19 | 20 | 21 | 22 | @string/email 23 | @string/calender 24 | @string/shopping 25 | @string/social_network 26 | 27 | 28 | 29 | 30 | 31 | @string/email_hint 32 | @string/calender_hint 33 | @string/shopping_hint 34 | @string/social_network_hint 35 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/res/values/color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #3eb74e 5 | #8c61b3 6 | #ffb500 7 | #00BCD4 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 8dp 6 | 2dp 7 | 10dp 8 | 5dp 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | AppIntroAnimation 3 | 4 | Hello world! 5 | Settings 6 | 7 | EMAIL 8 | CALENDAR 9 | SHOPPING 10 | SOCIAL NETWORK 11 | 12 | 13 | A system for sending and receiving messages electronically over a computer network. 14 | Note all your special occasions in calendar and keep them in your finger tips 15 | Shop and get offers, promo codes and discounts on your future purchase. 16 | Stay connected with your friends, colleagues and family globally 17 | SKIP 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/vpi__attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /app/src/main/res/values/vpi__colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | #ff000000 19 | #fff3f3f3 20 | @color/vpi__background_holo_light 21 | @color/vpi__background_holo_dark 22 | #ff4c4c4c 23 | #ffb2b2b2 24 | @color/vpi__bright_foreground_holo_light 25 | @color/vpi__bright_foreground_holo_dark 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/values/vpi__defaults.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | true 19 | #FFFFFFFF 20 | #40FFFFFF 21 | 0 22 | 3dp 23 | false 24 | #40FFFFFF 25 | 1dp 26 | 27 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.2.3' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sharish/AppIntroAnimation/8c96cbf6e79e794d5e6ce1f7c7b4c6ac6d3bfc42/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Apr 10 15:27:10 PDT 2013 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | --------------------------------------------------------------------------------