diff --git a/.travis.yml b/.travis.yml
index 1b500a5..e1e5d4a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,20 +3,38 @@ language: android
jdk:
- oraclejdk8
+env:
+ global:
+ - ANDROID_TARGET=android-19
+ - ANDROID_ABI=armeabi-v7a
+
android:
components:
- tools
- tools
- platform-tools
- - build-tools-24.0.3
- - android-24
+ - build-tools-26.0.
+ - android-19
+ - android-26
- extra-google-google_play_services
- extra-google-m2repository
- extra-android-m2repository
-
-licenses:
+ - sys-img-armeabi-v7a-android-19
+ licenses:
- '.+'
+branches:
+ except:
+ - gh-pages
+
+before_script:
+ # Create and start an emulator for instrumentation tests.
+ - echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI
+ - emulator -avd test -no-audio -no-window &
+ - android-wait-for-emulator
+ - adb shell setprop dalvik.vm.dexopt-flags v=n,o=v
+ - adb shell input keyevent 82
+
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
@@ -25,12 +43,20 @@ cache:
directories:
- $HOME/.m2
- $HOME/.gradle
+ - $HOME/.android/build-cache
before_install:
+ - chmod +x gradlew
- mkdir "$ANDROID_HOME/licenses" || true
- echo -e "\n8933bad161af4178b1185d1a37fbf41ea5269c55" > "$ANDROID_HOME/licenses/android-sdk-license"
- echo -e "\n84831b9409646a918e30573bab4c9c91346d8abd" > "$ANDROID_HOME/licenses/android-sdk-preview-license"
+script:
+ - ./gradlew build jacocoTestReport assembleAndroidTest connectedCheck
+
+after_success:
+ - bash <(curl -s https://codecov.io/bash)
+
notifications:
slack:
secure: qIOOj57yVyinyTs9SinZmp/aVN5Or/9LDg+l9SYMqVCaqM9zDk7s1/m/L7VNPdWCuWOzLf9g1+0ReBcwZ6vh+HWBQ4T1V4HQd09whhUGyW9kMj3BKE0gWpIJLYKuhM551auv3FVzTp3u27q4W0zgiXB8qHWatTQu9rcPumG+IJaZD1uHsbhrQq0RLD8n8hWjQAdkRKRtSo4UR55sTK35uGRZbMFcyJSiStBXRP43w2kTR1MxIst4r9NeOx/sjebBQ/XxabKJgqAHhue80O3Cy8s0u59NDHOMpqJOu00cdKbtmhePQsY0FUl5/689Xdc+bDs3OcwGWbokaFEjXLwA1De+CIz0NMjgdtyHIbEGWcYav8jujke4wYaAtQRPgKHtVL9EpIUX07jPznstRNV8T3H1qrf2S5xHW6elZ7nLOnYuDKsgETmEuDQLAg8ibYQTF4zNBYGFwvC3GOJCqCu+o40OwmFghyohmXxSmo8Cg019V/hOtmYThaFcyDQhN8QGkUSqHrjDNRxyyye2JHvU+bJlTshonZlPh2gM9NA9Tf/3fMEobtnA5XYurntj43UhdZ4HdsYjbrFhbOrXEBRx1mG8gcCFgexz/3E9wq7GN0fqm6LMB8radqUbP0hAd2cADlN9suCWWLVnufLAiS5iqo55M2e9u749p+e+ESCLXIo=
\ No newline at end of file
diff --git a/README.md b/README.md
index 05d7dc5..d36ae12 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ Material intro screen is inspired by [Material Intro] and developed with love fr
- [Easily add new slides][Intro Activity]
- [Custom slides][Custom Slide]
- [Parallax slides][Parallax Slide]
- - Easy extensible api
+ - Easy and extensible api
- Android TV support!
- Material design at it's best!!!
@@ -35,7 +35,7 @@ public class IntroActivity extends MaterialIntroActivity
```xml
+ android:theme="@style/Theme.MaterialIntro" />
```
### Step 4:
#### [Add slides:][Intro Activity]
@@ -50,15 +50,18 @@ public class IntroActivity extends MaterialIntroActivity
.possiblePermissions(new String[]{Manifest.permission.CALL_PHONE, Manifest.permission.READ_SMS})
.neededPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION})
.image(agency.tango.materialintroscreen.R.drawable.ic_next)
+ .grantPermissionMessage(R.string.txt_pls_grant_permission)
+ .grantPermissionError(R.string.txt_grant_permission_error)
.title("title 3")
.description("Description 3")
.build(),
- new MessageButtonBehaviour(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- showMessage("We provide solutions to make you love your work");
- }
- }, "Work with love"));
+ new MessageButtonBehaviour(new MessageButtonClickListener() {
+ @Override
+ public void onClick(Button messageButton) {
+ messageButton.setText("Click me once again!");
+ showMessage("We provide solutions to make you love your work");
+ }
+ }, "Work with love"));
}
```
#### Explanation of SlideFragment usage:
@@ -71,6 +74,7 @@ public class IntroActivity extends MaterialIntroActivity
- ```setSkipButtonVisible()``` ⇾ show skip button instead of back button on the left bottom of screen
- ```hideBackButton()``` ⇾ hides any button on the left bottom of screen
- ```enableLastSlideAlphaExitTransition()``` ⇾ set if the last slide should disapear with alpha hiding effect
+ - ```onLastSlidePassed``` ⇾ Override in order to perform some action after passing last slide
#### Customizing view animations:
@@ -92,25 +96,29 @@ getBackButtonTranslationWrapper()
- ```getSkipButtonTranslationWrapper()```
## Custom slides
-#### Of course you are able to implement completely custom slides. You only need to extend SlideFragment and override following functions:
+#### Of course you are able to implement completely custom slides. You only need to extend SlideFragmentBase and override all needed by you functions.
- ```backgroundColor()```
- ```buttonsColor()```
- ```canMoveFurther()``` (only if you want to stop user from being able to move further before he will do some action)
- ```cantMoveFurtherErrorMessage()``` (as above)
-
+ - ```neededPermissions()```
+ - ```possiblePermissions()```
+ - ```grantPermissionStringRes()```
+ - ```grantPermissionErrorStringRes()```
+
#### If you want to use parallax in a fragment please use one of the below views:
- [```ParallaxFrameLayout```][ParallaxFrame]
- [```ParallaxLinearLayout```][ParallaxLinear]
- [```ParallaxRelativeLayout```][ParallaxRelative]
-#### And set there the [app:layout_parallaxFactor][ParallaxFactor] attribute:
+#### And set there the [app:mis_layout_parallaxFactor][ParallaxFactor] attribute:
```xml
+ app:mis_layout_parallaxFactor="0.6"/>
```
All features which are not available in simple Slide Fragment are shown here: [Custom Slide]
diff --git a/app/build.gradle b/app/build.gradle
index be9973a..c1b3d16 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,14 +1,15 @@
apply plugin: 'com.android.application'
+//apply from: '../jacoco-android.gradle'
apply from: "$rootDir/versions.gradle"
android {
- compileSdkVersion 25
- buildToolsVersion "25.0.0"
+ compileSdkVersion project.compileSdkVersion
+ buildToolsVersion project.buildToolsVersion
defaultConfig {
applicationId "agency.tango.materialintro"
- minSdkVersion 15
- targetSdkVersion 25
+ minSdkVersion project.minSdkVersion
+ targetSdkVersion project.targetSdkVersion
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 40ed932..8b8637d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,16 +1,16 @@
+ package="agency.tango.materialintro">
-
-
-
-
-
+
+
+
+
+
@@ -18,16 +18,16 @@
android:name=".SplashActivity"
android:theme="@style/SplashScreen">
-
-
+
+
-
+
+ android:theme="@style/Theme.MaterialIntro"/>
diff --git a/app/src/main/java/agency/tango/materialintro/CustomSlide.java b/app/src/main/java/agency/tango/materialintro/CustomSlide.java
index 4214cf9..ad25be2 100644
--- a/app/src/main/java/agency/tango/materialintro/CustomSlide.java
+++ b/app/src/main/java/agency/tango/materialintro/CustomSlide.java
@@ -7,29 +7,21 @@
import android.view.ViewGroup;
import android.widget.CheckBox;
-import agency.tango.materialintroscreen.SlideFragment;
+import agency.tango.materialintroscreen.fragments.SlideFragmentBase;
+
+public class CustomSlide extends SlideFragmentBase {
-public class CustomSlide extends SlideFragment {
private CheckBox checkBox;
@Nullable
@Override
- public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_custom_slide, container, false);
checkBox = (CheckBox) view.findViewById(R.id.checkBox);
return view;
}
- @Override
- public int backgroundColor() {
- return R.color.custom_slide_background;
- }
-
- @Override
- public int buttonsColor() {
- return R.color.custom_slide_buttons;
- }
-
@Override
public boolean canMoveFurther() {
return checkBox.isChecked();
diff --git a/app/src/main/java/agency/tango/materialintro/IntroActivity.java b/app/src/main/java/agency/tango/materialintro/IntroActivity.java
index 461a4cf..047d65a 100644
--- a/app/src/main/java/agency/tango/materialintro/IntroActivity.java
+++ b/app/src/main/java/agency/tango/materialintro/IntroActivity.java
@@ -5,23 +5,28 @@
import android.support.annotation.FloatRange;
import android.support.annotation.Nullable;
import android.view.View;
+import android.widget.Button;
import android.widget.Toast;
import agency.tango.materialintroscreen.MaterialIntroActivity;
-import agency.tango.materialintroscreen.MessageButtonBehaviour;
-import agency.tango.materialintroscreen.SlideFragmentBuilder;
+import agency.tango.materialintroscreen.behaviours.MessageButtonBehaviour;
import agency.tango.materialintroscreen.animations.IViewTranslation;
+import agency.tango.materialintroscreen.fragments.SlideFragmentBuilder;
+import agency.tango.materialintroscreen.listeners.click.MessageButtonClickListener;
public class IntroActivity extends MaterialIntroActivity {
+
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
enableLastSlideAlphaExitTransition(true);
+ setSkipButtonVisible();
getBackButtonTranslationWrapper()
.setEnterTranslation(new IViewTranslation() {
@Override
- public void translate(View view, @FloatRange(from = 0, to = 1.0) float percentage) {
+ public void translate(View view,
+ @FloatRange(from = 0, to = 1.0) float percentage) {
view.setAlpha(percentage);
}
});
@@ -33,13 +38,23 @@ public void translate(View view, @FloatRange(from = 0, to = 1.0) float percentag
.title("Organize your time with us")
.description("Would you try?")
.build(),
- new MessageButtonBehaviour(new View.OnClickListener() {
+ new MessageButtonBehaviour(new MessageButtonClickListener() {
@Override
- public void onClick(View v) {
+ public void onClick(Button messageButton) {
+ messageButton.setText("Click me once again!");
showMessage("We provide solutions to make you love your work");
}
}, "Work with love"));
+ addSlide(new SlideFragmentBuilder()
+ .backgroundColor(R.color.first_slide_background)
+ .buttonsColor(R.color.first_slide_buttons)
+ .image(R.drawable.img_office)
+ .title("Organize your time with us")
+ .description("Would you try?")
+ .neededPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE})
+ .build());
+
addSlide(new SlideFragmentBuilder()
.backgroundColor(R.color.second_slide_background)
.buttonsColor(R.color.second_slide_buttons)
@@ -52,15 +67,20 @@ public void onClick(View v) {
addSlide(new SlideFragmentBuilder()
.backgroundColor(R.color.third_slide_background)
.buttonsColor(R.color.third_slide_buttons)
- .possiblePermissions(new String[]{Manifest.permission.CALL_PHONE, Manifest.permission.READ_SMS})
- .neededPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION})
+ .possiblePermissions(
+ new String[]{Manifest.permission.CALL_PHONE, Manifest.permission.READ_SMS})
+ .neededPermissions(new String[]{Manifest.permission.CAMERA,
+ Manifest.permission.ACCESS_FINE_LOCATION,
+ Manifest.permission.ACCESS_COARSE_LOCATION})
.image(R.drawable.img_equipment)
+ .grantPermissionMessage(R.string.error_message)
+ .grantPermissionError(R.string.error_message)
.title("We provide best tools")
.description("ever")
.build(),
- new MessageButtonBehaviour(new View.OnClickListener() {
+ new MessageButtonBehaviour(new MessageButtonClickListener() {
@Override
- public void onClick(View v) {
+ public void onClick(Button messageButton) {
showMessage("Try us!");
}
}, "Tools"));
@@ -71,11 +91,13 @@ public void onClick(View v) {
.title("That's it")
.description("Would you join us?")
.build());
+
+
+
}
@Override
- public void onFinish() {
- super.onFinish();
+ public void onLastSlidePassed() {
Toast.makeText(this, "Try this library in your project! :)", Toast.LENGTH_SHORT).show();
}
}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index c134d92..8fc4954 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -11,7 +11,7 @@
android:layout_gravity="center_horizontal|bottom"
android:layout_margin="16dp"
android:text="@string/launch_intro_activity"
- android:theme="@style/ColoredButton" />
+ android:theme="@style/MaterialButton" />
+ app:mis_layout_parallaxFactor="0.4" />
diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml
index c8e30c1..4a7d424 100644
--- a/app/src/main/res/values-v21/styles.xml
+++ b/app/src/main/res/values-v21/styles.xml
@@ -1,7 +1,7 @@
-
-
diff --git a/build.gradle b/build.gradle
index 6ab2dc7..9ee47e7 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,10 +3,13 @@
buildscript {
repositories {
jcenter()
+ maven { url 'https://maven.google.com' }
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.2.2'
- classpath 'com.novoda:bintray-release:0.3.4'
+ classpath 'com.android.tools.build:gradle:3.0.1'
+// classpath 'com.novoda:bintray-release:0.3.4'
+// classpath 'com.dicedmelon.gradle:jacoco-android:0.1.1'
+// classpath 'com.palantir:jacoco-coverage:0.4.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
@@ -15,6 +18,7 @@ buildscript {
allprojects {
repositories {
jcenter()
+ maven { url 'https://maven.google.com' }
}
tasks.withType(Javadoc) {
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 04e285f..556bfea 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Mon Dec 28 10:00:20 PST 2015
+#Mon Apr 03 12:02:18 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
diff --git a/jacoco-android.gradle b/jacoco-android.gradle
new file mode 100644
index 0000000..883d587
--- /dev/null
+++ b/jacoco-android.gradle
@@ -0,0 +1,15 @@
+apply plugin: 'jacoco-android'
+
+jacoco {
+ toolVersion = "0.7.7.201606060606"
+}
+
+android {
+ testOptions {
+ unitTests.all {
+ jacoco {
+ includeNoLocationClasses = true
+ }
+ }
+ }
+}
diff --git a/material-intro-screen/build.gradle b/material-intro-screen/build.gradle
index 160a4ba..14220b0 100644
--- a/material-intro-screen/build.gradle
+++ b/material-intro-screen/build.gradle
@@ -1,14 +1,16 @@
apply plugin: 'com.android.library'
-apply plugin: 'com.novoda.bintray-release'
+//apply plugin: 'com.novoda.bintray-release'
+//apply from: '../jacoco-android.gradle'
apply from: "$rootDir/versions.gradle"
android {
- compileSdkVersion 25
- buildToolsVersion "25.0.0"
+ compileSdkVersion project.compileSdkVersion
+ buildToolsVersion project.buildToolsVersion
+ resourcePrefix 'mis_'
defaultConfig {
- minSdkVersion 15
- targetSdkVersion 25
+ minSdkVersion project.minSdkVersion
+ targetSdkVersion project.targetSdkVersion
versionCode 1
versionName "1.0"
@@ -53,14 +55,15 @@ android {
})
compile "com.android.support:appcompat-v7:${project.androidSupport}"
compile "com.android.support:design:${project.androidSupport}"
+ compile "com.android.support:percent:${project.androidSupport}"
}
- publish {
- userOrg = 'tangoagency'
- groupId = 'agency.tango.android'
- artifactId = 'material-intro-screen'
- publishVersion = '0.0.5'
- desc = ''
- website = 'https://github.com/TangoAgency/material-intro-screen'
- }
+// publish {
+// userOrg = 'tangoagency'
+// groupId = 'agency.tango.android'
+// artifactId = 'material-intro-screen'
+// publishVersion = '0.0.5'
+// desc = ''
+// website = 'https://github.com/TangoAgency/material-intro-screen'
+// }
}
\ No newline at end of file
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/ISlideErrorHandler.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/ISlideErrorHandler.java
new file mode 100644
index 0000000..43e45cc
--- /dev/null
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/ISlideErrorHandler.java
@@ -0,0 +1,5 @@
+package agency.tango.materialintroscreen;
+
+public interface ISlideErrorHandler {
+ void handleError();
+}
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/MaterialIntroActivity.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/MaterialIntroActivity.java
index 9a96040..dd3fb3c 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/MaterialIntroActivity.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/MaterialIntroActivity.java
@@ -4,6 +4,8 @@
import android.content.res.ColorStateList;
import android.os.Build;
import android.os.Bundle;
+import android.support.annotation.CallSuper;
+import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@@ -28,20 +30,22 @@
import agency.tango.materialintroscreen.animations.wrappers.PageIndicatorTranslationWrapper;
import agency.tango.materialintroscreen.animations.wrappers.SkipButtonTranslationWrapper;
import agency.tango.materialintroscreen.animations.wrappers.ViewPagerTranslationWrapper;
+import agency.tango.materialintroscreen.behaviours.MessageButtonBehaviour;
+import agency.tango.materialintroscreen.fragments.SlideFragmentBase;
import agency.tango.materialintroscreen.listeners.IFinishListener;
import agency.tango.materialintroscreen.listeners.IPageScrolledListener;
import agency.tango.materialintroscreen.listeners.IPageSelectedListener;
import agency.tango.materialintroscreen.listeners.MessageButtonBehaviourOnPageSelected;
import agency.tango.materialintroscreen.listeners.ViewBehavioursOnPageChangeListener;
-import agency.tango.materialintroscreen.listeners.clickListeners.PermissionNotGrantedClickListener;
-import agency.tango.materialintroscreen.listeners.scrollListeners.ParallaxScrollListener;
+import agency.tango.materialintroscreen.listeners.click.PermissionNotGrantedClickListener;
+import agency.tango.materialintroscreen.listeners.scroll.ParallaxScrollListener;
import agency.tango.materialintroscreen.widgets.InkPageIndicator;
import agency.tango.materialintroscreen.widgets.OverScrollViewPager;
import agency.tango.materialintroscreen.widgets.SwipeableViewPager;
-import static android.view.View.GONE;
-
+@SuppressWarnings("unused")
public abstract class MaterialIntroActivity extends AppCompatActivity {
+
private SwipeableViewPager viewPager;
private InkPageIndicator pageIndicator;
private SlidesAdapter adapter;
@@ -69,15 +73,17 @@ public abstract class MaterialIntroActivity extends AppCompatActivity {
private SparseArray messageButtonBehaviours = new SparseArray<>();
@Override
+ @CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Window window = getWindow();
- window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
+ WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
- setContentView(R.layout.activity_material_intro);
+ setContentView(R.layout.mis_activity_material_intro);
overScrollLayout = (OverScrollViewPager) findViewById(R.id.view_pager_slides);
viewPager = overScrollLayout.getOverScrollView();
@@ -98,7 +104,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
nextButtonTranslationWrapper = new NextButtonTranslationWrapper(nextButton);
initOnPageChangeListeners();
- permissionNotGrantedClickListener = new PermissionNotGrantedClickListener(this, nextButtonTranslationWrapper);
+ permissionNotGrantedClickListener = new PermissionNotGrantedClickListener(this,
+ nextButtonTranslationWrapper);
finishScreenClickListener = new FinishScreenClickListener();
setBackButtonVisible();
@@ -118,8 +125,9 @@ public void run() {
}
@Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- SlideFragment fragment = adapter.getItem(viewPager.getCurrentItem());
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
+ @NonNull int[] grantResults) {
+ SlideFragmentBase fragment = adapter.getItem(viewPager.getCurrentItem());
boolean hasPermissionToGrant = fragment.hasNeededPermissionsToGrant();
if (!hasPermissionToGrant) {
viewPager.setSwipingRightAllowed(true);
@@ -165,43 +173,42 @@ public boolean onKeyDown(int keyCode, KeyEvent event) {
}
public void showPermissionsNotGrantedError() {
- showError(getString(R.string.please_grant_permissions));
+ showError(getString(adapter.getItem(viewPager.getCurrentItem()).grantPermissionErrorStringRes()));
}
/**
- * Add SlideFragment to IntroScreen
+ * Add SlideFragmentBase to IntroScreen
*
- * @param slideFragment Fragment to add
+ * @param slideFragmentBase Fragment to add
*/
- @SuppressWarnings("unused")
- public void addSlide(SlideFragment slideFragment) {
- adapter.addItem(slideFragment);
+ public void addSlide(SlideFragmentBase slideFragmentBase) {
+ adapter.addItem(slideFragmentBase);
}
/**
* Add SlideFragment to IntroScreen
*
- * @param slideFragment Fragment to add
+ * @param slideFragmentBase Fragment to add
* @param messageButtonBehaviour Add behaviour for message button
*/
- @SuppressWarnings("unused")
- public void addSlide(SlideFragment slideFragment, MessageButtonBehaviour messageButtonBehaviour) {
- adapter.addItem(slideFragment);
+ public void addSlide(SlideFragmentBase slideFragmentBase,
+ MessageButtonBehaviour messageButtonBehaviour) {
+ adapter.addItem(slideFragmentBase);
messageButtonBehaviours.put(adapter.getLastItemPosition(), messageButtonBehaviour);
}
/**
* Set skip button instead of back button
*/
- @SuppressWarnings("unused")
public void setSkipButtonVisible() {
- backButton.setVisibility(GONE);
+ backButton.setVisibility(View.GONE);
skipButton.setVisibility(View.VISIBLE);
skipButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- for (int position = viewPager.getCurrentItem(); position < adapter.getCount(); position++) {
+ for (int position = viewPager.getCurrentItem(); position < adapter.getCount();
+ position++) {
if (!adapter.getItem(position).canMoveFurther()) {
viewPager.setCurrentItem(position, true);
showError(adapter.getItem(position).cantMoveFurtherErrorMessage());
@@ -217,7 +224,7 @@ public void onClick(View v) {
* Set back button visible
*/
public void setBackButtonVisible() {
- skipButton.setVisibility(GONE);
+ skipButton.setVisibility(View.GONE);
backButton.setVisibility(View.VISIBLE);
backButton.setOnClickListener(new View.OnClickListener() {
@@ -231,7 +238,6 @@ public void onClick(View v) {
/**
* Hides any back button
*/
- @SuppressWarnings("unused")
public void hideBackButton() {
backButton.setVisibility(View.INVISIBLE);
skipButton.setVisibility(View.GONE);
@@ -251,7 +257,6 @@ public ViewTranslationWrapper getNextButtonTranslationWrapper() {
*
* @return ViewTranslationWrapper
*/
- @SuppressWarnings("unused")
public ViewTranslationWrapper getBackButtonTranslationWrapper() {
return backButtonTranslationWrapper;
}
@@ -261,7 +266,6 @@ public ViewTranslationWrapper getBackButtonTranslationWrapper() {
*
* @return ViewTranslationWrapper
*/
- @SuppressWarnings("unused")
public ViewTranslationWrapper getPageIndicatorTranslationWrapper() {
return pageIndicatorTranslationWrapper;
}
@@ -271,7 +275,6 @@ public ViewTranslationWrapper getPageIndicatorTranslationWrapper() {
*
* @return ViewTranslationWrapper
*/
- @SuppressWarnings("unused")
public ViewTranslationWrapper getViewPagerTranslationWrapper() {
return viewPagerTranslationWrapper;
}
@@ -281,7 +284,6 @@ public ViewTranslationWrapper getViewPagerTranslationWrapper() {
*
* @return ViewTranslationWrapper
*/
- @SuppressWarnings("unused")
public ViewTranslationWrapper getSkipButtonTranslationWrapper() {
return skipButtonTranslationWrapper;
}
@@ -291,7 +293,6 @@ public ViewTranslationWrapper getSkipButtonTranslationWrapper() {
*
* @param enableAlphaExitTransition should enable alpha exit transition
*/
- @SuppressWarnings("unused")
public void enableLastSlideAlphaExitTransition(boolean enableAlphaExitTransition) {
viewPager.alphaExitTransitionEnabled(enableAlphaExitTransition);
}
@@ -306,13 +307,16 @@ public void showMessage(String message) {
}
/**
- * Override to execute this method on finish intro activity
+ * Override in order to perform some action after passing last slide
*/
- public void onFinish() {
+ public void onLastSlidePassed() {
+ // This method is intentionally empty, because we didn't want to make this method
+ // abstract as it would force user to implement this, even if he wouldn't like to.
}
private void initOnPageChangeListeners() {
- messageButtonBehaviourOnPageSelected = new MessageButtonBehaviourOnPageSelected(messageButton, adapter, messageButtonBehaviours);
+ messageButtonBehaviourOnPageSelected = new MessageButtonBehaviourOnPageSelected(
+ messageButton, adapter, messageButtonBehaviours);
backButtonTranslationWrapper = new BackButtonTranslationWrapper(backButton);
pageIndicatorTranslationWrapper = new PageIndicatorTranslationWrapper(pageIndicator);
@@ -321,11 +325,18 @@ private void initOnPageChangeListeners() {
overScrollLayout.registerFinishListener(new IFinishListener() {
@Override
- public void doOnFinish() {
+ public void onFinish() {
performFinish();
}
});
+ viewPager.registerSlideErrorHandler(new ISlideErrorHandler() {
+ @Override
+ public void handleError() {
+ errorOccurred(adapter.getItem(viewPager.getCurrentItem()));
+ }
+ });
+
viewPager.addOnPageChangeListener(new ViewBehavioursOnPageChangeListener(adapter)
.registerViewTranslationWrapper(nextButtonTranslationWrapper)
.registerViewTranslationWrapper(backButtonTranslationWrapper)
@@ -339,7 +350,8 @@ public void pageScrolled(final int position, float offset) {
viewPager.post(new Runnable() {
@Override
public void run() {
- if (adapter.getItem(position).hasNeededPermissionsToGrant() || !adapter.getItem(position).canMoveFurther()) {
+ if (adapter.getItem(position).hasNeededPermissionsToGrant()
+ || !adapter.getItem(position).canMoveFurther()) {
viewPager.setCurrentItem(position, true);
pageIndicator.clearJoiningFractions();
}
@@ -364,23 +376,23 @@ public void pageSelected(int position) {
}
@SuppressWarnings("PointlessBooleanExpression")
- private void nextButtonBehaviour(final int position, final SlideFragment fragment) {
+ private void nextButtonBehaviour(final int position, final SlideFragmentBase fragment) {
boolean hasPermissionToGrant = fragment.hasNeededPermissionsToGrant();
if (hasPermissionToGrant) {
- nextButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_next));
+ nextButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.mis_ic_next));
nextButton.setOnClickListener(permissionNotGrantedClickListener);
} else if (adapter.isLastSlide(position)) {
- nextButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_finish));
+ nextButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.mis_ic_finish));
nextButton.setOnClickListener(finishScreenClickListener);
} else {
- nextButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.ic_next));
+ nextButton.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.mis_ic_next));
nextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- if (fragment.canMoveFurther() == false) {
- errorOccurred(fragment);
- } else {
+ if (fragment.canMoveFurther()) {
viewPager.moveToNextPage();
+ } else {
+ errorOccurred(fragment);
}
}
});
@@ -388,7 +400,7 @@ public void onClick(View v) {
}
private void performFinish() {
- onFinish();
+ onLastSlidePassed();
finish();
}
@@ -400,52 +412,66 @@ private void moveBack() {
}
}
- private void errorOccurred(SlideFragment slideFragment) {
+ private void errorOccurred(SlideFragmentBase slideFragmentBase) {
nextButtonTranslationWrapper.error();
- showError(slideFragment.cantMoveFurtherErrorMessage());
+ showError(slideFragmentBase.cantMoveFurtherErrorMessage());
}
private void showError(String error) {
- Snackbar.make(coordinatorLayout, error, Snackbar.LENGTH_SHORT).setCallback(new Snackbar.Callback() {
- @Override
- public void onDismissed(Snackbar snackbar, int event) {
- navigationView.setTranslationY(0f);
- super.onDismissed(snackbar, event);
- }
- }).show();
+ Snackbar.make(coordinatorLayout, error, Snackbar.LENGTH_SHORT)
+ .setCallback(new Snackbar.Callback() {
+ @Override
+ public void onDismissed(Snackbar snackbar, int event) {
+ navigationView.setTranslationY(0f);
+ super.onDismissed(snackbar, event);
+ }
+ }).show();
}
- private Integer getBackgroundColor(int position, float positionOffset) {
- return (Integer) argbEvaluator.evaluate(positionOffset, color(adapter.getItem(position).backgroundColor()), color(adapter.getItem(position + 1).backgroundColor()));
+ private int getBackgroundEvaluatedColor(int position, float positionOffset) {
+ return (int) argbEvaluator.evaluate(positionOffset, getBackgroundColor(position),
+ getBackgroundColor(position + 1));
}
- private Integer getButtonsColor(int position, float positionOffset) {
- return (Integer) argbEvaluator.evaluate(positionOffset, color(adapter.getItem(position).buttonsColor()), color(adapter.getItem(position + 1).buttonsColor()));
+ private int getButtonsEvaluatedColor(int position, float positionOffset) {
+ return (int) argbEvaluator
+ .evaluate(positionOffset, getButtonsColor(position), getButtonsColor(position + 1));
}
- private int color(@ColorRes int color) {
+ @ColorInt
+ private int getColorFromRes(@ColorRes int color) {
return ContextCompat.getColor(this, color);
}
+ private int getButtonsColor(int position) {
+ return getColorFromRes(adapter.getItem(position).buttonsColor());
+ }
+
+ private int getBackgroundColor(int position) {
+ return getColorFromRes(adapter.getItem(position).backgroundColor());
+ }
+
private class ColorTransitionScrollListener implements IPageScrolledListener {
+
@Override
public void pageScrolled(int position, float offset) {
if (position < adapter.getCount() - 1) {
setViewsColor(position, offset);
- } else if (adapter.getCount() == 1) {
- viewPager.setBackgroundColor(adapter.getItem(position).backgroundColor());
- messageButton.setTextColor(adapter.getItem(position).backgroundColor());
+ } else if (adapter.getCount() == 1 || isOnLastSlide(position, offset)) {
+ viewPager.setBackgroundColor(getBackgroundColor(position));
+ messageButton.setTextColor(getBackgroundColor(position));
+ pageIndicator.setPageIndicatorColor(getButtonsColor(position));
- tintButtons(ColorStateList.valueOf(adapter.getItem(position).buttonsColor()));
+ tintButtons(ColorStateList.valueOf(getButtonsColor(position)));
}
}
private void setViewsColor(int position, float offset) {
- int backgroundColor = getBackgroundColor(position, offset);
+ int backgroundColor = getBackgroundEvaluatedColor(position, offset);
viewPager.setBackgroundColor(backgroundColor);
messageButton.setTextColor(backgroundColor);
- int buttonsColor = getButtonsColor(position, offset);
+ int buttonsColor = getButtonsEvaluatedColor(position, offset);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setStatusBarColor(buttonsColor);
}
@@ -454,6 +480,10 @@ private void setViewsColor(int position, float offset) {
tintButtons(ColorStateList.valueOf(buttonsColor));
}
+ private boolean isOnLastSlide(int position, float offset) {
+ return position == adapter.getLastItemPosition() && offset == 0;
+ }
+
private void tintButtons(ColorStateList color) {
ViewCompat.setBackgroundTintList(nextButton, color);
ViewCompat.setBackgroundTintList(backButton, color);
@@ -462,9 +492,10 @@ private void tintButtons(ColorStateList color) {
}
private class FinishScreenClickListener implements View.OnClickListener {
+
@Override
public void onClick(View v) {
- SlideFragment slideFragment = adapter.getItem(adapter.getLastItemPosition());
+ SlideFragmentBase slideFragment = adapter.getItem(adapter.getLastItemPosition());
if (!slideFragment.canMoveFurther()) {
errorOccurred(slideFragment);
} else {
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/SlideFragment.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/SlideFragment.java
deleted file mode 100644
index ba15ac6..0000000
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/SlideFragment.java
+++ /dev/null
@@ -1,169 +0,0 @@
-package agency.tango.materialintroscreen;
-
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v4.app.ActivityCompat;
-import android.support.v4.content.ContextCompat;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import agency.tango.materialintroscreen.parallax.ParallaxFragment;
-
-public class SlideFragment extends ParallaxFragment {
- private final static String BACKGROUND_COLOR = "background_color";
- private static final String BUTTONS_COLOR = "buttons_color";
- private static final String TITLE = "title";
- private static final String DESCRIPTION = "description";
- private static final String NEEDED_PERMISSIONS = "needed_permission";
- private static final String POSSIBLE_PERMISSIONS = "possible_permission";
- private static final String IMAGE = "image";
- private static final int PERMISSIONS_REQUEST_CODE = 15621;
-
- private int backgroundColor;
- private int buttonsColor;
- private int image;
- private String title;
- private String description;
- private String[] neededPermissions;
- private String[] possiblePermissions;
-
- private TextView titleTextView;
- private TextView descriptionTextView;
- private ImageView imageView;
-
- public static SlideFragment createInstance(SlideFragmentBuilder builder) {
- SlideFragment slideFragment = new SlideFragment();
-
- Bundle bundle = new Bundle();
- bundle.putInt(BACKGROUND_COLOR, builder.backgroundColor);
- bundle.putInt(BUTTONS_COLOR, builder.buttonsColor);
- bundle.putInt(IMAGE, builder.image);
- bundle.putString(TITLE, builder.title);
- bundle.putString(DESCRIPTION, builder.description);
- bundle.putStringArray(NEEDED_PERMISSIONS, builder.neededPermissions);
- bundle.putStringArray(POSSIBLE_PERMISSIONS, builder.possiblePermissions);
-
- slideFragment.setArguments(bundle);
- return slideFragment;
- }
-
- public static boolean isNotNullOrEmpty(String string) {
- return string != null && !string.isEmpty();
- }
-
- @Nullable
- @Override
- public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.fragment_slide, container, false);
- titleTextView = (TextView) view.findViewById(R.id.txt_title_slide);
- descriptionTextView = (TextView) view.findViewById(R.id.txt_description_slide);
- imageView = (ImageView) view.findViewById(R.id.image_slide);
- initializeView();
- return view;
- }
-
- public void initializeView() {
- Bundle bundle = getArguments();
- backgroundColor = bundle.getInt(BACKGROUND_COLOR);
- buttonsColor = bundle.getInt(BUTTONS_COLOR);
- image = bundle.getInt(IMAGE, 0);
- title = bundle.getString(TITLE);
- description = bundle.getString(DESCRIPTION);
- neededPermissions = bundle.getStringArray(NEEDED_PERMISSIONS);
- possiblePermissions = bundle.getStringArray(POSSIBLE_PERMISSIONS);
-
- updateViewWithValues();
- }
-
- public int backgroundColor() {
- return backgroundColor;
- }
-
- public int buttonsColor() {
- return buttonsColor;
- }
-
- public boolean hasAnyPermissionsToGrant() {
- boolean hasPermissionToGrant = hasPermissionsToGrant(neededPermissions);
- if (!hasPermissionToGrant) {
- hasPermissionToGrant = hasPermissionsToGrant(possiblePermissions);
- }
- return hasPermissionToGrant;
- }
-
- public boolean hasNeededPermissionsToGrant() {
- return hasPermissionsToGrant(neededPermissions);
- }
-
- public boolean canMoveFurther() {
- return true;
- }
-
- public String cantMoveFurtherErrorMessage() {
- return getString(R.string.impassable_slide);
- }
-
- private void updateViewWithValues() {
- titleTextView.setText(title);
- descriptionTextView.setText(description);
-
- if (image != 0) {
- imageView.setImageDrawable(ContextCompat.getDrawable(getActivity(), image));
- imageView.setVisibility(View.VISIBLE);
- }
- }
-
- public void askForPermissions() {
- ArrayList notGrantedPermissions = new ArrayList<>();
-
- if (neededPermissions != null) {
- for (String permission : neededPermissions) {
- if (isNotNullOrEmpty(permission)) {
- if (ContextCompat.checkSelfPermission(getContext(), permission) != PackageManager.PERMISSION_GRANTED) {
- notGrantedPermissions.add(permission);
- }
- }
- }
- }
- if (possiblePermissions != null) {
- for (String permission : possiblePermissions) {
- if (isNotNullOrEmpty(permission)) {
- if (ContextCompat.checkSelfPermission(getContext(), permission) != PackageManager.PERMISSION_GRANTED) {
- notGrantedPermissions.add(permission);
- }
- }
- }
- }
-
- String[] permissionsToGrant = removeEmptyAndNullStrings(notGrantedPermissions);
- ActivityCompat.requestPermissions(getActivity(), permissionsToGrant, PERMISSIONS_REQUEST_CODE);
- }
-
- private boolean hasPermissionsToGrant(String[] permissions) {
- if (permissions != null) {
- for (String permission : permissions) {
- if (isNotNullOrEmpty(permission)) {
- if (ContextCompat.checkSelfPermission(getContext(), permission) != PackageManager.PERMISSION_GRANTED) {
- return true;
- }
- }
- }
- }
- return false;
- }
-
- @SuppressWarnings("SuspiciousMethodCalls")
- private String[] removeEmptyAndNullStrings(final ArrayList permissions) {
- List list = new ArrayList<>(permissions);
- list.removeAll(Collections.singleton(null));
- return list.toArray(new String[list.size()]);
- }
-}
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/SlideFragmentBuilder.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/SlideFragmentBuilder.java
deleted file mode 100644
index f32b5ae..0000000
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/SlideFragmentBuilder.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package agency.tango.materialintroscreen;
-
-import android.support.annotation.ColorRes;
-import android.support.annotation.DrawableRes;
-
-@SuppressWarnings({"unused", "WeakerAccess"})
-public class SlideFragmentBuilder {
- int backgroundColor;
- int buttonsColor;
- String title;
- String description;
- String[] neededPermissions;
- String[] possiblePermissions;
- int image;
-
- public SlideFragmentBuilder backgroundColor(@ColorRes int backgroundColor) {
- this.backgroundColor = backgroundColor;
- return this;
- }
-
- public SlideFragmentBuilder buttonsColor(@ColorRes int buttonsColor) {
- this.buttonsColor = buttonsColor;
- return this;
- }
-
- public SlideFragmentBuilder title(String title) {
- this.title = title;
- return this;
- }
-
- public SlideFragmentBuilder description(String description) {
- this.description = description;
- return this;
- }
-
- public SlideFragmentBuilder neededPermissions(String[] neededPermissions) {
- this.neededPermissions = neededPermissions;
- return this;
- }
-
- public SlideFragmentBuilder possiblePermissions(String[] possiblePermissions) {
- this.possiblePermissions = possiblePermissions;
- return this;
- }
-
- public SlideFragmentBuilder image(@DrawableRes int image) {
- this.image = image;
- return this;
- }
-
- public SlideFragment build() {
- return SlideFragment.createInstance(this);
- }
-}
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/adapter/SlidesAdapter.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/adapter/SlidesAdapter.java
index b73fd38..ac1e7ec 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/adapter/SlidesAdapter.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/adapter/SlidesAdapter.java
@@ -6,23 +6,24 @@
import java.util.ArrayList;
-import agency.tango.materialintroscreen.SlideFragment;
+import agency.tango.materialintroscreen.fragments.SlideFragmentBase;
public class SlidesAdapter extends FragmentStatePagerAdapter {
- private ArrayList fragments = new ArrayList<>();
+
+ private ArrayList fragments = new ArrayList<>();
public SlidesAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
@Override
- public SlideFragment getItem(int position) {
+ public SlideFragmentBase getItem(int position) {
return fragments.get(position);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
- SlideFragment fragment = (SlideFragment) super.instantiateItem(container, position);
+ SlideFragmentBase fragment = (SlideFragmentBase) super.instantiateItem(container, position);
fragments.set(position, fragment);
return fragment;
}
@@ -32,7 +33,7 @@ public int getCount() {
return fragments.size();
}
- public void addItem(SlideFragment fragment) {
+ public void addItem(SlideFragmentBase fragment) {
fragments.add(getCount(), fragment);
notifyDataSetChanged();
}
@@ -50,7 +51,7 @@ public boolean shouldFinish(int position) {
}
public boolean shouldLockSlide(int position) {
- SlideFragment fragment = getItem(position);
+ SlideFragmentBase fragment = getItem(position);
return !fragment.canMoveFurther() || fragment.hasNeededPermissionsToGrant();
}
}
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/animations/translations/EnterDefaultTranslation.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/animations/translations/EnterDefaultTranslation.java
index 48905f0..eeee4db 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/animations/translations/EnterDefaultTranslation.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/animations/translations/EnterDefaultTranslation.java
@@ -9,6 +9,6 @@
public class EnterDefaultTranslation implements IViewTranslation {
@Override
public void translate(View view, @FloatRange(from = 0, to = 1.0) float percentage) {
- view.setTranslationY((1f - percentage) * view.getResources().getDimensionPixelOffset(R.dimen.y_offset));
+ view.setTranslationY((1f - percentage) * view.getResources().getDimensionPixelOffset(R.dimen.mis_y_offset));
}
}
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/animations/translations/ExitDefaultTranslation.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/animations/translations/ExitDefaultTranslation.java
index a1d6693..45dcca3 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/animations/translations/ExitDefaultTranslation.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/animations/translations/ExitDefaultTranslation.java
@@ -9,6 +9,6 @@
public class ExitDefaultTranslation implements IViewTranslation {
@Override
public void translate(View view, @FloatRange(from = 0, to = 1.0) float percentage) {
- view.setTranslationY(percentage * view.getResources().getDimensionPixelOffset(R.dimen.y_offset));
+ view.setTranslationY(percentage * view.getResources().getDimensionPixelOffset(R.dimen.mis_y_offset));
}
}
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/animations/translations/NoTranslation.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/animations/translations/NoTranslation.java
index 2b1004d..a4b4859 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/animations/translations/NoTranslation.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/animations/translations/NoTranslation.java
@@ -8,5 +8,6 @@
public class NoTranslation implements IViewTranslation {
@Override
public void translate(View view, @FloatRange(from = 0, to = 1.0) float percentage) {
+ //This method is intentionally left blank, as it should do nothing
}
}
\ No newline at end of file
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/animations/wrappers/NextButtonTranslationWrapper.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/animations/wrappers/NextButtonTranslationWrapper.java
index 3d8baaf..8a294fb 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/animations/wrappers/NextButtonTranslationWrapper.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/animations/wrappers/NextButtonTranslationWrapper.java
@@ -13,6 +13,6 @@ public NextButtonTranslationWrapper(View view) {
setExitTranslation(new ExitDefaultTranslation())
.setDefaultTranslation(new DefaultPositionTranslation())
- .setErrorAnimation(R.anim.shake_it);
+ .setErrorAnimation(R.anim.mis_shake_it);
}
}
\ No newline at end of file
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/MessageButtonBehaviour.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/behaviours/MessageButtonBehaviour.java
similarity index 56%
rename from material-intro-screen/src/main/java/agency/tango/materialintroscreen/MessageButtonBehaviour.java
rename to material-intro-screen/src/main/java/agency/tango/materialintroscreen/behaviours/MessageButtonBehaviour.java
index 4db0ea9..204d680 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/MessageButtonBehaviour.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/behaviours/MessageButtonBehaviour.java
@@ -1,13 +1,14 @@
-package agency.tango.materialintroscreen;
+package agency.tango.materialintroscreen.behaviours;
-import android.view.View;
+import agency.tango.materialintroscreen.listeners.click.MessageButtonClickListener;
@SuppressWarnings("unused")
public class MessageButtonBehaviour {
- private View.OnClickListener clickListener;
+
+ private MessageButtonClickListener clickListener;
private String messageButtonText;
- public MessageButtonBehaviour(View.OnClickListener clickListener, String messageButtonText) {
+ public MessageButtonBehaviour(MessageButtonClickListener clickListener, String messageButtonText) {
this.clickListener = clickListener;
this.messageButtonText = messageButtonText;
}
@@ -16,7 +17,7 @@ public MessageButtonBehaviour(String messageButtonText) {
this.messageButtonText = messageButtonText;
}
- public View.OnClickListener getClickListener() {
+ public MessageButtonClickListener getClickListener() {
return clickListener;
}
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/MoveUpBehaviour.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/behaviours/MoveUpBehaviour.java
similarity index 88%
rename from material-intro-screen/src/main/java/agency/tango/materialintroscreen/MoveUpBehaviour.java
rename to material-intro-screen/src/main/java/agency/tango/materialintroscreen/behaviours/MoveUpBehaviour.java
index 2be956c..77d2429 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/MoveUpBehaviour.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/behaviours/MoveUpBehaviour.java
@@ -1,4 +1,4 @@
-package agency.tango.materialintroscreen;
+package agency.tango.materialintroscreen.behaviours;
import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
@@ -9,6 +9,7 @@
@SuppressWarnings("unused")
public class MoveUpBehaviour extends CoordinatorLayout.Behavior {
+
public MoveUpBehaviour(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -19,7 +20,8 @@ public boolean layoutDependsOn(CoordinatorLayout parent, LinearLayout child, Vie
}
@Override
- public boolean onDependentViewChanged(CoordinatorLayout parent, LinearLayout child, View dependency) {
+ public boolean onDependentViewChanged(CoordinatorLayout parent, LinearLayout child,
+ View dependency) {
float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());
child.setTranslationY(translationY);
return true;
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/fragments/SlideFragment.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/fragments/SlideFragment.java
new file mode 100644
index 0000000..4f1d47b
--- /dev/null
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/fragments/SlideFragment.java
@@ -0,0 +1,145 @@
+package agency.tango.materialintroscreen.fragments;
+
+import android.os.Bundle;
+import android.support.annotation.ColorRes;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.Nullable;
+import android.support.annotation.StringRes;
+import android.support.v4.content.ContextCompat;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import agency.tango.materialintroscreen.R;
+
+public class SlideFragment extends SlideFragmentBase {
+
+ public static final String BACKGROUND_COLOR = "background_color";
+ public static final String BUTTONS_COLOR = "buttons_color";
+ public static final String TITLE = "title";
+ public static final String DESCRIPTION = "description";
+ public static final String NEEDED_PERMISSIONS = "needed_permission";
+ public static final String POSSIBLE_PERMISSIONS = "possible_permission";
+ public static final String IMAGE = "image";
+ public static final String GRANT_PERMISSION_MESSAGE = "grant_permission_message";
+ public static final String GRANT_PERMISSION_ERROR = "grant_permission_error";
+
+ @ColorRes
+ private int backgroundColor;
+
+ @ColorRes
+ private int buttonsColor;
+
+ @DrawableRes
+ private int image;
+
+ @StringRes
+ private int grantPermissionStringRes;
+
+ @StringRes
+ private int grantPermissionErrorStringRes;
+
+ private String title;
+ private String description;
+ private String[] neededPermissions;
+ private String[] possiblePermissions;
+
+ private TextView titleTextView;
+ private TextView descriptionTextView;
+ private ImageView imageView;
+
+ public static SlideFragment createInstance(Bundle bundle) {
+ SlideFragment slideFragment = new SlideFragment();
+ slideFragment.setArguments(bundle);
+ return slideFragment;
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.mis_fragment_slide, container, false);
+ titleTextView = (TextView) view.findViewById(R.id.txt_title_slide);
+ descriptionTextView = (TextView) view.findViewById(R.id.txt_description_slide);
+ imageView = (ImageView) view.findViewById(R.id.image_slide);
+ initializeView();
+ return view;
+ }
+
+ @Override
+ @ColorRes
+ public int backgroundColor() {
+ return backgroundColor;
+ }
+
+ @Override
+ @ColorRes
+ public int buttonsColor() {
+ return buttonsColor;
+ }
+
+ @Override
+ public String[] possiblePermissions() {
+ return possiblePermissions;
+ }
+
+ @Override
+ public String[] neededPermissions() {
+ return neededPermissions;
+ }
+
+ @Override
+ public boolean canMoveFurther() {
+ return true;
+ }
+
+ @Override
+ public String cantMoveFurtherErrorMessage() {
+ return getString(R.string.mis_impassable_slide);
+ }
+
+ @Override
+ public int grantPermissionStringRes() {
+ return grantPermissionStringRes;
+ }
+
+ @Override
+ public int grantPermissionErrorStringRes() {
+ return grantPermissionErrorStringRes;
+ }
+
+ private void initializeView() {
+ Bundle bundle = getArguments();
+ backgroundColor = bundle.getInt(BACKGROUND_COLOR);
+ buttonsColor = bundle.getInt(BUTTONS_COLOR);
+ image = bundle.getInt(IMAGE, 0);
+ title = bundle.getString(TITLE);
+ description = bundle.getString(DESCRIPTION);
+ neededPermissions = bundle.getStringArray(NEEDED_PERMISSIONS);
+ possiblePermissions = bundle.getStringArray(POSSIBLE_PERMISSIONS);
+ grantPermissionStringRes = bundle.getInt(GRANT_PERMISSION_MESSAGE);
+ grantPermissionErrorStringRes = bundle.getInt(GRANT_PERMISSION_ERROR);
+
+ updateViewWithValues();
+ }
+
+ private void updateViewWithValues() {
+ titleTextView.setText(title);
+ descriptionTextView.setText(description);
+
+ if (image != 0) {
+ imageView.setImageDrawable(ContextCompat.getDrawable(getActivity(), image));
+ imageView.setVisibility(View.VISIBLE);
+ }
+
+ if (grantPermissionStringRes == 0) {
+ grantPermissionStringRes = R.string.mis_grant_permissions;
+ }
+
+ if (grantPermissionErrorStringRes == 0) {
+ grantPermissionErrorStringRes = R.string.mis_please_grant_permissions;
+ }
+ }
+}
\ No newline at end of file
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/fragments/SlideFragmentBase.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/fragments/SlideFragmentBase.java
new file mode 100644
index 0000000..80d7925
--- /dev/null
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/fragments/SlideFragmentBase.java
@@ -0,0 +1,133 @@
+package agency.tango.materialintroscreen.fragments;
+
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.support.annotation.ColorRes;
+import android.support.annotation.StringRes;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.content.ContextCompat;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import agency.tango.materialintroscreen.R;
+import agency.tango.materialintroscreen.parallax.ParallaxFragment;
+
+public class SlideFragmentBase extends ParallaxFragment {
+
+ private static final int PERMISSIONS_REQUEST_CODE = 15621;
+
+ @ColorRes
+ public int backgroundColor() {
+ return R.color.mis_default_background_color;
+ }
+
+ @ColorRes
+ public int buttonsColor() {
+ return R.color.mis_default_buttons_color;
+ }
+
+ public boolean canMoveFurther() {
+ return true;
+ }
+
+ public String cantMoveFurtherErrorMessage() {
+ return getString(R.string.mis_impassable_slide);
+ }
+
+ public String[] possiblePermissions() {
+ return new String[0];
+ }
+
+ public String[] neededPermissions() {
+ return new String[0];
+ }
+
+ @StringRes
+ public int grantPermissionStringRes() {
+ return R.string.mis_grant_permissions;
+ }
+
+ @StringRes
+ public int grantPermissionErrorStringRes() {
+ return R.string.mis_please_grant_permissions;
+ }
+
+ public boolean hasAnyPermissionsToGrant() {
+ if (!isAndroidVersionSupportingPermissions()) {
+ return false;
+ }
+
+ boolean hasPermissionToGrant = hasPermissionsToGrant(neededPermissions());
+ if (!hasPermissionToGrant) {
+ hasPermissionToGrant = hasPermissionsToGrant(possiblePermissions());
+ }
+ return hasPermissionToGrant;
+ }
+
+ public boolean hasNeededPermissionsToGrant() {
+ return hasPermissionsToGrant(neededPermissions());
+ }
+
+ @SuppressWarnings({"PMD.CollapsibleIfStatements"})
+ public void askForPermissions() {
+ ArrayList notGrantedPermissions = new ArrayList<>();
+
+ if (neededPermissions() != null) {
+ for (String permission : neededPermissions()) {
+ if (!TextUtils.isEmpty(permission)) {
+ if (ContextCompat.checkSelfPermission(getContext(), permission)
+ != PackageManager.PERMISSION_GRANTED) {
+ notGrantedPermissions.add(permission);
+ }
+ }
+ }
+ }
+ if (possiblePermissions() != null) {
+ for (String permission : possiblePermissions()) {
+ if (!TextUtils.isEmpty(permission)) {
+ if (ContextCompat.checkSelfPermission(getContext(), permission)
+ != PackageManager.PERMISSION_GRANTED) {
+ notGrantedPermissions.add(permission);
+ }
+ }
+ }
+ }
+
+ String[] permissionsToGrant = removeEmptyAndNullStrings(notGrantedPermissions);
+ ActivityCompat
+ .requestPermissions(getActivity(), permissionsToGrant, PERMISSIONS_REQUEST_CODE);
+ }
+
+ @SuppressWarnings({"PMD.CollapsibleIfStatements"})
+ private boolean hasPermissionsToGrant(String[] permissions) {
+ if (!isAndroidVersionSupportingPermissions()) {
+ return false;
+ }
+
+ if (permissions != null) {
+ for (String permission : permissions) {
+ if (!TextUtils.isEmpty(permission)) {
+ if (ContextCompat.checkSelfPermission(getContext(), permission)
+ != PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ @SuppressWarnings("SuspiciousMethodCalls")
+ private String[] removeEmptyAndNullStrings(final ArrayList permissions) {
+ List list = new ArrayList<>(permissions);
+ list.removeAll(Collections.singleton(null));
+ return list.toArray(new String[list.size()]);
+ }
+
+ private boolean isAndroidVersionSupportingPermissions() {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
+ }
+}
\ No newline at end of file
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/fragments/SlideFragmentBuilder.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/fragments/SlideFragmentBuilder.java
new file mode 100644
index 0000000..51d5660
--- /dev/null
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/fragments/SlideFragmentBuilder.java
@@ -0,0 +1,113 @@
+package agency.tango.materialintroscreen.fragments;
+
+import android.os.Bundle;
+import android.support.annotation.ColorRes;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.StringRes;
+
+import static agency.tango.materialintroscreen.fragments.SlideFragment.BACKGROUND_COLOR;
+import static agency.tango.materialintroscreen.fragments.SlideFragment.BUTTONS_COLOR;
+import static agency.tango.materialintroscreen.fragments.SlideFragment.DESCRIPTION;
+import static agency.tango.materialintroscreen.fragments.SlideFragment.GRANT_PERMISSION_ERROR;
+import static agency.tango.materialintroscreen.fragments.SlideFragment.GRANT_PERMISSION_MESSAGE;
+import static agency.tango.materialintroscreen.fragments.SlideFragment.IMAGE;
+import static agency.tango.materialintroscreen.fragments.SlideFragment.NEEDED_PERMISSIONS;
+import static agency.tango.materialintroscreen.fragments.SlideFragment.POSSIBLE_PERMISSIONS;
+import static agency.tango.materialintroscreen.fragments.SlideFragment.TITLE;
+
+@SuppressWarnings("unused")
+public class SlideFragmentBuilder {
+
+ @ColorRes
+ private int backgroundColor;
+
+ @ColorRes
+ private int buttonsColor;
+
+ @DrawableRes
+ private int image;
+
+ @StringRes
+ private int grantPermissionMessage;
+
+ @StringRes
+ private int grantPermissionError;
+
+ private String title;
+ private String description;
+ private String[] neededPermissions;
+ private String[] possiblePermissions;
+
+ public SlideFragmentBuilder backgroundColor(@ColorRes int backgroundColor) {
+ this.backgroundColor = backgroundColor;
+ return this;
+ }
+
+ public SlideFragmentBuilder buttonsColor(@ColorRes int buttonsColor) {
+ this.buttonsColor = buttonsColor;
+ return this;
+ }
+
+ public SlideFragmentBuilder title(String title) {
+ this.title = title;
+ return this;
+ }
+
+ public SlideFragmentBuilder description(String description) {
+ this.description = description;
+ return this;
+ }
+
+ public SlideFragmentBuilder neededPermissions(String[] neededPermissions) {
+ this.neededPermissions = neededPermissions;
+ return this;
+ }
+
+ public SlideFragmentBuilder possiblePermissions(String[] possiblePermissions) {
+ this.possiblePermissions = possiblePermissions;
+ return this;
+ }
+
+ public SlideFragmentBuilder image(@DrawableRes int image) {
+ this.image = image;
+ return this;
+ }
+
+ public SlideFragmentBuilder grantPermissionMessage(@StringRes int grantPermissionMessage) {
+ this.grantPermissionMessage = grantPermissionMessage;
+ return this;
+ }
+
+ public SlideFragmentBuilder grantPermissionError(int grantPermissionError) {
+ this.grantPermissionError = grantPermissionError;
+ return this;
+ }
+
+
+ public SlideFragment build() {
+ String missing = "";
+ if (backgroundColor == 0) {
+ missing += " backgroundColor";
+ }
+ if (buttonsColor == 0) {
+ missing += " buttonsColor";
+ }
+ if (!missing.isEmpty()) {
+ throw new IllegalStateException(
+ "Missing required properties in SlideFragmentBuilder:" + missing);
+ }
+
+ Bundle bundle = new Bundle();
+ bundle.putInt(BACKGROUND_COLOR, backgroundColor);
+ bundle.putInt(BUTTONS_COLOR, buttonsColor);
+ bundle.putInt(IMAGE, image);
+ bundle.putString(TITLE, title);
+ bundle.putString(DESCRIPTION, description);
+ bundle.putStringArray(NEEDED_PERMISSIONS, neededPermissions);
+ bundle.putStringArray(POSSIBLE_PERMISSIONS, possiblePermissions);
+ bundle.putInt(GRANT_PERMISSION_MESSAGE, grantPermissionMessage);
+ bundle.putInt(GRANT_PERMISSION_ERROR, grantPermissionError);
+
+ return SlideFragment.createInstance(bundle);
+ }
+}
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/IFinishListener.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/IFinishListener.java
index 8a013bb..37ed789 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/IFinishListener.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/IFinishListener.java
@@ -1,5 +1,5 @@
package agency.tango.materialintroscreen.listeners;
public interface IFinishListener {
- void doOnFinish();
+ void onFinish();
}
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/MessageButtonBehaviourOnPageSelected.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/MessageButtonBehaviourOnPageSelected.java
index 3ee439d..3b92155 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/MessageButtonBehaviourOnPageSelected.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/MessageButtonBehaviourOnPageSelected.java
@@ -1,35 +1,38 @@
package agency.tango.materialintroscreen.listeners;
+import android.text.TextUtils;
import android.util.SparseArray;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.widget.Button;
-import agency.tango.materialintroscreen.MessageButtonBehaviour;
import agency.tango.materialintroscreen.R;
-import agency.tango.materialintroscreen.SlideFragment;
import agency.tango.materialintroscreen.adapter.SlidesAdapter;
+import agency.tango.materialintroscreen.behaviours.MessageButtonBehaviour;
+import agency.tango.materialintroscreen.fragments.SlideFragmentBase;
-import static agency.tango.materialintroscreen.SlideFragment.isNotNullOrEmpty;
public class MessageButtonBehaviourOnPageSelected implements IPageSelectedListener {
- private Button messageButton;
- private SlidesAdapter adapter;
- private SparseArray messageButtonBehaviours;
- public MessageButtonBehaviourOnPageSelected(Button messageButton, SlidesAdapter adapter, SparseArray messageButtonBehaviours) {
+ private final Button messageButton;
+ private final SlidesAdapter adapter;
+ private final SparseArray messageButtonBehaviours;
+
+ public MessageButtonBehaviourOnPageSelected(Button messageButton, SlidesAdapter adapter,
+ SparseArray messageButtonBehaviours) {
this.messageButton = messageButton;
this.adapter = adapter;
this.messageButtonBehaviours = messageButtonBehaviours;
}
@Override
- public void pageSelected(int position) {
- final SlideFragment slideFragment = adapter.getItem(position);
+ public void pageSelected(final int position) {
+ final SlideFragmentBase slideFragment = adapter.getItem(position);
if (slideFragment.hasAnyPermissionsToGrant()) {
showMessageButton(slideFragment);
- messageButton.setText(slideFragment.getActivity().getString(R.string.grant_permissions));
+ messageButton.setText(
+ slideFragment.getString(adapter.getItem(position).grantPermissionStringRes()));
messageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
@@ -39,22 +42,31 @@ public void onClick(View view) {
} else if (checkIfMessageButtonHasBehaviour(position)) {
showMessageButton(slideFragment);
messageButton.setText(messageButtonBehaviours.get(position).getMessageButtonText());
- messageButton.setOnClickListener(messageButtonBehaviours.get(position).getClickListener());
+ messageButton
+ .setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ messageButtonBehaviours.get(position).getClickListener().onClick(messageButton);
+ }
+ });
} else if (messageButton.getVisibility() != View.INVISIBLE) {
- messageButton.startAnimation(AnimationUtils.loadAnimation(slideFragment.getContext(), R.anim.fade_out));
+ messageButton.startAnimation(
+ AnimationUtils.loadAnimation(slideFragment.getContext(), R.anim.mis_fade_out));
messageButton.setVisibility(View.INVISIBLE);
}
}
private boolean checkIfMessageButtonHasBehaviour(int position) {
- return messageButtonBehaviours.get(position) != null && isNotNullOrEmpty(messageButtonBehaviours.get(position).getMessageButtonText());
+ return messageButtonBehaviours.get(position) != null && !TextUtils.isEmpty(
+ messageButtonBehaviours.get(position).getMessageButtonText());
}
- private void showMessageButton(final SlideFragment fragment) {
+ private void showMessageButton(final SlideFragmentBase fragment) {
if (messageButton.getVisibility() != View.VISIBLE) {
messageButton.setVisibility(View.VISIBLE);
if (fragment.getActivity() != null) {
- messageButton.startAnimation(AnimationUtils.loadAnimation(fragment.getActivity(), R.anim.fade_in));
+ messageButton.startAnimation(
+ AnimationUtils.loadAnimation(fragment.getActivity(), R.anim.mis_fade_in));
}
}
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/ViewBehavioursOnPageChangeListener.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/ViewBehavioursOnPageChangeListener.java
index dc8804c..3dbd2eb 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/ViewBehavioursOnPageChangeListener.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/ViewBehavioursOnPageChangeListener.java
@@ -9,6 +9,7 @@
import agency.tango.materialintroscreen.animations.ViewTranslationWrapper;
public class ViewBehavioursOnPageChangeListener implements CustomViewPager.OnPageChangeListener {
+
private final SlidesAdapter adapter;
private List listeners = new ArrayList<>();
@@ -19,17 +20,20 @@ public ViewBehavioursOnPageChangeListener(SlidesAdapter adapter) {
this.adapter = adapter;
}
- public ViewBehavioursOnPageChangeListener registerPageSelectedListener(IPageSelectedListener pageSelectedListener) {
+ public ViewBehavioursOnPageChangeListener registerPageSelectedListener(
+ IPageSelectedListener pageSelectedListener) {
listeners.add(pageSelectedListener);
return this;
}
- public ViewBehavioursOnPageChangeListener registerViewTranslationWrapper(ViewTranslationWrapper wrapper) {
+ public ViewBehavioursOnPageChangeListener registerViewTranslationWrapper(
+ ViewTranslationWrapper wrapper) {
wrappers.add(wrapper);
return this;
}
- public ViewBehavioursOnPageChangeListener registerOnPageScrolled(IPageScrolledListener pageScrolledListener) {
+ public ViewBehavioursOnPageChangeListener registerOnPageScrolled(
+ IPageScrolledListener pageScrolledListener) {
pageScrolledListeners.add(pageScrolledListener);
return this;
}
@@ -64,6 +68,7 @@ public void onPageSelected(int position) {
@Override
public void onPageScrollStateChanged(int state) {
+ //This method is intentionally left blank, as it should do nothing
}
private boolean isFirstSlide(int position) {
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/click/MessageButtonClickListener.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/click/MessageButtonClickListener.java
new file mode 100644
index 0000000..31623f7
--- /dev/null
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/click/MessageButtonClickListener.java
@@ -0,0 +1,7 @@
+package agency.tango.materialintroscreen.listeners.click;
+
+import android.widget.Button;
+
+public interface MessageButtonClickListener {
+ void onClick(Button messageButton);
+}
\ No newline at end of file
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/clickListeners/PermissionNotGrantedClickListener.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/click/PermissionNotGrantedClickListener.java
similarity index 91%
rename from material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/clickListeners/PermissionNotGrantedClickListener.java
rename to material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/click/PermissionNotGrantedClickListener.java
index b931287..ab63067 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/clickListeners/PermissionNotGrantedClickListener.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/click/PermissionNotGrantedClickListener.java
@@ -1,4 +1,4 @@
-package agency.tango.materialintroscreen.listeners.clickListeners;
+package agency.tango.materialintroscreen.listeners.click;
import android.view.View;
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/scrollListeners/ParallaxScrollListener.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/scroll/ParallaxScrollListener.java
similarity index 86%
rename from material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/scrollListeners/ParallaxScrollListener.java
rename to material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/scroll/ParallaxScrollListener.java
index 0493e2e..c9b7a8f 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/scrollListeners/ParallaxScrollListener.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/listeners/scroll/ParallaxScrollListener.java
@@ -1,14 +1,15 @@
-package agency.tango.materialintroscreen.listeners.scrollListeners;
+package agency.tango.materialintroscreen.listeners.scroll;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
-import agency.tango.materialintroscreen.SlideFragment;
import agency.tango.materialintroscreen.adapter.SlidesAdapter;
+import agency.tango.materialintroscreen.fragments.SlideFragmentBase;
import agency.tango.materialintroscreen.listeners.IPageScrolledListener;
import agency.tango.materialintroscreen.parallax.Parallaxable;
public class ParallaxScrollListener implements IPageScrolledListener {
+
private SlidesAdapter adapter;
public ParallaxScrollListener(SlidesAdapter adapter) {
@@ -33,7 +34,7 @@ public void pageScrolled(int position, float offset) {
}
@Nullable
- private SlideFragment getNextFragment(int position) {
+ private SlideFragmentBase getNextFragment(int position) {
if (position < adapter.getLastItemPosition()) {
return adapter.getItem(position + 1);
}
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/parallax/ParallaxFrameLayout.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/parallax/ParallaxFrameLayout.java
index 2fb4f6d..30fb215 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/parallax/ParallaxFrameLayout.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/parallax/ParallaxFrameLayout.java
@@ -60,8 +60,8 @@ public static class LayoutParams extends FrameLayout.LayoutParams {
LayoutParams(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
- TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.ParallaxLayout_Layout);
- parallaxFactor = typedArray.getFloat(R.styleable.ParallaxLayout_Layout_layout_parallaxFactor, parallaxFactor);
+ TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.mis_ParallaxLayout_Layout);
+ parallaxFactor = typedArray.getFloat(R.styleable.mis_ParallaxLayout_Layout_mis_layout_parallaxFactor, parallaxFactor);
typedArray.recycle();
}
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/parallax/ParallaxLinearLayout.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/parallax/ParallaxLinearLayout.java
index 3fa2743..41c2423 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/parallax/ParallaxLinearLayout.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/parallax/ParallaxLinearLayout.java
@@ -60,8 +60,8 @@ public static class LayoutParams extends LinearLayout.LayoutParams {
LayoutParams(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
- TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.ParallaxLayout_Layout);
- parallaxFactor = typedArray.getFloat(R.styleable.ParallaxLayout_Layout_layout_parallaxFactor, parallaxFactor);
+ TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.mis_ParallaxLayout_Layout);
+ parallaxFactor = typedArray.getFloat(R.styleable.mis_ParallaxLayout_Layout_mis_layout_parallaxFactor, parallaxFactor);
typedArray.recycle();
}
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/parallax/ParallaxPercentFrameLayout.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/parallax/ParallaxPercentFrameLayout.java
new file mode 100644
index 0000000..93d742b
--- /dev/null
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/parallax/ParallaxPercentFrameLayout.java
@@ -0,0 +1,87 @@
+package agency.tango.materialintroscreen.parallax;
+
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.support.annotation.FloatRange;
+import android.support.percent.PercentFrameLayout;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+import agency.tango.materialintroscreen.R;
+
+public class ParallaxPercentFrameLayout extends PercentFrameLayout implements Parallaxable {
+
+ public ParallaxPercentFrameLayout(Context context) {
+ super(context);
+ }
+
+ public ParallaxPercentFrameLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ParallaxPercentFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+ return p instanceof LayoutParams;
+ }
+
+ @Override
+ protected LayoutParams generateDefaultLayoutParams() {
+ return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+ }
+
+ @Override
+ public LayoutParams generateLayoutParams(AttributeSet attrs) {
+ return new LayoutParams(getContext(), attrs);
+ }
+
+ @Override
+ protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+ return new LayoutParams(p);
+ }
+
+ @Override
+ public void setOffset(@FloatRange(from = -1.0, to = 1.0) float offset) {
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ View child = getChildAt(i);
+ LayoutParams p = (LayoutParams) child.getLayoutParams();
+ if (p.parallaxFactor == 0)
+ continue;
+ child.setTranslationX(getWidth() * -offset * p.parallaxFactor);
+ }
+ }
+
+ public static class LayoutParams extends PercentFrameLayout.LayoutParams {
+ float parallaxFactor = 0f;
+
+ LayoutParams(Context context, AttributeSet attributeSet) {
+ super(context, attributeSet);
+ TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.mis_ParallaxLayout_Layout);
+ parallaxFactor = typedArray.getFloat(R.styleable.mis_ParallaxLayout_Layout_mis_layout_parallaxFactor, parallaxFactor);
+ typedArray.recycle();
+ }
+
+ LayoutParams(int width, int height) {
+ super(width, height);
+ }
+
+ @SuppressWarnings("unused")
+ LayoutParams(int width, int height, int gravity) {
+ super(width, height, gravity);
+ }
+
+ LayoutParams(ViewGroup.LayoutParams source) {
+ super(source);
+ }
+
+ @SuppressWarnings("unused")
+ LayoutParams(MarginLayoutParams source) {
+ super(source);
+ }
+ }
+}
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/parallax/ParallaxPercentRelativeLayout.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/parallax/ParallaxPercentRelativeLayout.java
new file mode 100644
index 0000000..3b6a200
--- /dev/null
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/parallax/ParallaxPercentRelativeLayout.java
@@ -0,0 +1,82 @@
+package agency.tango.materialintroscreen.parallax;
+
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.support.annotation.FloatRange;
+import android.support.percent.PercentRelativeLayout;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+import agency.tango.materialintroscreen.R;
+
+public class ParallaxPercentRelativeLayout extends PercentRelativeLayout implements Parallaxable {
+
+ public ParallaxPercentRelativeLayout(Context context) {
+ super(context);
+ }
+
+ public ParallaxPercentRelativeLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ParallaxPercentRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+ return p instanceof LayoutParams;
+ }
+
+ @Override
+ protected LayoutParams generateDefaultLayoutParams() {
+ return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+ }
+
+ @Override
+ public LayoutParams generateLayoutParams(AttributeSet attrs) {
+ return new LayoutParams(getContext(), attrs);
+ }
+
+ @Override
+ protected PercentRelativeLayout.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+ return new LayoutParams(p);
+ }
+
+ @Override
+ public void setOffset(@FloatRange(from = -1.0, to = 1.0) float offset) {
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ View child = getChildAt(i);
+ LayoutParams p = (LayoutParams) child.getLayoutParams();
+ if (p.parallaxFactor == 0)
+ continue;
+ child.setTranslationX(getWidth() * -offset * p.parallaxFactor);
+ }
+ }
+
+ public static class LayoutParams extends PercentRelativeLayout.LayoutParams {
+ float parallaxFactor = 0f;
+
+ LayoutParams(Context context, AttributeSet attributeSet) {
+ super(context, attributeSet);
+ TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.mis_ParallaxLayout_Layout);
+ parallaxFactor = typedArray.getFloat(R.styleable.mis_ParallaxLayout_Layout_mis_layout_parallaxFactor, parallaxFactor);
+ typedArray.recycle();
+ }
+
+ LayoutParams(int width, int height) {
+ super(width, height);
+ }
+
+ LayoutParams(ViewGroup.LayoutParams source) {
+ super(source);
+ }
+
+ @SuppressWarnings("unused")
+ LayoutParams(MarginLayoutParams source) {
+ super(source);
+ }
+ }
+}
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/parallax/ParallaxRelativeLayout.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/parallax/ParallaxRelativeLayout.java
index 1e524be..54025f2 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/parallax/ParallaxRelativeLayout.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/parallax/ParallaxRelativeLayout.java
@@ -60,8 +60,8 @@ public static class LayoutParams extends RelativeLayout.LayoutParams {
LayoutParams(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
- TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.ParallaxLayout_Layout);
- parallaxFactor = typedArray.getFloat(R.styleable.ParallaxLayout_Layout_layout_parallaxFactor, parallaxFactor);
+ TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.mis_ParallaxLayout_Layout);
+ parallaxFactor = typedArray.getFloat(R.styleable.mis_ParallaxLayout_Layout_mis_layout_parallaxFactor, parallaxFactor);
typedArray.recycle();
}
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/widgets/InkPageIndicator.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/widgets/InkPageIndicator.java
index 5fa7762..83a24fe 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/widgets/InkPageIndicator.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/widgets/InkPageIndicator.java
@@ -1,3 +1,20 @@
+/*
+ * Copyright 2015 Google Inc.
+ * Modifications Copyright 2017 Tango Agency
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package agency.tango.materialintroscreen.widgets;
import android.animation.Animator;
@@ -24,21 +41,27 @@
import agency.tango.materialintroscreen.R;
-public class InkPageIndicator extends View implements CustomViewPager.OnPageChangeListener, View.OnAttachStateChangeListener {
+public class InkPageIndicator extends View
+ implements CustomViewPager.OnPageChangeListener, View.OnAttachStateChangeListener {
+
+ // defaults
private static final int DEFAULT_DOT_SIZE = 8;
private static final int DEFAULT_GAP = 12;
private static final int DEFAULT_ANIM_DURATION = 400;
private static final int DEFAULT_UNSELECTED_COLOUR = 0x80ffffff;
private static final int DEFAULT_SELECTED_COLOUR = 0xffffffff;
+ // constants
private static final float INVALID_FRACTION = -1f;
private static final float MINIMAL_REVEAL = 0.00001f;
+
private final Paint selectedPaint;
private final Path unselectedDotPath;
private final Path unselectedDotLeftPath;
private final Path unselectedDotRightPath;
private final RectF rectF;
private final Interpolator interpolator;
+
float endX1;
float endY1;
float endX2;
@@ -47,17 +70,24 @@ public class InkPageIndicator extends View implements CustomViewPager.OnPageChan
float controlY1;
float controlX2;
float controlY2;
+
+ // configurable attributes
private int dotDiameter;
private int gap;
private long animDuration;
private int unselectedColour;
+
+ // derived from attributes
private float dotRadius;
private float halfDotRadius;
private long animHalfDuration;
private float dotTopY;
private float dotCenterY;
private float dotBottomY;
+
private SwipeableViewPager viewPager;
+
+ // state
private int pageCount;
private int currentPage;
private int previousPage;
@@ -70,8 +100,12 @@ public class InkPageIndicator extends View implements CustomViewPager.OnPageChan
private float[] dotRevealFractions;
private boolean isAttachedToWindow;
private boolean pageChanging;
+
+ // drawing
private Paint unselectedPaint;
private Path combinedUnselectedPath;
+
+ // animation
private ValueAnimator moveAnimation;
private PendingRetreatAnimator retreatAnimation;
private PendingRevealAnimator[] revealAnimations;
@@ -89,17 +123,27 @@ public InkPageIndicator(Context context, AttributeSet attrs, int defStyle) {
final int density = (int) context.getResources().getDisplayMetrics().density;
+ // Load attributes
final TypedArray typedArray = getContext().obtainStyledAttributes(
- attrs, R.styleable.InkPageIndicator, defStyle, 0);
+ attrs, R.styleable.mis_InkPageIndicator, defStyle, 0);
- dotDiameter = typedArray.getDimensionPixelSize(R.styleable.InkPageIndicator_dotDiameter, DEFAULT_DOT_SIZE * density);
+ dotDiameter = typedArray
+ .getDimensionPixelSize(R.styleable.mis_InkPageIndicator_mis_dotDiameter,
+ DEFAULT_DOT_SIZE * density);
dotRadius = dotDiameter / 2;
halfDotRadius = dotRadius / 2;
- gap = typedArray.getDimensionPixelSize(R.styleable.InkPageIndicator_dotGap, DEFAULT_GAP * density);
- animDuration = (long) typedArray.getInteger(R.styleable.InkPageIndicator_animationDuration, DEFAULT_ANIM_DURATION);
+ gap = typedArray.getDimensionPixelSize(R.styleable.mis_InkPageIndicator_mis_dotGap,
+ DEFAULT_GAP * density);
+ animDuration = (long) typedArray
+ .getInteger(R.styleable.mis_InkPageIndicator_mis_animationDuration,
+ DEFAULT_ANIM_DURATION);
animHalfDuration = animDuration / 2;
- unselectedColour = typedArray.getColor(R.styleable.InkPageIndicator_pageIndicatorColor, DEFAULT_UNSELECTED_COLOUR);
- int selectedColour = typedArray.getColor(R.styleable.InkPageIndicator_currentPageIndicatorColor, DEFAULT_SELECTED_COLOUR);
+ unselectedColour = typedArray
+ .getColor(R.styleable.mis_InkPageIndicator_mis_pageIndicatorColor,
+ DEFAULT_UNSELECTED_COLOUR);
+ int selectedColour = typedArray
+ .getColor(R.styleable.mis_InkPageIndicator_mis_currentPageIndicatorColor,
+ DEFAULT_SELECTED_COLOUR);
typedArray.recycle();
unselectedPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@@ -108,6 +152,7 @@ public InkPageIndicator(Context context, AttributeSet attrs, int defStyle) {
selectedPaint.setColor(selectedColour);
interpolator = new FastOutSlowInInterpolator();
+ // create paths & rect now – reuse & rewind later
combinedUnselectedPath = new Path();
unselectedDotPath = new Path();
unselectedDotLeftPath = new Path();
@@ -144,6 +189,8 @@ public void onPageScrolled(int position, float positionOffset, int positionOffse
if (currentPosition != position) {
fraction = 1f - positionOffset;
+ // when swiping from #2 to #1 ViewPager reports position as 1 and a descending offset
+ // need to convert this into our left-dot-based 'coordinate space'
if (fraction == 1f) {
leftDotPosition = Math.min(currentPosition, position);
}
@@ -156,8 +203,10 @@ public void onPageScrolled(int position, float positionOffset, int positionOffse
public void onPageSelected(int position) {
if (position < pageCount) {
if (isAttachedToWindow) {
+ // this is the main event we're interested in!
setSelectedPage(position);
} else {
+ // when not attached, don't animate the move, just store immediately
setCurrentPageImmediate();
}
}
@@ -165,6 +214,7 @@ public void onPageSelected(int position) {
@Override
public void onPageScrollStateChanged(int state) {
+ // nothing to do
}
private void setPageCount(int pages) {
@@ -206,7 +256,8 @@ private void setCurrentPageImmediate() {
}
private boolean isDotAnimationStarted() {
- return dotCenterX != null && dotCenterX.length > 0 && (moveAnimation == null || !moveAnimation.isStarted());
+ return dotCenterX != null && dotCenterX.length > 0 && (moveAnimation == null
+ || !moveAnimation.isStarted());
}
private void resetState() {
@@ -277,7 +328,9 @@ public void onViewDetachedFromWindow(View view) {
@Override
protected void onDraw(Canvas canvas) {
- if (viewPager == null || pageCount == 0) return;
+ if (viewPager == null || pageCount == 0) {
+ return;
+ }
drawUnselected(canvas);
drawSelected(canvas);
}
@@ -285,6 +338,7 @@ protected void onDraw(Canvas canvas) {
private void drawUnselected(Canvas canvas) {
combinedUnselectedPath.rewind();
+ // draw any settled, revealing or joining dots
for (int page = 0; page < pageCount; page++) {
int nextXIndex;
@@ -304,6 +358,7 @@ private void drawUnselected(Canvas canvas) {
combinedUnselectedPath.addPath(unselectedPath);
}
+ // draw any retreating joins
if (retreatingJoinX1 != INVALID_FRACTION) {
Path retreatingJoinPath = getRetreatingJoinPath();
combinedUnselectedPath.addPath(retreatingJoinPath);
@@ -312,20 +367,47 @@ private void drawUnselected(Canvas canvas) {
canvas.drawPath(combinedUnselectedPath, unselectedPaint);
}
- private Path getUnselectedPath(int page, float centerX, float nextCenterX, float joiningFraction, float dotRevealFraction) {
+ /**
+ * Unselected dots can be in 6 states:
+ *
+ * #1 At rest
+ * #2 Joining neighbour, still separate
+ * #3 Joining neighbour, combined curved
+ * #4 Joining neighbour, combined straight
+ * #5 Join retreating
+ * #6 Dot re-showing / revealing
+ *
+ * It can also be in a combination of these states e.g. joining one neighbour while
+ * retreating from another. We therefore create a Path so that we can examine each
+ * dot pair separately and later take the union for these cases.
+ *
+ * This function returns a path for the given dot **and any action to it's right** e.g. joining
+ * or retreating from it's neighbour
+ */
+ @SuppressWarnings("PMD.ExcessiveMethodLength")
+ private Path getUnselectedPath(int page, float centerX, float nextCenterX,
+ float joiningFraction, float dotRevealFraction) {
unselectedDotPath.rewind();
+ // case #1 – At rest
if (isDotNotJoining(page, joiningFraction, dotRevealFraction)) {
unselectedDotPath.addCircle(dotCenterX[page], dotCenterY, dotRadius, Path.Direction.CW);
}
if (isDotJoining(joiningFraction)) {
+ // case #2 – Joining neighbour, still separate
+ // start with the left dot
unselectedDotLeftPath.rewind();
+
+ // start at the bottom center
unselectedDotLeftPath.moveTo(centerX, dotBottomY);
+
+ // semi circle to the top center
rectF.set(centerX - dotRadius, dotTopY, centerX + dotRadius, dotBottomY);
unselectedDotLeftPath.arcTo(rectF, 90, 180, true);
+ // cubic to the right middle
endX1 = centerX + dotRadius + (joiningFraction * gap);
endY1 = dotCenterY;
controlX1 = centerX + halfDotRadius;
@@ -336,6 +418,7 @@ private Path getUnselectedPath(int page, float centerX, float nextCenterX, float
controlX2, controlY2,
endX1, endY1);
+ // cubic back to the bottom center
endX2 = centerX;
endY2 = dotBottomY;
controlX1 = endX1;
@@ -348,12 +431,17 @@ private Path getUnselectedPath(int page, float centerX, float nextCenterX, float
unselectedDotPath.addPath(unselectedDotLeftPath);
+ // now do the next dot to the right
unselectedDotRightPath.rewind();
+
+ // start at the bottom center
unselectedDotRightPath.moveTo(nextCenterX, dotBottomY);
+ // semi circle to the top center
rectF.set(nextCenterX - dotRadius, dotTopY, nextCenterX + dotRadius, dotBottomY);
unselectedDotRightPath.arcTo(rectF, 90, -180, true);
+ // cubic to the left middle
endX1 = nextCenterX - dotRadius - (joiningFraction * gap);
endY1 = dotCenterY;
controlX1 = nextCenterX - halfDotRadius;
@@ -364,6 +452,7 @@ private Path getUnselectedPath(int page, float centerX, float nextCenterX, float
controlX2, controlY2,
endX1, endY1);
+ // cubic back to the bottom center
endX2 = nextCenterX;
endY2 = dotBottomY;
controlX1 = endX1;
@@ -376,13 +465,21 @@ private Path getUnselectedPath(int page, float centerX, float nextCenterX, float
unselectedDotPath.addPath(unselectedDotRightPath);
}
- if (joiningFraction > 0.5f && joiningFraction < 1f && retreatingJoinX1 == INVALID_FRACTION) {
+ if (joiningFraction > 0.5f && joiningFraction < 1f
+ && retreatingJoinX1 == INVALID_FRACTION) {
+ // case #3 – Joining neighbour, combined curved
+
+ // adjust the fraction so that it goes from 0.3 -> 1 to produce a more realistic 'join'
float adjustedFraction = (joiningFraction - 0.2f) * 1.25f;
+ // start in the bottom left
unselectedDotPath.moveTo(centerX, dotBottomY);
+
+ // semi-circle to the top left
rectF.set(centerX - dotRadius, dotTopY, centerX + dotRadius, dotBottomY);
unselectedDotPath.arcTo(rectF, 90, 180, true);
+ // bezier to the middle top of the join
endX1 = centerX + dotRadius + (gap / 2);
endY1 = dotCenterY - (adjustedFraction * dotRadius);
controlX1 = endX1 - (adjustedFraction * dotRadius);
@@ -393,6 +490,7 @@ private Path getUnselectedPath(int page, float centerX, float nextCenterX, float
controlX2, controlY2,
endX1, endY1);
+ // bezier to the top right of the join
endX2 = nextCenterX;
endY2 = dotTopY;
controlX1 = endX1 + ((1 - adjustedFraction) * dotRadius);
@@ -403,9 +501,12 @@ private Path getUnselectedPath(int page, float centerX, float nextCenterX, float
controlX2, controlY2,
endX2, endY2);
+ // semi-circle to the bottom right
rectF.set(nextCenterX - dotRadius, dotTopY, nextCenterX + dotRadius, dotBottomY);
unselectedDotPath.arcTo(rectF, 270, 180, true);
+ // bezier to the middle bottom of the join
+ // endX1 stays the same
endY1 = dotCenterY + (adjustedFraction * dotRadius);
controlX1 = endX1 + (adjustedFraction * dotRadius);
controlY1 = dotBottomY;
@@ -415,6 +516,7 @@ private Path getUnselectedPath(int page, float centerX, float nextCenterX, float
controlX2, controlY2,
endX1, endY1);
+ // bezier back to the start point in the bottom left
endX2 = centerX;
endY2 = dotBottomY;
controlX1 = endX1 - ((1 - adjustedFraction) * dotRadius);
@@ -426,11 +528,19 @@ private Path getUnselectedPath(int page, float centerX, float nextCenterX, float
endX2, endY2);
}
if (joiningFraction == 1 && retreatingJoinX1 == INVALID_FRACTION) {
+ // case #4 Joining neighbour, combined straight technically we could use case 3 for this
+ // situation as well but assume that this is an optimization rather than faffing around
+ // with beziers just to draw a rounded rect
rectF.set(centerX - dotRadius, dotTopY, nextCenterX + dotRadius, dotBottomY);
unselectedDotPath.addRoundRect(rectF, dotRadius, dotRadius, Path.Direction.CW);
}
+ // case #5 is handled by #getRetreatingJoinPath()
+ // this is done separately so that we can have a single retreating path spanning
+ // multiple dots and therefore animate it's movement smoothly
+
if (dotRevealFraction > MINIMAL_REVEAL) {
+ // case #6 – previously hidden dot revealing
unselectedDotPath.addCircle(centerX, dotCenterY, dotRevealFraction * dotRadius,
Path.Direction.CW);
}
@@ -439,7 +549,8 @@ private Path getUnselectedPath(int page, float centerX, float nextCenterX, float
}
private boolean isDotJoining(float joiningFraction) {
- return joiningFraction > 0f && joiningFraction <= 0.5f && retreatingJoinX1 == INVALID_FRACTION;
+ return joiningFraction > 0f && joiningFraction <= 0.5f
+ && retreatingJoinX1 == INVALID_FRACTION;
}
private boolean isDotNotJoining(int page, float joiningFraction, float dotRevealFraction) {
@@ -481,14 +592,20 @@ private void setSelectedPage(int now) {
}
}
+ // create the anim to move the selected dot – this animator will kick off
+ // retreat animations when it has moved 75% of the way.
+ // The retreat animation in turn will kick of reveal anims when the
+ // retreat has passed any dots to be revealed
moveAnimation = createMoveSelectedAnimator(dotCenterX[now], previousPage, now, steps);
moveAnimation.start();
}
private ValueAnimator createMoveSelectedAnimator(
final float moveTo, int was, int now, int steps) {
+ // create the actual move animator
ValueAnimator moveSelected = ValueAnimator.ofFloat(selectedDotX, moveTo);
+ // also set up a pending retreat anim – this starts when the move is 75% complete
retreatAnimation = new PendingRetreatAnimator(was, now, steps,
now > was ?
new RightwardStartPredicate(moveTo - ((moveTo - selectedDotX) * 0.25f)) :
@@ -511,15 +628,21 @@ public void onAnimationUpdate(ValueAnimator valueAnimator) {
moveSelected.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
+ // set a flag so that we continue to draw the unselected dot in the target position
+ // until the selected dot has finished moving into place
selectedDotInPosition = false;
}
@Override
public void onAnimationEnd(Animator animation) {
+ // set a flag when anim finishes so that we don't draw both selected & unselected
+ // page dots
selectedDotInPosition = true;
}
});
+ // slightly delay the start to give the joins a chance to run
+ // unless dot isn't in position yet – then don't delay!
moveSelected.setStartDelay(selectedDotInPosition ? animDuration / 4L : 0L);
moveSelected.setDuration(animDuration * 3L / 4L);
moveSelected.setInterpolator(interpolator);
@@ -527,11 +650,9 @@ public void onAnimationEnd(Animator animation) {
}
private void setJoiningFraction(int leftDot, float fraction) {
- if (joiningFractions != null) {
- if (leftDot < joiningFractions.length) {
- joiningFractions[leftDot] = fraction;
- ViewCompat.postInvalidateOnAnimation(this);
- }
+ if (joiningFractions != null && leftDot < joiningFractions.length) {
+ joiningFractions[leftDot] = fraction;
+ ViewCompat.postInvalidateOnAnimation(this);
}
}
@@ -570,6 +691,7 @@ public Parcelable onSaveInstanceState() {
}
static class SavedState extends BaseSavedState {
+
public static final Creator CREATOR = new Creator() {
@Override
public SavedState createFromParcel(Parcel in) {
@@ -599,7 +721,12 @@ public void writeToParcel(Parcel dest, int flags) {
}
}
+
+ /**
+ * A {@link ValueAnimator} that starts once a given predicate returns true.
+ */
public abstract class PendingStartAnimator extends ValueAnimator {
+
boolean hasStarted;
StartPredicate predicate;
@@ -617,7 +744,13 @@ void startIfNecessary(float currentValue) {
}
}
+ /**
+ * An Animator that shows and then shrinks a retreating join between the previous and newly
+ * selected pages. This also sets up some pending dot reveals – to be started when the retreat
+ * has passed the dot to be revealed.
+ */
public class PendingRetreatAnimator extends PendingStartAnimator {
+
PendingRetreatAnimator(int was, int now, int steps, StartPredicate predicate) {
super(predicate);
setDuration(animHalfDuration);
@@ -701,7 +834,11 @@ public void onAnimationEnd(Animator animation) {
}
}
+ /**
+ * An Animator that animates a given dot's revealFraction i.e. scales it up
+ */
public class PendingRevealAnimator extends PendingStartAnimator {
+
private int dot;
PendingRevealAnimator(int dot, StartPredicate predicate) {
@@ -727,7 +864,11 @@ public void onAnimationEnd(Animator animation) {
}
}
+ /**
+ * A predicate used to start an animation when a test passes
+ */
public abstract class StartPredicate {
+
float thresholdValue;
StartPredicate(float thresholdValue) {
@@ -737,7 +878,11 @@ public abstract class StartPredicate {
abstract boolean shouldStart(float currentValue);
}
+ /**
+ * A predicate used to start an animation when a given value is greater than a threshold
+ */
public class RightwardStartPredicate extends StartPredicate {
+
RightwardStartPredicate(float thresholdValue) {
super(thresholdValue);
}
@@ -747,7 +892,11 @@ boolean shouldStart(float currentValue) {
}
}
+ /**
+ * A predicate used to start an animation then a given value is less than a threshold
+ */
public class LeftwardStartPredicate extends StartPredicate {
+
LeftwardStartPredicate(float thresholdValue) {
super(thresholdValue);
}
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/widgets/OverScrollViewPager.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/widgets/OverScrollViewPager.java
index 186d532..0bceb18 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/widgets/OverScrollViewPager.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/widgets/OverScrollViewPager.java
@@ -14,6 +14,7 @@
import agency.tango.materialintroscreen.listeners.IFinishListener;
public class OverScrollViewPager extends RelativeLayout {
+
private SwipeableViewPager swipeableViewPager = null;
private boolean mIsBeingDragged = false;
private float mMotionBeginX = 0;
@@ -41,6 +42,7 @@ public OverScrollViewPager(Context context, AttributeSet attrs, int defStyle) {
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
}
+ @SuppressWarnings({"PMD.CollapsibleIfStatements"})
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
int action = event.getAction();
@@ -95,10 +97,11 @@ private void moveOverScrollView(float currentX) {
scrollTo((int) -currentX, 0);
positionOffset = calculateOffset();
- swipeableViewPager.onPageScrolled(swipeableViewPager.getAdapter().getLastItemPosition(), positionOffset, 0);
+ swipeableViewPager.onPageScrolled(swipeableViewPager.getAdapter().getLastItemPosition(),
+ positionOffset, 0);
if (shouldFinish()) {
- finishListener.doOnFinish();
+ finishListener.onFinish();
}
}
}
@@ -120,14 +123,17 @@ private void resetOverScrollViewWithAnimation(final float currentX) {
}
private void finishOverScrollViewWithAnimation(float currentX) {
- post(new SmoothScrollRunnable((int) currentX, -getWidth(), 300, new AccelerateInterpolator()));
+ post(new SmoothScrollRunnable((int) currentX, -getWidth(), 300,
+ new AccelerateInterpolator()));
}
+ @SuppressWarnings({"PMD.SimplifyBooleanReturns", "RedundantIfStatement", "PMD.CollapsibleIfStatements"})
private boolean canOverScrollAtEnd() {
SwipeableViewPager viewPager = getOverScrollView();
PagerAdapter adapter = viewPager.getAdapter();
if (null != adapter && adapter.getCount() > 0) {
- if (viewPager.alphaExitTransitionEnabled() && viewPager.getCurrentItem() == adapter.getCount() - 1) {
+ if (viewPager.alphaExitTransitionEnabled()
+ && viewPager.getCurrentItem() == adapter.getCount() - 1) {
return true;
}
return false;
@@ -138,11 +144,12 @@ private boolean canOverScrollAtEnd() {
private SwipeableViewPager createOverScrollView() {
SwipeableViewPager swipeableViewPager = new SwipeableViewPager(getContext(), null);
- swipeableViewPager.setId(R.id.swipeable_view_pager);
+ swipeableViewPager.setId(R.id.mis_swipeable_view_pager);
return swipeableViewPager;
}
final class SmoothScrollRunnable implements Runnable {
+
private final Interpolator interpolator;
private final int scrollToPosition;
private final int scrollFromPosition;
@@ -151,7 +158,8 @@ final class SmoothScrollRunnable implements Runnable {
private long startTime = -1;
private int currentPosition = -1;
- SmoothScrollRunnable(int fromPosition, int toPosition, long duration, Interpolator scrollAnimationInterpolator) {
+ SmoothScrollRunnable(int fromPosition, int toPosition, long duration,
+ Interpolator scrollAnimationInterpolator) {
scrollFromPosition = fromPosition;
scrollToPosition = toPosition;
interpolator = scrollAnimationInterpolator;
diff --git a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/widgets/SwipeableViewPager.java b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/widgets/SwipeableViewPager.java
index dc1d9c1..13fa04d 100644
--- a/material-intro-screen/src/main/java/agency/tango/materialintroscreen/widgets/SwipeableViewPager.java
+++ b/material-intro-screen/src/main/java/agency/tango/materialintroscreen/widgets/SwipeableViewPager.java
@@ -7,13 +7,17 @@
import android.view.KeyEvent;
import android.view.MotionEvent;
+import agency.tango.materialintroscreen.ISlideErrorHandler;
import agency.tango.materialintroscreen.adapter.SlidesAdapter;
+@SuppressWarnings("PMD.SingularField")
public class SwipeableViewPager extends CustomViewPager {
+
private float startPos = 0;
private int currentIt;
private boolean swipingAllowed;
private boolean alphaExitTransitionEnabled = false;
+ private ISlideErrorHandler errorHandler;
public SwipeableViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -53,13 +57,15 @@ public boolean onTouchEvent(final MotionEvent event) {
resolveSwipingRightAllowed();
return super.onTouchEvent(event);
case (MotionEvent.ACTION_MOVE):
- if (!swipingAllowed && startPos - event.getX() > 16) {
+ if (isSwipingNotAllowed(event)) {
+ errorHandler.handleError();
return true;
}
return super.onTouchEvent(event);
case (MotionEvent.ACTION_UP):
- if (!swipingAllowed && startPos - event.getX() > 16) {
+ if (isSwipingNotAllowed(event)) {
smoothScrollTo(getWidth() * currentIt, 0);
+ errorHandler.handleError();
return true;
}
startPos = 0;
@@ -79,8 +85,11 @@ public boolean executeKeyEvent(KeyEvent event) {
return false;
}
- public void moveToNextPage()
- {
+ public void registerSlideErrorHandler(ISlideErrorHandler handler) {
+ errorHandler = handler;
+ }
+
+ public void moveToNextPage() {
setCurrentItem(getCurrentItem() + 1, true);
}
@@ -104,6 +113,10 @@ public boolean alphaExitTransitionEnabled() {
return alphaExitTransitionEnabled && swipingAllowed;
}
+ private boolean isSwipingNotAllowed(MotionEvent event) {
+ return !swipingAllowed && startPos - event.getX() > 16;
+ }
+
private void resolveSwipingRightAllowed() {
if (getAdapter().shouldLockSlide(getCurrentItem())) {
setSwipingRightAllowed(false);
diff --git a/material-intro-screen/src/main/java/android/support/v4/view/CustomViewPager.java b/material-intro-screen/src/main/java/android/support/v4/view/CustomViewPager.java
index 5164dad..6ad12d9 100644
--- a/material-intro-screen/src/main/java/android/support/v4/view/CustomViewPager.java
+++ b/material-intro-screen/src/main/java/android/support/v4/view/CustomViewPager.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2011 The Android Open Source Project
+ * Modifications Copyright 2017 Tango Agency
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -70,9 +71,9 @@
* through pages of data. You supply an implementation of a
* {@link PagerAdapter} to generate the pages that the view shows.
*
- * ViewPager is most often used in conjunction with {@link android.app.Fragment},
+ *
CustomViewPager is most often used in conjunction with {@link android.app.Fragment},
* which is a convenient way to supply and manage the lifecycle of each page.
- * There are standard adapters implemented for using fragments with the ViewPager,
+ * There are standard adapters implemented for using fragments with the CustomViewPager,
* which cover the most common use cases. These are
* {@link android.support.v4.app.FragmentPagerAdapter} and
* {@link android.support.v4.app.FragmentStatePagerAdapter}; each of these
@@ -84,7 +85,7 @@
* its {@code android:layout_gravity} attribute. For example:
*
*
- * <android.support.v4.view.ViewPager
+ * <android.support.v4.view.CustomViewPager
* android:layout_width="match_parent"
* android:layout_height="match_parent">
*
@@ -93,21 +94,24 @@
* android:layout_height="wrap_content"
* android:layout_gravity="top" />
*
- * </android.support.v4.view.ViewPager>
+ * </android.support.v4.view.CustomViewPager>
*
*
- * For more information about how to use ViewPager, read For more information about how to use CustomViewPager, read Creating Swipe Views with
* Tabs.
*
- * Below is a more complicated example of ViewPager, using it in conjunction
+ *
Below is a more complicated example of CustomViewPager, using it in conjunction
* with {@link android.app.ActionBar} tabs. You can find other examples of using
- * ViewPager in the API 4+ Support Demos and API 13+ Support Demos sample code.
+ * CustomViewPager in the API 4+ Support Demos and API 13+ Support Demos sample code.
*
* {@sample frameworks/support/samples/Support13Demos/src/com/example/android/supportv13/app/ActionBarTabsPager.java
- * complete}
+ * complete}
*/
+
+@SuppressWarnings("PMD")
public class CustomViewPager extends ViewGroup {
+
private static final String TAG = "CustomViewPager";
private static final boolean DEBUG = false;
@@ -121,7 +125,7 @@ public class CustomViewPager extends ViewGroup {
private static final int MIN_FLING_VELOCITY = 400; // dips
- private static final int[] LAYOUT_ATTRS = new int[] {
+ private static final int[] LAYOUT_ATTRS = new int[]{
android.R.attr.layout_gravity
};
@@ -131,21 +135,14 @@ public class CustomViewPager extends ViewGroup {
*/
private int mExpectedAdapterCount;
- static class ItemInfo {
- Object object;
- int position;
- boolean scrolling;
- float widthFactor;
- float offset;
- }
-
- private static final Comparator COMPARATOR = new Comparator(){
+ private static final Comparator COMPARATOR = new Comparator() {
@Override
public int compare(ItemInfo lhs, ItemInfo rhs) {
return lhs.position - rhs.position;
}
};
+ @SuppressWarnings("PMD.AvoidReassigningParameters")
private static final Interpolator sInterpolator = new Interpolator() {
@Override
public float getInterpolation(float t) {
@@ -181,8 +178,6 @@ public float getInterpolation(float t) {
private float mFirstOffset = -Float.MAX_VALUE;
private float mLastOffset = Float.MAX_VALUE;
- private int mChildWidthMeasureSpec;
- private int mChildHeightMeasureSpec;
private boolean mInLayout;
private boolean mScrollingCacheEnabled;
@@ -234,7 +229,6 @@ public float getInterpolation(float t) {
private EdgeEffectCompat mRightEdge;
private boolean mFirstLayout = true;
- private boolean mNeedCalculatePageOffsets = false;
private boolean mCalledSuper;
private int mDecorChildCount;
@@ -287,9 +281,11 @@ public interface OnPageChangeListener {
* This method will be invoked when the current page is scrolled, either as part
* of a programmatically initiated smooth scroll or a user initiated touch scroll.
*
- * @param position Position index of the first page currently being displayed.
- * Page position+1 will be visible if positionOffset is nonzero.
- * @param positionOffset Value from [0, 1) indicating the offset from the page at position.
+ * @param position Position index of the first page currently being displayed.
+ * Page position+1 will be visible if positionOffset is
+ * nonzero.
+ * @param positionOffset Value from [0, 1) indicating the offset from the page at
+ * position.
* @param positionOffsetPixels Value in pixels indicating the offset from position.
*/
void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);
@@ -321,6 +317,7 @@ public interface OnPageChangeListener {
* every method of {@link OnPageChangeListener}.
*/
public static class SimpleOnPageChangeListener implements OnPageChangeListener {
+
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// This space for rent
@@ -347,10 +344,11 @@ public void onPageScrollStateChanged(int state) {
* be ignored.
*/
public interface PageTransformer {
+
/**
* Apply a property transformation to the given page.
*
- * @param page Apply the transformation to this page
+ * @param page Apply the transformation to this page
* @param position Position of page relative to the current front-and-center
* position of the pager. 0 is front and center. 1 is one full
* page position to the right, and -1 is one page position to the left.
@@ -362,6 +360,7 @@ public interface PageTransformer {
* Callback interface for responding to adapter changes.
*/
public interface OnAdapterChangeListener {
+
/**
* Called when the adapter for the given view pager has changed.
*
@@ -370,7 +369,7 @@ public interface OnAdapterChangeListener {
* @param newAdapter the newly set adapter
*/
void onAdapterChanged(@NonNull CustomViewPager viewPager,
- @Nullable PagerAdapter oldAdapter, @Nullable PagerAdapter newAdapter);
+ @Nullable PagerAdapter oldAdapter, @Nullable PagerAdapter newAdapter);
}
/**
@@ -387,6 +386,7 @@ void onAdapterChanged(@NonNull CustomViewPager viewPager,
@Target(ElementType.TYPE)
@Inherited
public @interface DecorView {
+
}
public CustomViewPager(Context context) {
@@ -432,7 +432,7 @@ void initViewPager() {
@Override
public WindowInsetsCompat onApplyWindowInsets(final View v,
- final WindowInsetsCompat originalInsets) {
+ final WindowInsetsCompat originalInsets) {
// First let the ViewPager itself try and consume them...
final WindowInsetsCompat applied =
ViewCompat.onApplyWindowInsets(v, originalInsets);
@@ -616,7 +616,7 @@ public void setCurrentItem(int item) {
/**
* Set the currently selected page.
*
- * @param item Item index to select
+ * @param item Item index to select
* @param smoothScroll True to smoothly scroll to the new item, false to transition immediately
*/
public void setCurrentItem(int item, boolean smoothScroll) {
@@ -673,7 +673,7 @@ void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int
}
private void scrollToItem(int item, boolean smoothScroll, int velocity,
- boolean dispatchSelected) {
+ boolean dispatchSelected) {
final ItemInfo curInfo = infoForPosition(item);
int destX = 0;
if (curInfo != null) {
@@ -701,7 +701,6 @@ private void scrollToItem(int item, boolean smoothScroll, int velocity,
* scrolled. See {@link OnPageChangeListener}.
*
* @param listener Listener to set
- *
* @deprecated Use {@link #addOnPageChangeListener(OnPageChangeListener)}
* and {@link #removeOnPageChangeListener(OnPageChangeListener)} instead.
*/
@@ -754,11 +753,12 @@ public void clearOnPageChangeListeners() {
* transformations to each page, overriding the default sliding look and feel.
*
* Note: Prior to Android 3.0 the property animation APIs did not exist.
- * As a result, setting a PageTransformer prior to Android 3.0 (API 11) will have no effect.
+ * As a result, setting a PageTransformer prior to Android 3.0 (API 11) will have no
+ * effect.
*
* @param reverseDrawingOrder true if the supplied PageTransformer requires page views
* to be drawn from last to first instead of first to last.
- * @param transformer PageTransformer that will modify each page's animation properties
+ * @param transformer PageTransformer that will modify each page's animation properties
*/
public void setPageTransformer(boolean reverseDrawingOrder, PageTransformer transformer) {
if (Build.VERSION.SDK_INT >= 11) {
@@ -771,7 +771,9 @@ public void setPageTransformer(boolean reverseDrawingOrder, PageTransformer tran
} else {
mDrawingOrder = DRAW_ORDER_DEFAULT;
}
- if (needsPopulate) populate();
+ if (needsPopulate) {
+ populate();
+ }
}
}
@@ -780,7 +782,7 @@ void setChildrenDrawingOrderEnabledCompat(boolean enable) {
if (mSetChildrenDrawingOrderEnabled == null) {
try {
mSetChildrenDrawingOrderEnabled = ViewGroup.class.getDeclaredMethod(
- "setChildrenDrawingOrderEnabled", new Class[] { Boolean.TYPE });
+ "setChildrenDrawingOrderEnabled", new Class[]{Boolean.TYPE});
} catch (NoSuchMethodException e) {
Log.e(TAG, "Can't find setChildrenDrawingOrderEnabled", e);
}
@@ -887,7 +889,9 @@ public int getPageMargin() {
*/
public void setPageMarginDrawable(Drawable d) {
mMarginDrawable = d;
- if (d != null) refreshDrawableState();
+ if (d != null) {
+ refreshDrawableState();
+ }
setWillNotDraw(d == null);
invalidate();
}
@@ -938,8 +942,8 @@ public void smoothScrollTo(int x, int y) {
/**
* Like {@link View#scrollBy}, but scroll smoothly instead of immediately.
*
- * @param x the number of pixels to scroll by on the X axis
- * @param y the number of pixels to scroll by on the Y axis
+ * @param x the number of pixels to scroll by on the X axis
+ * @param y the number of pixels to scroll by on the Y axis
* @param velocity the velocity associated with a fling, if applicable. (0 otherwise)
*/
void smoothScrollTo(int x, int y, int velocity) {
@@ -1105,7 +1109,9 @@ void populate(int newCurrentItem) {
// fling to a new position until we have finished the scroll to
// that position, avoiding glitches from happening at that point.
if (mPopulatePending) {
- if (DEBUG) Log.i(TAG, "populate is pending, skipping for now...");
+ if (DEBUG) {
+ Log.i(TAG, "populate is pending, skipping for now...");
+ }
sortChildDrawingOrder();
return;
}
@@ -1145,7 +1151,9 @@ void populate(int newCurrentItem) {
for (curIndex = 0; curIndex < mItems.size(); curIndex++) {
final ItemInfo ii = mItems.get(curIndex);
if (ii.position >= mCurItem) {
- if (ii.position == mCurItem) curItem = ii;
+ if (ii.position == mCurItem) {
+ curItem = ii;
+ }
break;
}
}
@@ -1303,7 +1311,7 @@ private void calculatePageOffsets(ItemInfo curItem, int curIndex, ItemInfo oldCu
ItemInfo ii = null;
float offset = oldCurInfo.offset + oldCurInfo.widthFactor + marginOffset;
for (int pos = oldCurPosition + 1;
- pos <= curItem.position && itemIndex < mItems.size(); pos++) {
+ pos <= curItem.position && itemIndex < mItems.size(); pos++) {
ii = mItems.get(itemIndex);
while (pos > ii.position && itemIndex < mItems.size() - 1) {
itemIndex++;
@@ -1323,7 +1331,7 @@ private void calculatePageOffsets(ItemInfo curItem, int curIndex, ItemInfo oldCu
ItemInfo ii = null;
float offset = oldCurInfo.offset;
for (int pos = oldCurPosition - 1;
- pos >= curItem.position && itemIndex >= 0; pos--) {
+ pos >= curItem.position && itemIndex >= 0; pos--) {
ii = mItems.get(itemIndex);
while (pos < ii.position && itemIndex > 0) {
itemIndex--;
@@ -1356,7 +1364,9 @@ private void calculatePageOffsets(ItemInfo curItem, int curIndex, ItemInfo oldCu
}
offset -= ii.widthFactor + marginOffset;
ii.offset = offset;
- if (ii.position == 0) mFirstOffset = offset;
+ if (ii.position == 0) {
+ mFirstOffset = offset;
+ }
}
offset = curItem.offset + curItem.widthFactor + marginOffset;
pos = curItem.position + 1;
@@ -1373,7 +1383,6 @@ private void calculatePageOffsets(ItemInfo curItem, int curIndex, ItemInfo oldCu
offset += ii.widthFactor + marginOffset;
}
- mNeedCalculatePageOffsets = false;
}
/**
@@ -1383,6 +1392,7 @@ private void calculatePageOffsets(ItemInfo curItem, int curIndex, ItemInfo oldCu
* contains that state.
*/
public static class SavedState extends AbsSavedState {
+
int position;
Parcelable adapterState;
ClassLoader loader;
@@ -1411,6 +1421,7 @@ public String toString() {
public SavedState createFromParcel(Parcel in, ClassLoader loader) {
return new SavedState(in, loader);
}
+
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
@@ -1606,8 +1617,10 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
}
}
- mChildWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY);
- mChildHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeightSize, MeasureSpec.EXACTLY);
+ int childWidthMeasureSpec = MeasureSpec
+ .makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY);
+ int childHeightMeasureSpec = MeasureSpec
+ .makeMeasureSpec(childHeightSize, MeasureSpec.EXACTLY);
// Make sure we have created all fragments that we need to have shown.
mInLayout = true;
@@ -1620,14 +1633,14 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
if (DEBUG) {
- Log.v(TAG, "Measuring #" + i + " " + child + ": " + mChildWidthMeasureSpec);
+ Log.v(TAG, "Measuring #" + i + " " + child + ": " + childWidthMeasureSpec);
}
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp == null || !lp.isDecor) {
final int widthSpec = MeasureSpec.makeMeasureSpec(
(int) (childWidthSize * lp.widthFactor), MeasureSpec.EXACTLY);
- child.measure(widthSpec, mChildHeightMeasureSpec);
+ child.measure(widthSpec, childHeightMeasureSpec);
}
}
}
@@ -1846,9 +1859,9 @@ private boolean pageScrolled(int xpos) {
* (e.g. super.onPageScrolled(position, offset, offsetPixels)) before onPageScrolled
* returns.
*
- * @param position Position index of the first page currently being displayed.
- * Page position+1 will be visible if positionOffset is nonzero.
- * @param offset Value from [0, 1) indicating the offset from the page at position.
+ * @param position Position index of the first page currently being displayed.
+ * Page position+1 will be visible if positionOffset is nonzero.
+ * @param offset Value from [0, 1) indicating the offset from the page at position.
* @param offsetPixels Value in pixels indicating the offset from position.
*/
@CallSuper
@@ -1863,7 +1876,9 @@ protected void onPageScrolled(int position, float offset, int offsetPixels) {
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
- if (!lp.isDecor) continue;
+ if (!lp.isDecor) {
+ continue;
+ }
final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
int childLeft = 0;
@@ -1902,7 +1917,9 @@ protected void onPageScrolled(int position, float offset, int offsetPixels) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
- if (lp.isDecor) continue;
+ if (lp.isDecor) {
+ continue;
+ }
final float transformPos = (float) (child.getLeft() - scrollX) / getClientWidth();
mPageTransformer.transformPage(child, transformPos);
}
@@ -2025,7 +2042,9 @@ public boolean onInterceptTouchEvent(MotionEvent ev) {
// Always take care of the touch gesture being complete.
if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
// Release the drag.
- if (DEBUG) Log.v(TAG, "Intercept done!");
+ if (DEBUG) {
+ Log.v(TAG, "Intercept done!");
+ }
resetTouch();
return false;
}
@@ -2034,11 +2053,15 @@ public boolean onInterceptTouchEvent(MotionEvent ev) {
// are dragging.
if (action != MotionEvent.ACTION_DOWN) {
if (mIsBeingDragged) {
- if (DEBUG) Log.v(TAG, "Intercept returning true!");
+ if (DEBUG) {
+ Log.v(TAG, "Intercept returning true!");
+ }
return true;
}
if (mIsUnableToDrag) {
- if (DEBUG) Log.v(TAG, "Intercept returning false!");
+ if (DEBUG) {
+ Log.v(TAG, "Intercept returning false!");
+ }
return false;
}
}
@@ -2066,7 +2089,9 @@ public boolean onInterceptTouchEvent(MotionEvent ev) {
final float xDiff = Math.abs(dx);
final float y = ev.getY(pointerIndex);
final float yDiff = Math.abs(y - mInitialMotionY);
- if (DEBUG) Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff);
+ if (DEBUG) {
+ Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff);
+ }
if (dx != 0 && !isGutterDrag(mLastMotionX, dx)
&& canScroll(this, false, (int) dx, (int) x, (int) y)) {
@@ -2077,7 +2102,9 @@ && canScroll(this, false, (int) dx, (int) x, (int) y)) {
return false;
}
if (xDiff > mTouchSlop && xDiff * 0.5f > yDiff) {
- if (DEBUG) Log.v(TAG, "Starting drag!");
+ if (DEBUG) {
+ Log.v(TAG, "Starting drag!");
+ }
mIsBeingDragged = true;
requestParentDisallowInterceptTouchEvent(true);
setScrollState(SCROLL_STATE_DRAGGING);
@@ -2090,7 +2117,9 @@ && canScroll(this, false, (int) dx, (int) x, (int) y)) {
// direction to be counted as a drag... abort
// any attempt to drag horizontally, to work correctly
// with children that have scrolling containers.
- if (DEBUG) Log.v(TAG, "Starting unable to drag!");
+ if (DEBUG) {
+ Log.v(TAG, "Starting unable to drag!");
+ }
mIsUnableToDrag = true;
}
if (mIsBeingDragged) {
@@ -2210,7 +2239,9 @@ public boolean onTouchEvent(MotionEvent ev) {
Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff);
}
if (xDiff > mTouchSlop && xDiff > yDiff) {
- if (DEBUG) Log.v(TAG, "Starting drag!");
+ if (DEBUG) {
+ Log.v(TAG, "Starting drag!");
+ }
mIsBeingDragged = true;
requestParentDisallowInterceptTouchEvent(true);
mLastMotionX = x - mInitialMotionX > 0 ? mInitialMotionX + mTouchSlop :
@@ -2346,7 +2377,7 @@ private boolean performDrag(float x) {
/**
* @return Info about the page at the current scroll position.
- * This can be synthetic for a missing middle page; the 'object' field can be null.
+ * This can be synthetic for a missing middle page; the 'object' field can be null.
*/
private ItemInfo infoForCurrentScrollPosition() {
final int width = getClientWidth();
@@ -2509,7 +2540,6 @@ protected void onDraw(Canvas canvas) {
* is already in progress, this method will return false.
*
* @return true if the fake drag began successfully, false if it could not be started.
- *
* @see #fakeDragBy(float)
* @see #endFakeDrag()
*/
@@ -2621,7 +2651,6 @@ public void fakeDragBy(float xOffset) {
* Returns true if a fake drag is in progress.
*
* @return true if currently in a fake drag, false otherwise.
- *
* @see #beginFakeDrag()
* @see #fakeDragBy(float)
* @see #endFakeDrag()
@@ -2675,7 +2704,7 @@ private void setScrollingCacheEnabled(boolean enabled) {
*
* @param direction Negative to check scrolling left, positive to check scrolling right.
* @return Whether this ViewPager can be scrolled in the specified direction. It will always
- * return false if the specified direction is 0.
+ * return false if the specified direction is 0.
*/
public boolean canScrollHorizontally(int direction) {
if (mAdapter == null) {
@@ -2696,12 +2725,12 @@ public boolean canScrollHorizontally(int direction) {
/**
* Tests scrollability within child views of v given a delta of dx.
*
- * @param v View to test for horizontal scrollability
+ * @param v View to test for horizontal scrollability
* @param checkV Whether the view v passed should itself be checked for scrollability (true),
* or just its children (false).
- * @param dx Delta scrolled in pixels
- * @param x X coordinate of the active touch point
- * @param y Y coordinate of the active touch point
+ * @param dx Delta scrolled in pixels
+ * @param x X coordinate of the active touch point
+ * @param y Y coordinate of the active touch point
* @return true if child views of v can be scrolled by delta of dx.
*/
protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
@@ -2781,7 +2810,7 @@ public boolean arrowScroll(int direction) {
} else if (currentFocused != null) {
boolean isChild = false;
for (ViewParent parent = currentFocused.getParent(); parent instanceof ViewGroup;
- parent = parent.getParent()) {
+ parent = parent.getParent()) {
if (parent == this) {
isChild = true;
break;
@@ -2792,7 +2821,7 @@ public boolean arrowScroll(int direction) {
final StringBuilder sb = new StringBuilder();
sb.append(currentFocused.getClass().getSimpleName());
for (ViewParent parent = currentFocused.getParent(); parent instanceof ViewGroup;
- parent = parent.getParent()) {
+ parent = parent.getParent()) {
sb.append(" => ").append(parent.getClass().getSimpleName());
}
Log.e(TAG, "arrowScroll tried to find focus based on non-child "
@@ -2948,7 +2977,7 @@ public void addTouchables(ArrayList views) {
*/
@Override
protected boolean onRequestFocusInDescendants(int direction,
- Rect previouslyFocusedRect) {
+ Rect previouslyFocusedRect) {
int index;
int increment;
int end;
@@ -3060,13 +3089,15 @@ public boolean performAccessibilityAction(View host, int action, Bundle args) {
setCurrentItem(mCurItem + 1);
return true;
}
- } return false;
+ }
+ return false;
case AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD: {
if (canScrollHorizontally(-1)) {
setCurrentItem(mCurItem - 1);
return true;
}
- } return false;
+ }
+ return false;
}
return false;
}
@@ -3077,10 +3108,12 @@ private boolean canScroll() {
}
private class PagerObserver extends DataSetObserver {
+
@Override
public void onChanged() {
dataSetChanged();
}
+
@Override
public void onInvalidated() {
dataSetChanged();
@@ -3092,6 +3125,7 @@ public void onInvalidated() {
* ViewPager.
*/
public static class LayoutParams extends ViewGroup.LayoutParams {
+
/**
* true if this view is a decoration on the pager itself and not
* a view supplied by the adapter.
@@ -3140,6 +3174,7 @@ public LayoutParams(Context context, AttributeSet attrs) {
}
static class ViewPositionComparator implements Comparator {
+
@Override
public int compare(View lhs, View rhs) {
final LayoutParams llp = (LayoutParams) lhs.getLayoutParams();
@@ -3150,4 +3185,13 @@ public int compare(View lhs, View rhs) {
return llp.position - rlp.position;
}
}
+
+ static class ItemInfo {
+
+ Object object;
+ int position;
+ boolean scrolling;
+ float widthFactor;
+ float offset;
+ }
}
\ No newline at end of file
diff --git a/material-intro-screen/src/main/res/anim/cycle_2.xml b/material-intro-screen/src/main/res/anim/mis_cycle_2.xml
similarity index 100%
rename from material-intro-screen/src/main/res/anim/cycle_2.xml
rename to material-intro-screen/src/main/res/anim/mis_cycle_2.xml
diff --git a/material-intro-screen/src/main/res/anim/fade_in.xml b/material-intro-screen/src/main/res/anim/mis_fade_in.xml
similarity index 100%
rename from material-intro-screen/src/main/res/anim/fade_in.xml
rename to material-intro-screen/src/main/res/anim/mis_fade_in.xml
diff --git a/material-intro-screen/src/main/res/anim/fade_out.xml b/material-intro-screen/src/main/res/anim/mis_fade_out.xml
similarity index 100%
rename from material-intro-screen/src/main/res/anim/fade_out.xml
rename to material-intro-screen/src/main/res/anim/mis_fade_out.xml
diff --git a/material-intro-screen/src/main/res/anim/shake_it.xml b/material-intro-screen/src/main/res/anim/mis_shake_it.xml
similarity index 80%
rename from material-intro-screen/src/main/res/anim/shake_it.xml
rename to material-intro-screen/src/main/res/anim/mis_shake_it.xml
index 12fc9f9..c4a07f5 100644
--- a/material-intro-screen/src/main/res/anim/shake_it.xml
+++ b/material-intro-screen/src/main/res/anim/mis_shake_it.xml
@@ -2,5 +2,5 @@
\ No newline at end of file
diff --git a/material-intro-screen/src/main/res/drawable-v21/button_background.xml b/material-intro-screen/src/main/res/drawable-v21/mis_button_background.xml
similarity index 100%
rename from material-intro-screen/src/main/res/drawable-v21/button_background.xml
rename to material-intro-screen/src/main/res/drawable-v21/mis_button_background.xml
diff --git a/material-intro-screen/src/main/res/drawable/button_background.xml b/material-intro-screen/src/main/res/drawable/mis_button_background.xml
similarity index 100%
rename from material-intro-screen/src/main/res/drawable/button_background.xml
rename to material-intro-screen/src/main/res/drawable/mis_button_background.xml
diff --git a/material-intro-screen/src/main/res/drawable/ic_finish.xml b/material-intro-screen/src/main/res/drawable/mis_ic_finish.xml
similarity index 100%
rename from material-intro-screen/src/main/res/drawable/ic_finish.xml
rename to material-intro-screen/src/main/res/drawable/mis_ic_finish.xml
diff --git a/material-intro-screen/src/main/res/drawable/ic_next.xml b/material-intro-screen/src/main/res/drawable/mis_ic_next.xml
similarity index 100%
rename from material-intro-screen/src/main/res/drawable/ic_next.xml
rename to material-intro-screen/src/main/res/drawable/mis_ic_next.xml
diff --git a/material-intro-screen/src/main/res/drawable/ic_previous.xml b/material-intro-screen/src/main/res/drawable/mis_ic_previous.xml
similarity index 100%
rename from material-intro-screen/src/main/res/drawable/ic_previous.xml
rename to material-intro-screen/src/main/res/drawable/mis_ic_previous.xml
diff --git a/material-intro-screen/src/main/res/drawable/ic_skip.xml b/material-intro-screen/src/main/res/drawable/mis_ic_skip.xml
similarity index 100%
rename from material-intro-screen/src/main/res/drawable/ic_skip.xml
rename to material-intro-screen/src/main/res/drawable/mis_ic_skip.xml
diff --git a/material-intro-screen/src/main/res/layout-land/fragment_slide.xml b/material-intro-screen/src/main/res/layout-land/mis_fragment_slide.xml
similarity index 94%
rename from material-intro-screen/src/main/res/layout-land/fragment_slide.xml
rename to material-intro-screen/src/main/res/layout-land/mis_fragment_slide.xml
index 98ee8d2..4e66dc0 100644
--- a/material-intro-screen/src/main/res/layout-land/fragment_slide.xml
+++ b/material-intro-screen/src/main/res/layout-land/mis_fragment_slide.xml
@@ -16,13 +16,13 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
- android:layout_marginRight="16dp"
android:layout_marginBottom="128dp"
- android:paddingTop="32dp"
+ android:layout_marginRight="16dp"
android:layout_weight="1"
android:adjustViewBounds="true"
+ android:paddingTop="32dp"
android:visibility="gone"
- app:layout_parallaxFactor="0.6"
+ app:mis_layout_parallaxFactor="0.6"
tools:src="@android:drawable/arrow_down_float"
tools:visibility="visible" />
@@ -39,7 +39,6 @@
android:layout_height="wrap_content"
android:gravity="center"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
- app:layout_parallaxFactor="0.5"
tools:text="Lorem ipsum" />
diff --git a/material-intro-screen/src/main/res/layout/empty_fragment_slide.xml b/material-intro-screen/src/main/res/layout/empty_fragment_slide.xml
deleted file mode 100644
index ca62b3a..0000000
--- a/material-intro-screen/src/main/res/layout/empty_fragment_slide.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/material-intro-screen/src/main/res/layout/activity_material_intro.xml b/material-intro-screen/src/main/res/layout/mis_activity_material_intro.xml
similarity index 79%
rename from material-intro-screen/src/main/res/layout/activity_material_intro.xml
rename to material-intro-screen/src/main/res/layout/mis_activity_material_intro.xml
index 0826b95..8af0cc1 100644
--- a/material-intro-screen/src/main/res/layout/activity_material_intro.xml
+++ b/material-intro-screen/src/main/res/layout/mis_activity_material_intro.xml
@@ -23,14 +23,14 @@
android:layout_gravity="bottom"
android:orientation="vertical"
android:paddingTop="32dp"
- app:layout_behavior="agency.tango.materialintroscreen.MoveUpBehaviour">
+ app:layout_behavior="agency.tango.materialintroscreen.behaviours.MoveUpBehaviour">
@@ -46,9 +46,9 @@
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginLeft="16dp"
- android:background="@drawable/button_background"
+ android:background="@drawable/mis_button_background"
android:padding="16dp"
- android:src="@drawable/ic_previous"
+ android:src="@drawable/mis_ic_previous"
android:visibility="invisible" />
+ app:mis_animationDuration="320"
+ app:mis_currentPageIndicatorColor="@android:color/white"
+ app:mis_dotDiameter="8dp"
+ app:mis_dotGap="8dp"
+ app:mis_pageIndicatorColor="@android:color/holo_red_light" />
+ android:src="@drawable/mis_ic_next" />
diff --git a/material-intro-screen/src/main/res/layout/fragment_slide.xml b/material-intro-screen/src/main/res/layout/mis_fragment_slide.xml
similarity index 93%
rename from material-intro-screen/src/main/res/layout/fragment_slide.xml
rename to material-intro-screen/src/main/res/layout/mis_fragment_slide.xml
index b8ed075..983ca3f 100644
--- a/material-intro-screen/src/main/res/layout/fragment_slide.xml
+++ b/material-intro-screen/src/main/res/layout/mis_fragment_slide.xml
@@ -26,7 +26,7 @@
android:layout_weight="1"
android:adjustViewBounds="true"
android:gravity="center"
- app:layout_parallaxFactor="0.6"
+ app:mis_layout_parallaxFactor="0.6"
tools:src="@android:drawable/sym_action_call" />
diff --git a/material-intro-screen/src/main/res/values-v21/styles.xml b/material-intro-screen/src/main/res/values-v21/styles.xml
index a5663b4..dce9a94 100644
--- a/material-intro-screen/src/main/res/values-v21/styles.xml
+++ b/material-intro-screen/src/main/res/values-v21/styles.xml
@@ -1,13 +1,13 @@
-
+
-
-
diff --git a/material-intro-screen/src/main/res/values/attrs.xml b/material-intro-screen/src/main/res/values/attrs.xml
index 4dcfc69..59921f4 100644
--- a/material-intro-screen/src/main/res/values/attrs.xml
+++ b/material-intro-screen/src/main/res/values/attrs.xml
@@ -1,13 +1,13 @@
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
\ No newline at end of file
diff --git a/material-intro-screen/src/main/res/values/colors.xml b/material-intro-screen/src/main/res/values/colors.xml
index 6a195f9..f77531b 100644
--- a/material-intro-screen/src/main/res/values/colors.xml
+++ b/material-intro-screen/src/main/res/values/colors.xml
@@ -1,5 +1,6 @@
- @android:color/transparent
-
+ @android:color/transparent
+ #3F51B5
+ #1A237E
\ No newline at end of file
diff --git a/material-intro-screen/src/main/res/values/dimens.xml b/material-intro-screen/src/main/res/values/dimens.xml
index a4d05b0..c178919 100644
--- a/material-intro-screen/src/main/res/values/dimens.xml
+++ b/material-intro-screen/src/main/res/values/dimens.xml
@@ -1,4 +1,4 @@
- 72dp
+ 72dp
\ No newline at end of file
diff --git a/material-intro-screen/src/main/res/values/ids.xml b/material-intro-screen/src/main/res/values/ids.xml
index 79ba769..dd7e099 100644
--- a/material-intro-screen/src/main/res/values/ids.xml
+++ b/material-intro-screen/src/main/res/values/ids.xml
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/material-intro-screen/src/main/res/values/strings.xml b/material-intro-screen/src/main/res/values/strings.xml
index b2480a8..a18bfc0 100644
--- a/material-intro-screen/src/main/res/values/strings.xml
+++ b/material-intro-screen/src/main/res/values/strings.xml
@@ -1,6 +1,6 @@
- material-intro-screen
- Grant permissions
- Please grant needed permissions
- Can\'t pass this slide.
+ material-intro-screen
+ Grant permissions
+ Please grant needed permissions
+ Can\'t pass this slide.
diff --git a/material-intro-screen/src/main/res/values/styles.xml b/material-intro-screen/src/main/res/values/styles.xml
index 13307cc..0addbdc 100644
--- a/material-intro-screen/src/main/res/values/styles.xml
+++ b/material-intro-screen/src/main/res/values/styles.xml
@@ -1,12 +1,12 @@
-
+
-
-
diff --git a/versions.gradle b/versions.gradle
index 4cc1138..f533d26 100644
--- a/versions.gradle
+++ b/versions.gradle
@@ -1 +1,6 @@
-ext.androidSupport = "25.0.1"
+ext.minSdkVersion = 16
+ext.targetSdkVersion = 26
+ext.compileSdkVersion = 26
+ext.buildToolsVersion = '26.0.2'
+ext.androidSupport = "26.1.0"
+