{"id":14117507,"url":"https://github.com/janheinrichmerker/material-intro","last_synced_at":"2025-05-14T07:08:24.748Z","repository":{"id":74119163,"uuid":"52039640","full_name":"janheinrichmerker/material-intro","owner":"janheinrichmerker","description":"A simple material design app intro with cool animations and a fluent API.","archived":false,"fork":false,"pushed_at":"2025-03-31T09:04:37.000Z","size":24449,"stargazers_count":1732,"open_issues_count":57,"forks_count":303,"subscribers_count":47,"default_branch":"master","last_synced_at":"2025-05-11T09:52:13.048Z","etag":null,"topics":["android","android-library","animations","autoplay","java","jitpack","material","material-components","material-design","slides-featuring"],"latest_commit_sha":null,"homepage":"https://jitpack.io/#com.heinrichreimer/material-intro","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/janheinrichmerker.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"heinrichreimer","custom":null}},"created_at":"2016-02-18T21:20:47.000Z","updated_at":"2025-05-05T07:52:10.000Z","dependencies_parsed_at":"2024-01-14T11:19:15.907Z","dependency_job_id":"9e5d2983-7054-44fa-9a29-4232adcee90a","html_url":"https://github.com/janheinrichmerker/material-intro","commit_stats":null,"previous_names":["janheinrichmerker/material-intro","heinrichreimer/material-intro"],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janheinrichmerker%2Fmaterial-intro","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janheinrichmerker%2Fmaterial-intro/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janheinrichmerker%2Fmaterial-intro/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janheinrichmerker%2Fmaterial-intro/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/janheinrichmerker","download_url":"https://codeload.github.com/janheinrichmerker/material-intro/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254092663,"owners_count":22013290,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","android-library","animations","autoplay","java","jitpack","material","material-components","material-design","slides-featuring"],"created_at":"2024-08-14T18:01:44.722Z","updated_at":"2025-05-14T07:08:24.714Z","avatar_url":"https://github.com/janheinrichmerker.png","language":"Java","funding_links":["https://github.com/sponsors/heinrichreimer"],"categories":["Java"],"sub_categories":[],"readme":"![Icon](http://i.imgur.com/biiZxND.png)\n\n# material-intro\n\n[![Build Status](https://img.shields.io/github/actions/workflow/status/janheinrichmerker/material-intro/ci.yml?branch=master\u0026style=flat-square)](https://github.com/janheinrichmerker/material-intro/actions/workflows/ci.yml)\n[![JitPack](https://img.shields.io/jitpack/v/github/janheinrichmerker/material-intro?style=flat-square)](https://jitpack.io/#com.janheinrichmerker/material-intro)\n[![Downloads](https://img.shields.io/jitpack/dm/github/janheinrichmerker/material-intro?style=flat-square)](https://jitpack.io/#com.janheinrichmerker/material-intro)\n[![License](https://img.shields.io/github/license/janheinrichmerker/material-intro?style=flat-square)](https://github.com/janheinrichmerker/material-intro/blob/master/LICENSE.txt)\n[![GitHub issues](https://img.shields.io/github/issues/janheinrichmerker/material-intro?style=flat-square)](https://github.com/janheinrichmerker/material-intro/issues)\n\nA simple material design app intro with cool animations and a fluent API.\n\n_Very inspired by Google's app intros._\n\n### Demo:\n\nA demo app is available on Google Play:\n\n\u003ca href=\"https://play.google.com/store/apps/details?id=com.heinrichreimersoftware.materialintro.demo\"\u003e\n\t\u003cimg alt=\"Get it on Google Play\" src=\"https://play.google.com/intl/en_us/badges/images/generic/en-play-badge.png\" height=\"60\" /\u003e\n\u003c/a\u003e\n\n### Screenshots:\n\n| Simple slide | Custom slide | Fade effect | Permission request |\n|:-:|:-:|:-:|:-:|\n| ![Simple slide](http://i.imgur.com/cLWW5qm.png) | ![Custom slide](http://i.imgur.com/hmhnzUb.png) | ![Fade effect](http://i.imgur.com/7ujB0S4.png) | ![Permission request](http://i.imgur.com/EDNLGy8.png) |\n| [`SimpleSlide.java`](https://github.com/janheinrichmerker/material-intro/blob/master/library/src/main/java/com/heinrichreimersoftware/materialintro/slide/SimpleSlide.java) | [`FragmentSlide.java`](https://github.com/janheinrichmerker/material-intro/blob/master/library/src/main/java/com/heinrichreimersoftware/materialintro/slide/FragmentSlide.java) | [`IntroActivity.java`](https://github.com/janheinrichmerker/material-intro/blob/master/library/src/main/java/com/heinrichreimersoftware/materialintro/app/IntroActivity.java) | [`SimpleSlide.java`](https://github.com/janheinrichmerker/material-intro/blob/master/library/src/main/java/com/heinrichreimersoftware/materialintro/slide/SimpleSlide.java) |\n\n### Features:\n\n* Material design ([check the docs](https://material.io/guidelines/growth-communications/onboarding.html#onboarding-top-user-benefits))\n* Easy customization\n* Predefined slide layouts\n* Custom slides\n* Autoplay\n* Parallax slides\n* Fluent API\n\n## Table of Contents\n\n1. [Setup](#setup)\n    1. [Gradle Dependency](#gradle-dependency)\n    1. [Requirements](#requirements)\n1. [Slides](#slides)\n    1. [Standard slide](#standard-slide-simpleslide)\n    1. [Fragment slide](#fragment-slide-fragmentslide)\n    1. [Custom slide](#custom-slide-slide)\n1. [Customization](#customization)\n    1. [Back button](#left-back-button)\n    1. [Next button](#right-next-button)\n    1. [CTA button](#cta-button)\n    1. [Fullscreen](#fullscreen)\n    1. [Scroll duration](#scroll-duration)\n1. [Navigation](#navigation)\n    1. [Block navigation](#block-navigation)\n    1. [Navigate to slides](#navigate-to-slides)\n    1. [Autoplay](#autoplay)\n    1. [Callbacks](#callbacks)\n1. [Tips \u0026 Tricks](#tips--tricks)\n    1. [Activity result](#activity-result)\n    1. [Parallax slides](#parallax-slides)\n    1. [Splash screens](#splash-screens)\n1. [Apps using this library](#apps-using-this-library)\n1. [Changes](#changes)\n1. [Open-source libraries](#open-source-libraries)\n1. [License](#license)\n\n## Setup:\n\n### Gradle Dependency:\n\n*material-intro* is available on [**jitpack.io**](https://jitpack.io/#com.heinrichreimersoftware/material-intro).\n\nAdd this in your root `build.gradle` file (**not** your module `build.gradle` file):\n```gradle\nallprojects {\n    repositories {\n        maven { url 'https://jitpack.io' }\n    }\n}\n```\n\nAdd this in your module `build.gradle` file: \n\n![](https://jitpack.io/v/com.heinrichreimersoftware/material-intro.svg)\n\n```gradle\ndependencies {\n    implementation 'com.heinrichreimersoftware:material-intro:x.y.z'\n}\n```\n\n### Requirements:\nThe activity must extend [`IntroActivity`](https://github.com/janheinrichmerker/material-intro/blob/master/library/src/main/java/com/heinrichreimersoftware/materialintro/app/IntroActivity.java) and have a theme extending `@style/Theme.Intro`:\n```java\npublic class MainIntroActivity extends IntroActivity {\n    @Override \n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n\t    // Add slides, edit configuration...\n    }\n}\n```\n\n```xml\n\u003cmanifest ...\u003e\n    \u003capplication ...\u003e\n        \u003cactivity \n            android:name=\".MainIntroActivity\"\n            android:theme=\"@style/Theme.Intro\"/\u003e\n    \u003c/application\u003e\n\u003c/manifest\u003e\n```\n\n_(Unless mentioned otherwise, all of the following method calls should go in the Activity's `onCreate()`.)_\n\n## Slides:\n\n_material-intro_ has fluent style builders for both a simple text/image slide, as seen in Google's apps, and for slides featuring a custom `Fragment` or layout resource.\n\nFeel free to submit an [issue](https://github.com/janheinrichmerker/material-intro/issues/new) or [pull request](https://github.com/janheinrichmerker/material-intro/compare) if you think any slide types are missing.\n\n### Standard slide ([`SimpleSlide`](https://github.com/janheinrichmerker/material-intro/blob/master/library/src/main/java/com/heinrichreimersoftware/materialintro/slide/SimpleSlide.java)):\n\nStandard slide featuring a title, short description and image like Google's intros.\n\n```java\naddSlide(new SimpleSlide.Builder()\n        .title(R.string.title_1)\n        .description(R.string.description_1)\n        .image(R.drawable.image_1)\n        .background(R.color.background_1)\n        .backgroundDark(R.color.background_dark_1)\n        .scrollable(false)\n        .permission(Manifest.permission.CAMERA)\n        .build());\n```\n\n### Fragment slide ([`FragmentSlide`](https://github.com/janheinrichmerker/material-intro/blob/master/library/src/main/java/com/heinrichreimersoftware/materialintro/slide/FragmentSlide.java)):\n\nCustom slide containing a `Fragment` or a layout resource.\n\n```java\naddSlide(new FragmentSlide.Builder()\n        .background(R.color.background_2)\n        .backgroundDark(R.color.background_dark_2)\n        .fragment(R.layout.fragment_2, R.style.FragmentTheme)\n        .build());\n```\n\n(When using `FragmentSlide` with a `Fragment`, you should extend [`SlideFragment`](https://github.com/janheinrichmerker/material-intro/blob/master/library/src/main/java/com/heinrichreimersoftware/materialintro/app/SlideFragment.java) to proxy navigation calls to the intro activity.)\n\n### Custom slide ([`Slide`](https://github.com/janheinrichmerker/material-intro/blob/master/library/src/main/java/com/heinrichreimersoftware/materialintro/slide/Slide.java)):\n\nBase slide. If you want to modify what's shown in your slide this is the way to go.\n\n## Customization:\n\n### Left (\"back\") button:\n\nControl left button behavior or hide/show it.\n\n```java\n/* Show/hide button */\nsetButtonBackVisible(true);\n/* Use skip button behavior */\nsetButtonBackFunction(BUTTON_BACK_FUNCTION_SKIP);\n/* Use back button behavior */\nsetButtonBackFunction(BUTTON_BACK_FUNCTION_BACK);\n```\n\n### Right (\"next\") button:\n\nControl right button behavior or hide/show it.\n\n```java\n/* Show/hide button */\nsetButtonNextVisible(true);\n/* Use next and finish button behavior */\nsetButtonNextFunction(BUTTON_NEXT_FUNCTION_NEXT_FINISH);\n/* Use next button behavior */\nsetButtonNextFunction(BUTTON_NEXT_FUNCTION_NEXT);\n```\n\n### CTA button:\n\nChange the appearance of the \"call to action\" button:\n\n```java\n/* Show/hide button */\nsetButtonCtaVisible(getStartedEnabled);\n/* Tint button text */\nsetButtonCtaTintMode(BUTTON_CTA_TINT_MODE_TEXT);\n/* Tint button background */\nsetButtonCtaTintMode(BUTTON_CTA_TINT_MODE_BACKGROUND);\n/* Set custom CTA label */\nsetButtonCtaLabel(R.string.start)\n/**/\nsetButtonCtaClickListener(new View.OnClickListener() {\n\n});\n```\n\n### Fullscreen:\n\nDisplay the intro activity at fullscreen. This hides the status bar.\n\n```java\npublic class MainIntroActivity extends IntroActivity{\n    @Override protected void onCreate(Bundle savedInstanceState){\n        setFullscreen(true);\n        super.onCreate(savedInstanceState);\n\t...\n    }\n}\n```\n\nMake sure to call `setFullscreen()` **before** calling `super.onCreate()`\n\n### Scroll duration:\n\nAdjust how long a single slide scroll takes.\n\n```java\nsetPageScrollDuration(500);\n```\n\n(The page scroll duration is dynamically adapted when scrolling more than one position to reflect [**dynamic durations**](https://material.io/guidelines/motion/duration-easing.html#duration-easing-dynamic-durations) from the [Material design docs](https://material.io/guidelines/motion/duration-easing.html#duration-easing-dynamic-durations).\nThe exact formula for calculating the scroll duration is `duration * (distance + sqrt(distance)) / 2`.)\n\n## Navigation:\n\n### Block navigation:\n\nThere are three ways to block navigation for a slide:\n\n1. In a [`SlideFragment`](https://github.com/janheinrichmerker/material-intro/blob/master/library/src/main/java/com/heinrichreimersoftware/materialintro/app/SlideFragment.java) (using a [`FragmentSlide`](https://github.com/janheinrichmerker/material-intro/blob/master/library/src/main/java/com/heinrichreimersoftware/materialintro/slide/FragmentSlide.java)) by overriding `canGoForward()`/`canGoBackward()` methods.\n2. For a `SimpleSlide` by setting `SimpleSlide.Builder#canGoForward(boolean)`/`SimpleSlide.Builder#canGoBackward(boolean)`.\n    (If at least one permission is set to the `SimpleSlide`, navigation is automatically blocked until every permission is granted.)\n3. From your `IntroActivity` by setting a [`NavigationPolicy`](https://github.com/janheinrichmerker/material-intro/blob/master/library/src/main/java/com/heinrichreimersoftware/materialintro/app/NavigationPolicy.java):\n    ```java\n    setNavigationPolicy(new NavigationPolicy() {\n        @Override public boolean canGoForward(int position) {\n            return true;\n        }\n\n        @Override public boolean canGoBackward(int position) {\n            return false;\n        }\n    });\n    ```\n\n### Navigate to slides\n\nNavigate through the intro manually using one of the following methods e.g. from a listeners callback.\nEach of them will respect [blocked navigation](#block-navigation) settings.\n\n```java\n/* Scroll to any position */\ngoToSlide(5);\n\n/* Scroll to the next slide in the intro */\nnextSlide();\n\n/* Scroll to the previous slide in the intro */\npreviousSlide();\n\n/* Scroll to the last slide of the intro */\ngoToLastSlide();\n\n/* Scroll to the first slide of the intro */\ngoToFirstSlide();\n```\n\n### Autoplay\n\nAutomatically scroll through the intro until user interacts with the intro.\n\n```java\n/* Start an auto slideshow with 2500ms delay between scrolls and infinite repeats */\nautoplay(2500, INFINITE);\n/* Start an auto slideshow with default configuration  */\nautoplay();\n/* Cancel the slideshow */\ncancelAutoplay()\n```\n\n### Callbacks\n\nIf any of the above returns `false` when a user tries to navigate to a slide, a `OnNavigationBlockedListener` callback is fired that you can use to display a message. Additionally you can add plain-old `ViewPager.OnPageChangeListener`s to listen for page scrolls:\n```java\naddOnNavigationBlockedListener(new OnNavigationBlockedListener() {\n    @Override public void onNavigationBlocked(int position, int direction) { ... }\n});\n\naddOnPageChangeListener(new ViewPager.OnPageChangeListener(){\n    @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { ... }\n    @Override public void onPageSelected(int position) { ... }\n    @Override public void onPageScrollStateChanged(int state) { ... }\n});\n```\n\n## Tips \u0026 Tricks:\n\n### Activity result:\n\nYou can check if the user canceled the intro (by pressing back) or finished it including all slides.\nJust call up the activity using `startActivityForResult(intent, REQUEST_CODE_INTRO);` and then listen for the result:\n```java\n@Override\nprotected void onActivityResult(int requestCode, int resultCode, Intent data) {\n    super.onActivityResult(requestCode, resultCode, data);\n    if (requestCode == REQUEST_CODE_INTRO) {\n        if (resultCode == RESULT_OK) {\n            // Finished the intro\n        } else {\n            // Cancelled the intro. You can then e.g. finish this activity too.\n            finish();\n\t}\n    }\n}\n```\n\n### Parallax slides:\n\nYou can easily achieve a nice looking parallax effect for any slide by using either [`ParallaxFrameLayout.java`](https://github.com/janheinrichmerker/material-intro/blob/master/library/src/main/java/com/heinrichreimersoftware/materialintro/view/parallax/ParallaxFrameLayout.java), [`ParallaxLinearLayout.java`](https://github.com/janheinrichmerker/material-intro/blob/master/library/src/main/java/com/heinrichreimersoftware/materialintro/view/parallax/ParallaxLinearLayout.java) or [`ParallaxRelativeLayout.java`](https://github.com/janheinrichmerker/material-intro/blob/master/library/src/main/java/com/heinrichreimersoftware/materialintro/view/parallax/ParallaxRelativeLayout.java) and defining `layout_parallaxFactor` for its direct childrens.\nA higher factor means a stronger parallax effect, `0` means no parallax effect at all.\n\n```xml\n\u003ccom.heinrichreimersoftware.materialintro.view.parallax.ParallaxLinearLayout\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    ... \u003e\n\n    \u003cTextView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        app:layout_parallaxFactor=\"0\"\n        ... /\u003e\n\n    \u003cImageView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        app:layout_parallaxFactor=\"1.25\"\n        ... /\u003e\n\n\u003c/com.heinrichreimersoftware.materialintro.view.parallax.ParallaxLinearLayout\u003e\n```\n\nCheck the [\"Canteen\"-demo](https://github.com/janheinrichmerker/material-intro/blob/master/app/src/main/res/layout/slide_canteen.xml) for a layout example.\n\n### Splash screens:\n\nIf you want to show the intro only at the first app start you can use `onActivityResult()` to store a shared preference when the user finished the intro.\n\nSee the demo app for a sample splash screen implementation:\n- **[SplashActivity.java](https://github.com/janheinrichmerker/material-intro/blob/master/app/src/main/java/com/heinrichreimersoftware/materialintro/demo/SplashActivity.java)**: A fake splash screen\n- **[SplashIntroActivity.java](https://github.com/janheinrichmerker/material-intro/blob/master/app/src/main/java/com/heinrichreimersoftware/materialintro/demo/SplashIntroActivity.java)**: The intro started from FinishActivity\n- **[FinishActivity.java](https://github.com/janheinrichmerker/material-intro/blob/master/app/src/main/java/com/heinrichreimersoftware/materialintro/demo/FinishActivity.java)**: The activity started after the splash screen\n\n## Apps using this library:\n\n- [**Simply Unroot**](https://play.google.com/store/apps/details?id=de.pinpong.simplyunroot) by @pinpong\n- [**Prodigal Music Player**](https://play.google.com/store/apps/details?id=bob.sun.prodigal) by @SpongeBobSun\n- [**Puff Password Utility**](https://play.google.com/store/apps/details?id=sun.bob.leela) by @SpongeBobSun\n- [**QualityGate**](https://play.google.com/store/apps/details?id=com.frontendart.qualitygate.android) by @FrontEndART\n- [**Monitor**](https://play.google.com/store/apps/details?id=com.danielstone.energyhive) by @daniel-stoneuk\n- [**Contact Lenses Time**](https://play.google.com/store/apps/details?id=com.brando.lenti) by @ste23droid\n- [**Antidote Danmark**](https://play.google.com/store/apps/details?id=dk.antidotedanmark) by @AntidoteDanmark\n- [**Speed Boost Lite**](https://play.google.com/store/apps/details?id=com.TMillerApps.SpeedBoostLite) by @tjmille2\n- [**Root Checker**](https://play.google.com/store/apps/details?id=com.joeykrim.rootcheck) by @joeykrim\n\n## Changes:\n\nSee the [releases section](https://github.com/janheinrichmerker/material-intro/releases) for changelogs.\n\n## Open-source libraries:\n\n*material-intro* uses the following open-source files:\n\n* [CheatSheet.java](https://gist.github.com/romannurik/3982005) by [@Roman Nurik](https://github.com/romannurik/) (Apache License 2.0)\n* [AnimUtils.java](https://github.com/nickbutcher/plaid/blob/master/app/src/main/java/io/plaidapp/util/AnimUtils.java) by [@Nick Butcher](https://github.com/nickbutcher/) (Apache License 2.0), _modified version_\n* [InkPageIndicator.java](https://github.com/nickbutcher/plaid/blob/master/app/src/main/java/io/plaidapp/ui/widget/InkPageIndicator.java) by [@Nick Butcher](https://github.com/nickbutcher/) (Apache License 2.0)\n\n## License:\n\n```\nMIT License\n\nCopyright (c) 2017 Jan Heinrich Reimer\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanheinrichmerker%2Fmaterial-intro","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjanheinrichmerker%2Fmaterial-intro","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanheinrichmerker%2Fmaterial-intro/lists"}