Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add feature to specify swipeable methods #226

Merged
merged 10 commits into from
Mar 31, 2019
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
- [Max Degree](#max-degree)
- [Swipe Direction](#swipe-direction)
- [Swipe Restriction](#swipe-restriction)
- [Swipeable Method](#swipeable-method)
- [Public Interfaces](#public-interfaces)
- [Callbacks](#callbacks)
- [Migration Guide](#migration-guide)
Expand Down Expand Up @@ -239,6 +240,19 @@ CardStackLayoutManager.setCanScrollHorizontal(true);
CardStackLayoutManager.setCanScrollVertical(true);
```

## Swipeable Method

| Default | Value | Sample |
| :----: | :----: | :----: |
| ✅ | AutomaticAndManual | ![SwipeableMethod-AutomaticAndManual](https://github.com/yuyakaido/images/blob/master/CardStackView/sample-swipeable-method-automatic-and-manual.gif) |
| | Automatic | ![SwipwableMethod-Automatic](https://github.com/yuyakaido/images/blob/master/CardStackView/sample-swipeable-method-automatic.gif) |
| | Manual | ![SwipwableMethod-Manual](https://github.com/yuyakaido/images/blob/master/CardStackView/sample-swipeable-method-manual.gif) |
| | None | ![SwipwableMethod-None](https://github.com/yuyakaido/images/blob/master/CardStackView/sample-swipeable-method-none.gif) |

```java
CardStackLayoutManager.setSwipeableMethod(SwipeableMethod.AutomaticAndManual)
```

# Public Interfaces

## Basic usages
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public void rewind() {

private void initialize() {
new CardStackSnapHelper().attachToRecyclerView(this);
setOverScrollMode(RecyclerView.OVER_SCROLL_NEVER);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.yuyakaido.android.cardstackview;

public enum SwipeableMethod {
AutomaticAndManual,
Automatic,
Manual,
None;

boolean canSwipe() {
return canSwipeAutomatically() || canSwipeManually();
}

boolean canSwipeAutomatically() {
return this == AutomaticAndManual || this == Automatic;
}

boolean canSwipeManually() {
return this == AutomaticAndManual || this == Manual;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.yuyakaido.android.cardstackview.RewindAnimationSetting;
import com.yuyakaido.android.cardstackview.StackFrom;
import com.yuyakaido.android.cardstackview.SwipeAnimationSetting;
import com.yuyakaido.android.cardstackview.SwipeableMethod;

import java.util.List;

Expand All @@ -17,6 +18,7 @@ public class CardStackSetting {
public List<Direction> directions = Direction.HORIZONTAL;
public boolean canScrollHorizontal = true;
public boolean canScrollVertical = true;
public SwipeableMethod swipeableMethod = SwipeableMethod.AutomaticAndManual;
public SwipeAnimationSetting swipeAnimationSetting = new SwipeAnimationSetting.Builder().build();
public RewindAnimationSetting rewindAnimationSetting = new RewindAnimationSetting.Builder().build();
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.yuyakaido.android.cardstackview.internal;

import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.View;

Expand Down Expand Up @@ -28,13 +29,17 @@ public CardStackSmoothScroller(
}

@Override
protected void onSeekTargetStep(int dx, int dy, RecyclerView.State state, Action action) {
protected void onSeekTargetStep(
int dx,
int dy,
@NonNull RecyclerView.State state,
@NonNull Action action
) {
if (type == ScrollType.AutomaticRewind) {
manager.removeAllViews();
// ■ 概要
// ここでViewのRemoveを行わないとRewindが無限ループに陥ってしまう
// ■ 再現手順
// 1. 上記処理をコメントアウト
// 1. `manager.removeAllViews();`をコメントアウト
// 2. AutomaticSwipeを1度実行する
// 3. AutomaticRewindを1度実行する
// 4. AutomaticSwipeを1度実行する
Expand All @@ -46,6 +51,7 @@ protected void onSeekTargetStep(int dx, int dy, RecyclerView.State state, Action
// ■ 副作用
// ViewのRemoveを行っているため、表示対象となっているViewの再生成が実行されてしまう
// これによってパフォーマンス上の問題が発生する可能性がある
manager.removeAllViews();
RewindAnimationSetting setting = manager.getCardStackSetting().rewindAnimationSetting;
action.update(
-getDx(setting),
Expand All @@ -57,7 +63,11 @@ protected void onSeekTargetStep(int dx, int dy, RecyclerView.State state, Action
}

@Override
protected void onTargetFound(View targetView, RecyclerView.State state, Action action) {
protected void onTargetFound(
@NonNull View targetView,
@NonNull RecyclerView.State state,
@NonNull Action action
) {
int x = (int) targetView.getTranslationX();
int y = (int) targetView.getTranslationY();
AnimationSetting setting;
Expand Down Expand Up @@ -109,14 +119,14 @@ protected void onStart() {
CardStackState state = manager.getCardStackState();
switch (type) {
case AutomaticSwipe:
state.next(CardStackState.Status.PrepareSwipeAnimation);
state.next(CardStackState.Status.AutomaticSwipeAnimating);
listener.onCardDisappeared(manager.getTopView(), manager.getTopPosition());
break;
case AutomaticRewind:
state.next(CardStackState.Status.RewindAnimating);
break;
case ManualSwipe:
state.next(CardStackState.Status.PrepareSwipeAnimation);
state.next(CardStackState.Status.ManualSwipeAnimating);
listener.onCardDisappeared(manager.getTopView(), manager.getTopPosition());
break;
case ManualCancel:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public int[] calculateDistanceToFinalSnap(
if (setting.swipeThreshold < horizontal || setting.swipeThreshold < vertical) {
CardStackState state = manager.getCardStackState();
if (setting.directions.contains(state.getDirection())) {
state.targetPosition = state.topPosition + 1;
CardStackSmoothScroller scroller = new CardStackSmoothScroller(CardStackSmoothScroller.ScrollType.ManualSwipe, manager);
scroller.setTargetPosition(manager.getTopPosition());
manager.startSmoothScroll(scroller);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,36 @@ public class CardStackState {
public float proportion = 0.0f;

public enum Status {
Idle, Dragging, RewindAnimating, PrepareSwipeAnimation, SwipeAnimating
Idle,
Dragging,
RewindAnimating,
AutomaticSwipeAnimating,
AutomaticSwipeAnimated,
ManualSwipeAnimating,
ManualSwipeAnimated;

public boolean isBusy() {
return this != Idle;
}

public boolean isDragging() {
return this == Dragging;
}

public boolean isSwipeAnimating() {
return this == ManualSwipeAnimating || this == AutomaticSwipeAnimating;
}

public Status toAnimatedStatus() {
switch (this) {
case ManualSwipeAnimating:
return ManualSwipeAnimated;
case AutomaticSwipeAnimating:
return AutomaticSwipeAnimated;
default:
return Idle;
}
}
}

public void next(Status state) {
Expand Down Expand Up @@ -50,4 +79,31 @@ public float getRatio() {
return Math.min(ratio, 1.0f);
}

public boolean isSwipeCompleted() {
if (status.isSwipeAnimating()) {
if (topPosition < targetPosition) {
if (width < Math.abs(dx) || height < Math.abs(dy)) {
return true;
}
}
}
return false;
}

public boolean canScrollToPosition(int position, int itemCount) {
if (position == topPosition) {
return false;
}
if (position < 0) {
return false;
}
if (itemCount < position) {
return false;
}
if (status.isBusy()) {
return false;
}
return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ class MainActivity : AppCompatActivity(), CardStackListener {
manager.setDirections(Direction.HORIZONTAL)
manager.setCanScrollHorizontal(true)
manager.setCanScrollVertical(true)
manager.setSwipeableMethod(SwipeableMethod.AutomaticAndManual)
cardStackView.layoutManager = manager
cardStackView.adapter = adapter
cardStackView.itemAnimator.apply {
Expand Down