Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
janheinrichmerker committed Mar 21, 2017
1 parent 8757d41 commit 5db130c
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 93 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@
import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
Expand Down Expand Up @@ -76,6 +74,8 @@ public class IntroActivity extends AppCompatActivity implements IntroNavigation
private static final String KEY_BUTTON_CTA_VISIBLE =
"com.heinrichreimersoftware.materialintro.app.IntroActivity.KEY_BUTTON_CTA_VISIBLE";

private boolean activityCreated = false;

//Settings constants
@IntDef({BUTTON_NEXT_FUNCTION_NEXT, BUTTON_NEXT_FUNCTION_NEXT_FINISH})
@Retention(RetentionPolicy.SOURCE)
Expand Down Expand Up @@ -144,8 +144,6 @@ public class IntroActivity extends AppCompatActivity implements IntroNavigation
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

lockOrientation();

pageScrollInterpolator = AnimationUtils.loadInterpolator(this, android.R.interpolator.accelerate_decelerate);
pageScrollDuration = getResources().getInteger(android.R.integer.config_shortAnimTime);

Expand Down Expand Up @@ -181,6 +179,8 @@ protected void onCreate(Bundle savedInstanceState) {
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
activityCreated = true;

updateTaskDescription();
updateButtonNextDrawable();
updateButtonBackDrawable();
Expand Down Expand Up @@ -242,10 +242,11 @@ public Intent onSendActivityResult(int result) {

@Override
protected void onDestroy() {
if (isAutoplaying())
if (isAutoplaying()) {
cancelAutoplay();
}

unlockOrientation();
activityCreated = false;
super.onDestroy();
}

Expand Down Expand Up @@ -466,12 +467,7 @@ public boolean goToFirstSlide() {

private void performButtonBackPress() {
if (buttonBackFunction == BUTTON_BACK_FUNCTION_SKIP) {
int count = getCount();
int endPosition = pager.getCurrentItem();
while (endPosition < count && canGoForward(endPosition, true)) {
endPosition++;
}
smoothScrollPagerTo(endPosition);
goToSlide(getCount());
} else if (buttonBackFunction == BUTTON_BACK_FUNCTION_BACK) {
previousSlide();
}
Expand Down Expand Up @@ -941,26 +937,6 @@ private void updateButtonBackDrawable() {
}
}

private void lockOrientation() {
int orientation;
int rotation = getResources().getConfiguration().orientation;
switch (rotation) {
case Configuration.ORIENTATION_LANDSCAPE:
orientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
break;
case Configuration.ORIENTATION_PORTRAIT:
default:
orientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;
break;
}

setRequestedOrientation(orientation);
}

private void unlockOrientation() {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}

@SuppressWarnings("unused")
public void autoplay(@IntRange(from = 1) long delay, @IntRange(from = -1) int repeatCount) {
autoplayCounter = repeatCount;
Expand Down Expand Up @@ -1399,12 +1375,18 @@ public void setPageTransformer(boolean reverseDrawingOrder, ViewPager.PageTransf
}

public void notifyDataSetChanged() {
if (!activityCreated) {
// Don't notify any listener until the activity is created
return;
}

int position = this.position;
pager.setAdapter(adapter);
pager.setCurrentItem(position);

if (finishIfNeeded())
if (finishIfNeeded()) {
return;
}

updateTaskDescription();
updateButtonBackDrawable();
Expand All @@ -1419,8 +1401,9 @@ public void onPageScrolled(int position, float positionOffset, int positionOffse
IntroActivity.this.position = (int) Math.floor(position + positionOffset);
IntroActivity.this.positionOffset = (((position + positionOffset) % 1) + 1) % 1;

if (finishIfNeeded())
if (finishIfNeeded()) {
return;
}

//Lock while scrolling a slide near its edges to lock (uncommon) multiple page swipes
if (Math.abs(positionOffset) < 0.1f) {
Expand All @@ -1442,12 +1425,7 @@ public void onPageSelected(int position) {
private class ButtonCtaClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
int count = getCount();
int endPosition = pager.getCurrentItem();
while (endPosition < count && canGoForward(endPosition, true)) {
endPosition++;
}
smoothScrollPagerTo(endPosition);
goToSlide(getCount());
}
}
}
Original file line number Diff line number Diff line change
@@ -1,35 +1,31 @@
package com.heinrichreimersoftware.materialintro.view;

import android.content.Context;
import android.support.annotation.IntDef;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

public class SwipeBlockableViewPager extends ViewPager {
@IntDef({SWIPE_DIRECTION_LEFT, SWIPE_DIRECTION_NONE, SWIPE_DIRECTION_RIGHT})
@Retention(RetentionPolicy.SOURCE)
private @interface SwipeDirection {
}

private static final int SWIPE_DIRECTION_LEFT = 1;

private static final int SWIPE_DIRECTION_NONE = 0;
private static final int SWIPE_LOCK_THRESHOLD = 0;
private static final int SWIPE_UNLOCK_THRESHOLD = 0;

private static final int SWIPE_DIRECTION_RIGHT = -1;
private static final String STATE_SUPER = "SUPER";
private static final String STATE_SWIPE_RIGHT_ENABLED = "SWIPE_RIGHT_ENABLED";
private static final String STATE_SWIPE_LEFT_ENABLED = "SWIPE_LEFT_ENABLED";

private static final int SWIPE_THRESHOLD = 0;
private static final int INVALID_POINTER_ID = -1;

private float initialX;
private int activePointerId = INVALID_POINTER_ID;
private float lastTouchX;

private boolean swipeRightEnabled = true;

private boolean swipeLeftEnabled = true;

private boolean locked = false;
private boolean lockedLeft = false;
private boolean lockedRight = false;

public SwipeBlockableViewPager(Context context) {
super(context);
Expand Down Expand Up @@ -58,51 +54,105 @@ public boolean onInterceptTouchEvent(MotionEvent event) {
}

private boolean handleTouchEvent(MotionEvent event) {
if (getSwipeDirection(event) == SWIPE_DIRECTION_RIGHT && !swipeRightEnabled) {
if (!locked) {
locked = true;
updatePosition();
boolean allowTouch = false;
final int action = event.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
lastTouchX = event.getX();

// Save the ID of this pointer
activePointerId = event.getPointerId(0);

break;
}
return false;
}
else if (getSwipeDirection(event) == SWIPE_DIRECTION_LEFT && !swipeLeftEnabled) {
if (!locked) {
locked = true;
updatePosition();

case MotionEvent.ACTION_MOVE: {
// Find the index of the active pointer and fetch its position
final int pointerIndex = event.findPointerIndex(activePointerId);
final float x = event.getX(pointerIndex);

final float dx = x - lastTouchX;

if (dx > 0) {
// Swiped right
if (!swipeRightEnabled && Math.abs(dx) > SWIPE_LOCK_THRESHOLD) {
lockedRight = true;
}
if (!lockedRight) {
allowTouch = true;
if (Math.abs(dx) > SWIPE_UNLOCK_THRESHOLD) {
lockedLeft = false;
}
}
} else if (dx < 0) {
// Swiped left
if (!swipeLeftEnabled && Math.abs(dx) > SWIPE_LOCK_THRESHOLD) {
lockedLeft = true;
}
if (!lockedLeft) {
allowTouch = true;
if (Math.abs(dx) > SWIPE_UNLOCK_THRESHOLD) {
lockedRight = false;
}
}
}

lastTouchX = x;

invalidate();
break;
}
return false;
}
locked = false;
return true;
}

private void updatePosition() {
int currentItem = getCurrentItem();
scrollTo(currentItem * getWidth(), getScrollY());
setCurrentItem(currentItem);
}
case MotionEvent.ACTION_UP: {
activePointerId = INVALID_POINTER_ID;
lockedLeft = false;
lockedRight = false;
break;
}

case MotionEvent.ACTION_CANCEL: {
activePointerId = INVALID_POINTER_ID;
lockedLeft = false;
lockedRight = false;
break;
}

@SwipeDirection
public int getSwipeDirection(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
initialX = event.getX();
return SWIPE_DIRECTION_NONE;
case MotionEvent.ACTION_POINTER_UP: {
// Extract the index of the pointer that left the touch sensor
final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = event.getPointerId(pointerIndex);
if (pointerId == activePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
lastTouchX = event.getX(newPointerIndex);
activePointerId = event.getPointerId(newPointerIndex);
}
break;
}
}

if (event.getAction() == MotionEvent.ACTION_MOVE ||
event.getAction() == MotionEvent.ACTION_UP) {
float distanceX = event.getX() - initialX;
return (!lockedLeft && !lockedRight) || allowTouch;
}

if (SWIPE_THRESHOLD > Math.abs(distanceX)) {
return SWIPE_DIRECTION_NONE;
}
if (distanceX > 0) {
return SWIPE_DIRECTION_RIGHT;
} else if (distanceX < 0) {
return SWIPE_DIRECTION_LEFT;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
Bundle bundle = (Bundle) state;
swipeRightEnabled = bundle.getBoolean(STATE_SWIPE_RIGHT_ENABLED, true);
swipeLeftEnabled = bundle.getBoolean(STATE_SWIPE_LEFT_ENABLED, true);
state = bundle.getParcelable(STATE_SUPER);
}
super.onRestoreInstanceState(state);
}

return SWIPE_DIRECTION_NONE;
@Override
public Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle(4);
bundle.putParcelable(STATE_SUPER, super.onSaveInstanceState());
bundle.putBoolean(STATE_SWIPE_RIGHT_ENABLED, swipeRightEnabled);
bundle.putBoolean(STATE_SWIPE_LEFT_ENABLED, swipeLeftEnabled);
return bundle;
}
}

0 comments on commit 5db130c

Please sign in to comment.