卡片联动效果
This commit is contained in:
@@ -1,178 +0,0 @@
|
||||
package com.yarolegovich.discretescrollview;
|
||||
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Created by yarolegovich on 28-Apr-17.
|
||||
*/
|
||||
|
||||
public class InfiniteScrollAdapter<T extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<T>
|
||||
implements DiscreteScrollLayoutManager.InitialPositionProvider {
|
||||
|
||||
private static final int CENTER = Integer.MAX_VALUE / 2;
|
||||
private static final int RESET_BOUND = 100;
|
||||
|
||||
public static <T extends RecyclerView.ViewHolder> InfiniteScrollAdapter<T> wrap(
|
||||
@NonNull RecyclerView.Adapter<T> adapter) {
|
||||
return new InfiniteScrollAdapter<>(adapter);
|
||||
}
|
||||
|
||||
private RecyclerView.Adapter<T> wrapped;
|
||||
private DiscreteScrollLayoutManager layoutManager;
|
||||
|
||||
public InfiniteScrollAdapter(@NonNull RecyclerView.Adapter<T> wrapped) {
|
||||
this.wrapped = wrapped;
|
||||
this.wrapped.registerAdapterDataObserver(new DataSetChangeDelegate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
|
||||
wrapped.onAttachedToRecyclerView(recyclerView);
|
||||
if (recyclerView instanceof DiscreteScrollView) {
|
||||
layoutManager = (DiscreteScrollLayoutManager) recyclerView.getLayoutManager();
|
||||
} else {
|
||||
String msg = recyclerView.getContext().getString(R.string.dsv_ex_msg_adapter_wrong_recycler);
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
|
||||
wrapped.onDetachedFromRecyclerView(recyclerView);
|
||||
layoutManager = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull T onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return wrapped.onCreateViewHolder(parent, viewType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull T holder, int position) {
|
||||
if (isResetRequired(position)) {
|
||||
int resetPosition = CENTER + mapPositionToReal(layoutManager.getCurrentPosition());
|
||||
setPosition(resetPosition);
|
||||
return;
|
||||
}
|
||||
wrapped.onBindViewHolder(holder, mapPositionToReal(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
return wrapped.getItemViewType(mapPositionToReal(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return isInfinite() ? Integer.MAX_VALUE : wrapped.getItemCount();
|
||||
}
|
||||
|
||||
public int getRealItemCount() {
|
||||
return wrapped.getItemCount();
|
||||
}
|
||||
|
||||
public int getRealCurrentPosition() {
|
||||
return getRealPosition(layoutManager.getCurrentPosition());
|
||||
}
|
||||
|
||||
public int getRealPosition(int position) {
|
||||
return mapPositionToReal(position);
|
||||
}
|
||||
|
||||
public int getClosestPosition(int position) {
|
||||
ensureValidPosition(position);
|
||||
int adapterCurrent = layoutManager.getCurrentPosition();
|
||||
int current = mapPositionToReal(adapterCurrent);
|
||||
if (position == current) {
|
||||
return adapterCurrent;
|
||||
}
|
||||
int delta = position - current;
|
||||
int target = adapterCurrent + delta;
|
||||
int wraparoundTarget = adapterCurrent + (position > current ?
|
||||
delta - wrapped.getItemCount() :
|
||||
wrapped.getItemCount() + delta);
|
||||
int distance = Math.abs(adapterCurrent - target);
|
||||
int wraparoundDistance = Math.abs(adapterCurrent - wraparoundTarget);
|
||||
if (distance == wraparoundDistance) {
|
||||
//Scroll to the right feels more natural, so prefer it
|
||||
return target > adapterCurrent ? target : wraparoundTarget;
|
||||
} else {
|
||||
return distance < wraparoundDistance ? target : wraparoundTarget;
|
||||
}
|
||||
}
|
||||
|
||||
private int mapPositionToReal(int position) {
|
||||
if (position < CENTER) {
|
||||
int rem = (CENTER - position) % wrapped.getItemCount();
|
||||
return rem == 0 ? 0 : wrapped.getItemCount() - rem;
|
||||
} else {
|
||||
return (position - CENTER) % wrapped.getItemCount();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isResetRequired(int requestedPosition) {
|
||||
return isInfinite()
|
||||
&& (requestedPosition <= RESET_BOUND
|
||||
|| requestedPosition >= (Integer.MAX_VALUE - RESET_BOUND));
|
||||
}
|
||||
|
||||
private void ensureValidPosition(int position) {
|
||||
if (position >= wrapped.getItemCount()) {
|
||||
throw new IndexOutOfBoundsException(String.format(Locale.US,
|
||||
"requested position is outside adapter's bounds: position=%d, size=%d",
|
||||
position, wrapped.getItemCount()));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInfinite() {
|
||||
return wrapped.getItemCount() > 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInitialPosition() {
|
||||
return isInfinite() ? CENTER : 0;
|
||||
}
|
||||
|
||||
private void setPosition(int position) {
|
||||
layoutManager.scrollToPosition(position);
|
||||
}
|
||||
|
||||
//TODO: handle proper data set change notifications
|
||||
private class DataSetChangeDelegate extends RecyclerView.AdapterDataObserver {
|
||||
|
||||
@Override
|
||||
public void onChanged() {
|
||||
setPosition(getInitialPosition());
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemRangeRemoved(int positionStart, int itemCount) {
|
||||
onChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemRangeInserted(int positionStart, int itemCount) {
|
||||
onChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
|
||||
onChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemRangeChanged(int positionStart, int itemCount) {
|
||||
notifyItemRangeChanged(0, getItemCount());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
|
||||
notifyItemRangeChanged(0, getItemCount(), payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.alibaba.android.arouter.launcher.ARouter;
|
||||
import com.mogo.commons.mvp.MvpFragment;
|
||||
@@ -19,7 +20,6 @@ import com.mogo.service.cardmanager.IMogoCardChangedListener;
|
||||
import com.mogo.service.fragmentmanager.FragmentDescriptor;
|
||||
import com.mogo.service.fragmentmanager.IMogoFragmentManager;
|
||||
import com.mogo.service.module.IMogoModuleProvider;
|
||||
|
||||
import com.mogo.utils.logger.Logger;
|
||||
import com.yarolegovich.discretescrollview.DiscreteScrollView;
|
||||
import java.util.ArrayList;
|
||||
@@ -179,7 +179,13 @@ public class AppNavigatorFragment extends MvpFragment<AppNavigatorView, AppNavig
|
||||
|
||||
@Override
|
||||
public void onCurrentItemChanged(@Nullable RecyclerView.ViewHolder viewHolder, int i) {
|
||||
//AppServiceHandler.getMogoCardManager().invoke(i%CARD_SIZE,"");
|
||||
Logger.d(TAG, "onCurrentItemChanged--position--" + i % CARD_SIZE);
|
||||
int currentPosition = i % CARD_SIZE - 2;
|
||||
if (currentPosition < 0) {
|
||||
currentPosition += CARD_SIZE;
|
||||
}
|
||||
this.currentPosition=currentPosition;
|
||||
AppServiceHandler.getMogoCardManager().invoke(currentPosition, "");
|
||||
}
|
||||
|
||||
@Override public void onScrollStart(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
|
||||
@@ -196,15 +202,33 @@ public class AppNavigatorFragment extends MvpFragment<AppNavigatorView, AppNavig
|
||||
|
||||
}
|
||||
|
||||
private int currentPosition = 0;
|
||||
|
||||
@Override public void onSwitched(int position, String moduleName) {
|
||||
int index = (position - scroller.getCurrentItem() % CARD_SIZE + 2) % CARD_SIZE;
|
||||
int i = scroller.getCurrentItem() + index;
|
||||
//DiscreteScrollLayoutManager layoutManager =
|
||||
// (DiscreteScrollLayoutManager) scroller.getLayoutManager();
|
||||
//int index = (position - scroller.getCurrentItem() % CARD_SIZE + 2) % CARD_SIZE;
|
||||
//int i = scroller.getCurrentItem() + index;
|
||||
//LinearLayoutManager layoutManager =
|
||||
// (LinearLayoutManager) scroller.getLayoutManager();
|
||||
//
|
||||
//layoutManager.smoothScrollToPosition();
|
||||
|
||||
Logger.d(TAG, "position" + index + "scroll" + i);
|
||||
scroller.smoothScrollToPosition(i);
|
||||
int index = position - currentPosition;
|
||||
|
||||
if (index == 0) {
|
||||
return;
|
||||
}
|
||||
if (index < -2) {
|
||||
index = 1;
|
||||
} else if (index > 2) {
|
||||
index = -1;
|
||||
}
|
||||
//很奇怪,但是位置就是相差
|
||||
if (index == -1) {
|
||||
index = -3;
|
||||
}
|
||||
|
||||
Logger.d(TAG, "position--" + position + "index--" + index);
|
||||
scroller.smoothScrollToPosition(scroller.getCurrentItem() + index);
|
||||
currentPosition = position;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -14,6 +15,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.view.accessibility.AccessibilityEventCompat;
|
||||
import androidx.core.view.accessibility.AccessibilityRecordCompat;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.LinearSmoothScroller;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.yarolegovich.discretescrollview.transform.DiscreteScrollItemTransformer;
|
||||
@@ -23,7 +25,7 @@ import java.util.Locale;
|
||||
/**
|
||||
* Created by yarolegovich on 17.02.2017.
|
||||
*/
|
||||
class DiscreteScrollLayoutManager extends RecyclerView.LayoutManager {
|
||||
class DiscreteScrollLayoutManager extends LinearLayoutManager {
|
||||
|
||||
static final int NO_POSITION = -1;
|
||||
|
||||
@@ -79,6 +81,7 @@ class DiscreteScrollLayoutManager extends RecyclerView.LayoutManager {
|
||||
@NonNull Context c,
|
||||
@NonNull ScrollStateListener scrollStateListener,
|
||||
@NonNull DSVOrientation orientation) {
|
||||
super(c);
|
||||
this.context = c;
|
||||
this.timeForItemSettle = DEFAULT_TIME_FOR_ITEM_SETTLE;
|
||||
this.pendingPosition = NO_POSITION;
|
||||
@@ -355,18 +358,39 @@ class DiscreteScrollLayoutManager extends RecyclerView.LayoutManager {
|
||||
recyclerViewProxy.requestLayout();
|
||||
}
|
||||
|
||||
//@Override
|
||||
//public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
|
||||
// if (currentPosition == position || pendingPosition != NO_POSITION) {
|
||||
// return;
|
||||
// }
|
||||
// checkTargetPosition(state, position);
|
||||
// if (currentPosition == NO_POSITION) {
|
||||
// //Layout not happened yet
|
||||
// currentPosition = position;
|
||||
// } else {
|
||||
// startSmoothPendingScroll(position);
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
@Override
|
||||
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
|
||||
if (currentPosition == position || pendingPosition != NO_POSITION) {
|
||||
return;
|
||||
}
|
||||
checkTargetPosition(state, position);
|
||||
if (currentPosition == NO_POSITION) {
|
||||
//Layout not happened yet
|
||||
currentPosition = position;
|
||||
} else {
|
||||
startSmoothPendingScroll(position);
|
||||
}
|
||||
LinearSmoothScroller smoothScroller =
|
||||
new LinearSmoothScroller(recyclerView.getContext()) {
|
||||
@Override
|
||||
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
|
||||
// 返回:滑过1px时经历的时间(ms)。
|
||||
return 150f / displayMetrics.densityDpi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) {
|
||||
return boxStart - viewStart;
|
||||
}
|
||||
};
|
||||
|
||||
smoothScroller.setTargetPosition(position);
|
||||
startSmoothScroll(smoothScroller);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -512,6 +536,9 @@ class DiscreteScrollLayoutManager extends RecyclerView.LayoutManager {
|
||||
startSmoothPendingScroll();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isAutoMeasureEnabled() {
|
||||
return true;
|
||||
|
||||
@@ -447,6 +447,8 @@ public class MainActivity extends MvpActivity< MainView, MainPresenter > impleme
|
||||
}
|
||||
|
||||
@Override public void onSwitched(int position, String moduleName) {
|
||||
mCardsContainer.setCurrentItem( position );
|
||||
//int index= (position+mCardModulesAdapter.getCount())/mCardModulesAdapter.getCount();
|
||||
Logger.d(TAG,"onSwitched==="+position);
|
||||
mCardsContainer.setCurrentItem( position ,position!=0&&position!=mCardModulesAdapter.getCount()-1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user