Skip to content

Commit

Permalink
Add navigation interface to make slide navigation consistent between …
Browse files Browse the repository at this point in the history
…IntroActivity and SlideFragment (fix #155, fix #156, fix #166), fix #162
  • Loading branch information
heinrichreimer committed Mar 21, 2017
1 parent dbae320 commit 8757d41
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
import java.util.List;

@SuppressLint("Registered")
public class IntroActivity extends AppCompatActivity {
public class IntroActivity extends AppCompatActivity implements IntroNavigation {
private static final String KEY_CURRENT_ITEM =
"com.heinrichreimersoftware.materialintro.app.IntroActivity.KEY_CURRENT_ITEM";
private static final String KEY_FULLSCREEN =
Expand Down Expand Up @@ -366,60 +366,102 @@ private long calculateScrollDuration(int distance) {
return Math.round(pageScrollDuration * (distance + Math.sqrt(distance)) / 2);
}

public void nextSlide() {
int currentItem = pager.getCurrentItem();
if (currentItem > adapter.getCount() - 1) finishIfNeeded();
@Override
public boolean goToSlide(int position) {
int lastPosition = pager.getCurrentItem();

if (canGoForward(currentItem, true)) {
smoothScrollPagerTo(++currentItem);
if (lastPosition >= adapter.getCount()) {
finishIfNeeded();
}

int newPosition = lastPosition;

position = Math.max(0, Math.min(position, getCount()));

if (position > lastPosition) {
// Go forward
while (newPosition < position && canGoForward(newPosition, true)) {
newPosition++;
}
} else if (position < lastPosition) {
// Go backward
while (newPosition > position && canGoBackward(newPosition, true)) {
newPosition--;
}
}
else {
AnimUtils.applyShakeAnimation(this, buttonNext);
// Noting to do here
return true;
}

boolean blocked = false;
if (newPosition != position) {
// Could not go the complete way to the given position.
blocked = true;

if (position > lastPosition) {
AnimUtils.applyShakeAnimation(this, buttonNext);
} else if (position < lastPosition) {
AnimUtils.applyShakeAnimation(this, buttonBack);
}
}

// Scroll to new position
smoothScrollPagerTo(newPosition);

return !blocked;
}

@Override
public boolean nextSlide() {
int currentItem = pager.getCurrentItem();
return goToSlide(currentItem + 1);
}

private int nextSlideAuto() {
int endPosition = pager.getCurrentItem();
int lastPosition = pager.getCurrentItem();
int count = getCount();

if (count == 1) {
return 0;
}
else if (pager.getCurrentItem() >= count - 1) {
while (endPosition >= 0 && canGoBackward(endPosition, true)) {
endPosition--;
while (lastPosition >= 0 && canGoBackward(lastPosition, true)) {
lastPosition--;
}
if (autoplayCounter > 0)
autoplayCounter--;
}
else if (canGoForward(endPosition, true)) {
endPosition++;
} else if (canGoForward(lastPosition, true)) {
lastPosition++;
}

int distance = Math.abs(endPosition - pager.getCurrentItem());
int distance = Math.abs(lastPosition - pager.getCurrentItem());

if (endPosition == pager.getCurrentItem())
if (lastPosition == pager.getCurrentItem())
return 0;

smoothScrollPagerTo(endPosition);
smoothScrollPagerTo(lastPosition);

if (autoplayCounter == 0)
return 0;
return distance;

}

public void previousSlide() {
@Override
public boolean previousSlide() {
int currentItem = pager.getCurrentItem();
if (currentItem <= 0) return;
return goToSlide(currentItem - 1);
}

if (canGoBackward(currentItem, true)) {
smoothScrollPagerTo(--currentItem);
}
else {
AnimUtils.applyShakeAnimation(this, buttonBack);
@Override
public boolean goToLastSlide() {
return goToSlide(getCount() - 1);
}

}
@Override
public boolean goToFirstSlide() {
return goToSlide(0);
}

private void performButtonBackPress() {
Expand All @@ -436,8 +478,12 @@ private void performButtonBackPress() {
}

private boolean canGoForward(int position, boolean notifyListeners) {
if (position >= getCount())
if (position >= getCount()) {
return false;
}
if (position <= 0) {
return true;
}

if (buttonNextFunction == BUTTON_NEXT_FUNCTION_NEXT && position >= getCount() - 1)
//Block finishing when button "next" function is not "finish".
Expand All @@ -454,8 +500,12 @@ private boolean canGoForward(int position, boolean notifyListeners) {
}

private boolean canGoBackward(int position, boolean notifyListeners) {
if (position <= 0)
if (position <= 0) {
return false;
}
if (position >= getCount()) {
return true;
}

boolean canGoBackward = (navigationPolicy == null || navigationPolicy.canGoBackward(position)) &&
getSlide(position).canGoBackward();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.heinrichreimersoftware.materialintro.app;

interface IntroNavigation {
/**
* Tries to go to the given position and will stop when {@code canGoForward()} or
* {@code canGoBackward()} returns {@code false}.
*
* @param position The position the pager should go to.
* @return {@code true} if the pager was able to go the complete way to the given position,
* {@code false} otherwise.
*/
boolean goToSlide(int position);

/**
* Tries to go to the next slide if {@code canGoForward()} returns {@code true}.
*
* @return {@code true} if the pager was able to go to the next slide, {@code false} otherwise.
*/
boolean nextSlide();


/**
* Tries to go to the previous slide if {@code canGoForward()} returns {@code true}.
*
* @return {@code true} if the pager was able to go to the previous slide, {@code false}
* otherwise.
*/
boolean previousSlide();

/**
* Tries to go to the last slide and will stop when {@code canGoForward()} returns
* {@code false}.
*
* @return {@code true} if the pager was able to go the complete way to the last slide,
* {@code false} otherwise.
*/
boolean goToLastSlide();

/**
* Tries to go to the first slide and will stop when {@code canGoBackward()} returns
* {@code false}.
*
* @return {@code true} if the pager was able to go the complete way to the first slide,
* {@code false} otherwise.
*/
boolean goToFirstSlide();
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import android.support.v4.app.Fragment;
import android.view.View;

public class SlideFragment extends Fragment {
public class SlideFragment extends Fragment implements IntroNavigation {

public boolean canGoForward() {
return true;
Expand Down Expand Up @@ -33,12 +33,29 @@ public void removeOnNavigationBlockedListener(OnNavigationBlockedListener listen
getIntroActivity().removeOnNavigationBlockedListener(listener);
}

protected void nextSlide() {
getIntroActivity().nextSlide();
@Override
public boolean goToSlide(int position) {
return getIntroActivity().goToSlide(position);
}

protected void previousSlide() {
getIntroActivity().previousSlide();
@Override
public boolean nextSlide() {
return getIntroActivity().nextSlide();
}

@Override
public boolean previousSlide() {
return getIntroActivity().previousSlide();
}

@Override
public boolean goToLastSlide() {
return getIntroActivity().goToLastSlide();
}

@Override
public boolean goToFirstSlide() {
return getIntroActivity().goToFirstSlide();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,9 @@ public Object instantiateItem(ViewGroup container, int position) {
//Load old fragment from fragment manager
((RestorableSlide) slide).setFragment(instantiatedFragment);
data.set(position, slide);
if (instantiatedFragment instanceof SlideFragment)
if (instantiatedFragment instanceof SlideFragment && instantiatedFragment.isAdded()) {
((SlideFragment) instantiatedFragment).updateNavigation();
}
}
return instantiatedFragment;
}
Expand Down

0 comments on commit 8757d41

Please sign in to comment.