diff --git a/OCH/mogo-och-bus/build.gradle b/OCH/mogo-och-bus/build.gradle
index eea68114f8..4de0719cb7 100644
--- a/OCH/mogo-och-bus/build.gradle
+++ b/OCH/mogo-och-bus/build.gradle
@@ -51,6 +51,7 @@ dependencies {
implementation rootProject.ext.dependencies.rxjava
implementation rootProject.ext.dependencies.rxandroid
+ compileOnly rootProject.ext.dependencies.recyclerviewadapterhelper
implementation project(":OCH:mogo-och-common-module")
diff --git a/OCH/mogo-och-bus/src/main/AndroidManifest.xml b/OCH/mogo-och-bus/src/main/AndroidManifest.xml
index 0e09e1a997..76856fd226 100644
--- a/OCH/mogo-och-bus/src/main/AndroidManifest.xml
+++ b/OCH/mogo-och-bus/src/main/AndroidManifest.xml
@@ -13,7 +13,7 @@
/>
+ android:screenOrientation="landscape" />
\ No newline at end of file
diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/bean/BusQueryLinesResponse.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/bean/BusQueryLinesResponse.java
index 99ead6ee0e..21dd901fc8 100644
--- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/bean/BusQueryLinesResponse.java
+++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/bean/BusQueryLinesResponse.java
@@ -19,5 +19,9 @@ public class BusQueryLinesResponse extends BaseData {
public String startSiteName;//始发站名称
public String endSiteName;//终点名称
+ public boolean open;
+ public boolean haveTask;
+
+ public List taskList;
}
}
diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/callback/IBusLinesCallback.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/callback/IBusLinesCallback.java
index b181736278..805a359757 100644
--- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/callback/IBusLinesCallback.java
+++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/callback/IBusLinesCallback.java
@@ -9,4 +9,5 @@ import com.mogo.och.bus.bean.BusQueryLinesResponse;
public interface IBusLinesCallback {
void onBusLinesChange(BusQueryLinesResponse lines);
void onChangeLineIdSuccess();
+ void onBusLineTasks(BusQueryLinesResponse o, int position);
}
diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/model/BusLineModel.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/model/BusLineModel.java
index 0d79156db8..54014f9f5a 100644
--- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/model/BusLineModel.java
+++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/model/BusLineModel.java
@@ -63,6 +63,36 @@ public class BusLineModel {
});
}
+ /**
+ * 通过线路id 查询线路排班表
+ * @param lineId
+ * @param position 位置
+ */
+ public void queryBusLineTasksById(int lineId, int position){
+ BusServiceManager.getInstance().queryBusLines(mContext, new IBusServiceCallback() {
+ @Override
+ public void onSuccess(BusQueryLinesResponse data) {
+ if (null == data && mBusLinesCallback != null) {
+ mBusLinesCallback.onBusLineTasks(null,position);
+ return;
+ }
+
+ if (mBusLinesCallback != null){
+ mBusLinesCallback.onBusLineTasks(data,position);
+ }
+ }
+
+ @Override
+ public void onFail(String failMsg) {
+ if (!NetworkUtils.isConnected(mContext)) {
+ ToastUtils.showShort("网络异常,请稍后重试");
+ }else {
+ ToastUtils.showShort("查询所有绑定路线失败:"+failMsg);
+ }
+ }
+ });
+ }
+
public void commitSwitchLineId(int lineId){
BusServiceManager.getInstance().switchLine(mContext,lineId, new IBusServiceCallback() {
@Override
diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusLinePresenter.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusLinePresenter.java
index bafd9f298b..5fb1485874 100644
--- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusLinePresenter.java
+++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/presenter/BusLinePresenter.java
@@ -61,6 +61,10 @@ public class BusLinePresenter extends Presenter implements IB
BusLineModel.getInstance().queryBusLines();
}
+ public void queryBusLineTasks(int lineId, int position){
+ BusLineModel.getInstance().queryBusLineTasksById(lineId,position);
+ }
+
public void commitSwitchLineId(int lineId){
BusLineModel.getInstance().commitSwitchLineId(lineId);
}
@@ -77,4 +81,10 @@ public class BusLinePresenter extends Presenter implements IB
public void onDestroy(@NonNull LifecycleOwner owner) {
super.onDestroy(owner);
}
+
+
+ @Override
+ public void onBusLineTasks(BusQueryLinesResponse o, int position) {
+ mView.onBusLineTasks(o,position);
+ }
}
diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/ui/BusSwitchLineActivity.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/ui/BusSwitchLineActivity.java
index 847071ba49..ded9038f14 100644
--- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/ui/BusSwitchLineActivity.java
+++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/ui/BusSwitchLineActivity.java
@@ -3,9 +3,7 @@ package com.mogo.och.bus.ui;
import android.content.Context;
import android.graphics.Point;
import android.os.Bundle;
-import android.text.TextUtils;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
@@ -21,12 +19,19 @@ import androidx.recyclerview.widget.RecyclerView;
import com.mogo.commons.mvp.MvpActivity;
import com.mogo.eagle.core.utilcode.util.ToastUtils;
+import com.mogo.module.common.view.SpacesItemDecoration;
import com.mogo.och.bus.R;
import com.mogo.och.bus.bean.BusQueryLinesResponse;
import com.mogo.och.bus.presenter.BusLinePresenter;
+import com.mogo.och.bus.ui.adapter.OpenItemAnimator;
+import com.mogo.och.bus.ui.adapter.SwitchLineAdapter;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import io.reactivex.Observable;
+import io.reactivex.disposables.Disposable;
/**
* @author: wangmingjun
@@ -43,6 +48,8 @@ public class BusSwitchLineActivity extends MvpActivity mData = new ArrayList<>();
private int mSelectLineId = -1;
+ private Disposable subscribe;
+
@Override
protected int getLayoutId() {
return R.layout.activity_bus_switch_line;
@@ -79,19 +86,19 @@ public class BusSwitchLineActivity extends MvpActivity position && !TextUtils.isEmpty(mData.get(position).startSiteName )
- && !TextUtils.isEmpty(mData.get(position).endSiteName)){
- mSelectLineId = mData.get(position).lineId;
- }else {
- mSelectLineId = -1;
- }
+ mAdapter.setOnLineItemClickListener((position) -> {
+ mPresenter.queryBusLineTasks(mData.get(position).lineId,position);
+ if(subscribe!=null&&!subscribe.isDisposed()){
+ subscribe.dispose();
}
+ subscribe = Observable.timer(3, TimeUnit.MINUTES).subscribe(aLong -> {
+ mPresenter.queryBusLineTasks(mData.get(position).lineId,position);
+ });
});
}
@@ -165,6 +172,24 @@ public class BusSwitchLineActivity extends MvpActivity();
+ }
+ if(o.data.size()!=result.taskList.size()) {// 不相等有变动 重新赋值
+ result.taskList.clear();
+ if (position % 3 != 0) {
+ result.taskList.addAll(o.data);
+ result.haveTask = false;
+ } else {
+ result.haveTask = true;
+ }
+ }
+ mAdapter.notifyItemChanged(position);
+ }
+
/**
* 有无数据UI显示
* @param b
@@ -195,105 +220,14 @@ public class BusSwitchLineActivity extends MvpActivity{
-
- private Context mContext;
- private List mData;
- // RecyclerView设置点击事件
- private LineItemClickListener mItemClickListener ;
- private int clickPos = -1;
-
- public SwitchLineAdapter(Context context, List data){
- mContext = context;
- mData = data;
+ if(subscribe!=null&&!subscribe.isDisposed()){
+ subscribe.dispose();
}
-
- @NonNull
- @Override
- public SwitchLineViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
- View view = LayoutInflater.from(mContext).inflate(R.layout.bus_switch_line_list_item
- ,parent,false);
- SwitchLineViewHolder viewHolder = new SwitchLineViewHolder(view);
- return viewHolder;
- }
-
- @Override
- public void onBindViewHolder(@NonNull SwitchLineViewHolder holder, int position) {
- BusQueryLinesResponse.Result line = mData.get(position);
- holder.lineName.setText(mContext.getString(R.string.bus_switch_line_name)+" "+line.name);
- holder.lineStartName.setText(mContext.getString(R.string.bus_line_start)+" "+line.startSiteName);
- holder.lineEndName.setText(mContext.getString(R.string.bus_line_end)+" "+line.endSiteName);
-
- //设置item点击事件
- holder.itemView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mItemClickListener != null){
- mItemClickListener.onItemClick(position);
- clickPos = position;
- notifyDataSetChanged();
- }
- }
- });
- //选中绑定
- if (clickPos > -1){
- if (clickPos == position){
- holder.selectIv.setImageResource(R.drawable.bus_selected_btn);
- }else {
- holder.selectIv.setImageResource(R.drawable.bus_unselect_btn);
- }
- }else {
- if (line.choose == 1){//1:绑定 2:未绑定 默认绑定
- if (mItemClickListener != null) {
- mItemClickListener.onItemClick(position);
- }
- holder.selectIv.setImageResource(R.drawable.bus_selected_btn);
- }else {
- holder.selectIv.setImageResource(R.drawable.bus_unselect_btn);
- }
- }
-
- }
-
- @Override
- public int getItemCount() {
- return mData.size();
- }
- public void setOnLineItemClickListener(LineItemClickListener itemClickListener){
- this.mItemClickListener = itemClickListener ;
-
- }
- }
-
- static class SwitchLineViewHolder extends RecyclerView.ViewHolder{
-
- private ImageView selectIv;
- private TextView lineName; //线路名称
- private TextView lineStartName; //起点
- private TextView lineEndName; //终点
-
- public SwitchLineViewHolder(@NonNull View itemView) {
- super(itemView);
- selectIv = itemView.findViewById(R.id.switch_line_item_select_iv);
- lineName = itemView.findViewById(R.id.switch_line_name);
- lineStartName = itemView.findViewById(R.id.switch_line_start_station);
- lineEndName = itemView.findViewById(R.id.switch_line_end_station);
- }
- }
-
- public interface LineItemClickListener {
- void onItemClick(int position) ;
}
}
diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/ui/BusSwitchLineView.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/ui/BusSwitchLineView.java
index febd6429b1..14309a101f 100644
--- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/ui/BusSwitchLineView.java
+++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/ui/BusSwitchLineView.java
@@ -11,5 +11,7 @@ public interface BusSwitchLineView extends IView {
void onBusLinesChange(BusQueryLinesResponse data);
void onChangeLineIdSuccess();
+
+ void onBusLineTasks(BusQueryLinesResponse o, int position);
}
diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/ui/adapter/OpenItemAnimator.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/ui/adapter/OpenItemAnimator.java
new file mode 100644
index 0000000000..1571739e3b
--- /dev/null
+++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/ui/adapter/OpenItemAnimator.java
@@ -0,0 +1,655 @@
+package com.mogo.och.bus.ui.adapter;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.view.View;
+import android.view.ViewPropertyAnimator;
+
+import androidx.annotation.NonNull;
+import androidx.core.view.ViewCompat;
+import androidx.recyclerview.widget.DefaultItemAnimator;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.SimpleItemAnimator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This implementation of {@link RecyclerView.ItemAnimator} provides basic
+ * animations on remove, add, and move events that happen to the items in
+ * a RecyclerView. RecyclerView uses a DefaultItemAnimator by default.
+ *
+ * @see RecyclerView#setItemAnimator(RecyclerView.ItemAnimator)
+ */
+public class OpenItemAnimator extends DefaultItemAnimator {
+ private static final boolean DEBUG = false;
+
+ private static TimeInterpolator sDefaultInterpolator;
+
+ private ArrayList mPendingRemovals = new ArrayList<>();
+ private ArrayList mPendingAdditions = new ArrayList<>();
+ private ArrayList mPendingMoves = new ArrayList<>();
+ private ArrayList mPendingChanges = new ArrayList<>();
+
+ ArrayList> mAdditionsList = new ArrayList<>();
+ ArrayList> mMovesList = new ArrayList<>();
+ ArrayList> mChangesList = new ArrayList<>();
+
+ ArrayList mAddAnimations = new ArrayList<>();
+ ArrayList mMoveAnimations = new ArrayList<>();
+ ArrayList mRemoveAnimations = new ArrayList<>();
+ ArrayList mChangeAnimations = new ArrayList<>();
+
+ private static class MoveInfo {
+ public RecyclerView.ViewHolder holder;
+ public int fromX, fromY, toX, toY;
+
+ MoveInfo(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
+ this.holder = holder;
+ this.fromX = fromX;
+ this.fromY = fromY;
+ this.toX = toX;
+ this.toY = toY;
+ }
+ }
+
+ private static class ChangeInfo {
+ public RecyclerView.ViewHolder oldHolder, newHolder;
+ public int fromX, fromY, toX, toY;
+ private ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder) {
+ this.oldHolder = oldHolder;
+ this.newHolder = newHolder;
+ }
+
+ ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder,
+ int fromX, int fromY, int toX, int toY) {
+ this(oldHolder, newHolder);
+ this.fromX = fromX;
+ this.fromY = fromY;
+ this.toX = toX;
+ this.toY = toY;
+ }
+
+ @Override
+ public String toString() {
+ return "ChangeInfo{"
+ + "oldHolder=" + oldHolder
+ + ", newHolder=" + newHolder
+ + ", fromX=" + fromX
+ + ", fromY=" + fromY
+ + ", toX=" + toX
+ + ", toY=" + toY
+ + '}';
+ }
+ }
+
+ @Override
+ public void runPendingAnimations() {
+ boolean removalsPending = !mPendingRemovals.isEmpty();
+ boolean movesPending = !mPendingMoves.isEmpty();
+ boolean changesPending = !mPendingChanges.isEmpty();
+ boolean additionsPending = !mPendingAdditions.isEmpty();
+ if (!removalsPending && !movesPending && !additionsPending && !changesPending) {
+ // nothing to animate
+ return;
+ }
+ // First, remove stuff
+ for (RecyclerView.ViewHolder holder : mPendingRemovals) {
+ animateRemoveImpl(holder);
+ }
+ mPendingRemovals.clear();
+ // Next, move stuff
+ if (movesPending) {
+ final ArrayList moves = new ArrayList<>();
+ moves.addAll(mPendingMoves);
+ mMovesList.add(moves);
+ mPendingMoves.clear();
+ Runnable mover = new Runnable() {
+ @Override
+ public void run() {
+ for (MoveInfo moveInfo : moves) {
+ animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY,
+ moveInfo.toX, moveInfo.toY);
+ }
+ moves.clear();
+ mMovesList.remove(moves);
+ }
+ };
+ if (removalsPending) {
+ View view = moves.get(0).holder.itemView;
+ ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration());
+ } else {
+ mover.run();
+ }
+ }
+ // Next, change stuff, to run in parallel with move animations
+ if (changesPending) {
+ final ArrayList changes = new ArrayList<>();
+ changes.addAll(mPendingChanges);
+ mChangesList.add(changes);
+ mPendingChanges.clear();
+ Runnable changer = new Runnable() {
+ @Override
+ public void run() {
+ for (ChangeInfo change : changes) {
+ animateChangeImpl(change);
+ }
+ changes.clear();
+ mChangesList.remove(changes);
+ }
+ };
+ if (removalsPending) {
+ RecyclerView.ViewHolder holder = changes.get(0).oldHolder;
+ ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration());
+ } else {
+ changer.run();
+ }
+ }
+ // Next, add stuff
+ if (additionsPending) {
+ final ArrayList additions = new ArrayList<>();
+ additions.addAll(mPendingAdditions);
+ mAdditionsList.add(additions);
+ mPendingAdditions.clear();
+ Runnable adder = new Runnable() {
+ @Override
+ public void run() {
+ for (RecyclerView.ViewHolder holder : additions) {
+ animateAddImpl(holder);
+ }
+ additions.clear();
+ mAdditionsList.remove(additions);
+ }
+ };
+ if (removalsPending || movesPending || changesPending) {
+ long removeDuration = removalsPending ? getRemoveDuration() : 0;
+ long moveDuration = movesPending ? getMoveDuration() : 0;
+ long changeDuration = changesPending ? getChangeDuration() : 0;
+ long totalDelay = removeDuration + Math.max(moveDuration, changeDuration);
+ View view = additions.get(0).itemView;
+ ViewCompat.postOnAnimationDelayed(view, adder, totalDelay);
+ } else {
+ adder.run();
+ }
+ }
+ }
+
+ @Override
+ public boolean animateRemove(final RecyclerView.ViewHolder holder) {
+ resetAnimation(holder);
+ mPendingRemovals.add(holder);
+ return true;
+ }
+
+ private void animateRemoveImpl(final RecyclerView.ViewHolder holder) {
+ final View view = holder.itemView;
+ final ViewPropertyAnimator animation = view.animate();
+ mRemoveAnimations.add(holder);
+ animation.setDuration(getRemoveDuration()).alpha(0).setListener(
+ new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animator) {
+ dispatchRemoveStarting(holder);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ animation.setListener(null);
+ view.setAlpha(1);
+ dispatchRemoveFinished(holder);
+ mRemoveAnimations.remove(holder);
+ dispatchFinishedWhenDone();
+ }
+ }).start();
+ }
+
+ @Override
+ public boolean animateAdd(final RecyclerView.ViewHolder holder) {
+ resetAnimation(holder);
+ holder.itemView.setAlpha(0);
+ mPendingAdditions.add(holder);
+ return true;
+ }
+
+ void animateAddImpl(final RecyclerView.ViewHolder holder) {
+ final View view = holder.itemView;
+ final ViewPropertyAnimator animation = view.animate();
+ mAddAnimations.add(holder);
+ animation.alpha(1).setDuration(getAddDuration())
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animator) {
+ dispatchAddStarting(holder);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animator) {
+ view.setAlpha(1);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ animation.setListener(null);
+ dispatchAddFinished(holder);
+ mAddAnimations.remove(holder);
+ dispatchFinishedWhenDone();
+ }
+ }).start();
+ }
+
+ @Override
+ public boolean animateMove(final RecyclerView.ViewHolder holder, int fromX, int fromY,
+ int toX, int toY) {
+ final View view = holder.itemView;
+ fromX += (int) holder.itemView.getTranslationX();
+ fromY += (int) holder.itemView.getTranslationY();
+ resetAnimation(holder);
+ int deltaX = toX - fromX;
+ int deltaY = toY - fromY;
+ if (deltaX == 0 && deltaY == 0) {
+ dispatchMoveFinished(holder);
+ return false;
+ }
+ if (deltaX != 0) {
+ view.setTranslationX(-deltaX);
+ }
+ if (deltaY != 0) {
+ view.setTranslationY(-deltaY);
+ }
+ mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY));
+ return true;
+ }
+
+ void animateMoveImpl(final RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
+ final View view = holder.itemView;
+ final int deltaX = toX - fromX;
+ final int deltaY = toY - fromY;
+ if (deltaX != 0) {
+ view.animate().translationX(0);
+ }
+ if (deltaY != 0) {
+ view.animate().translationY(0);
+ }
+ // TODO: make EndActions end listeners instead, since end actions aren't called when
+ // vpas are canceled (and can't end them. why?)
+ // need listener functionality in VPACompat for this. Ick.
+ final ViewPropertyAnimator animation = view.animate();
+ mMoveAnimations.add(holder);
+ animation.setDuration(getMoveDuration()).setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animator) {
+ dispatchMoveStarting(holder);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animator) {
+ if (deltaX != 0) {
+ view.setTranslationX(0);
+ }
+ if (deltaY != 0) {
+ view.setTranslationY(0);
+ }
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ animation.setListener(null);
+ dispatchMoveFinished(holder);
+ mMoveAnimations.remove(holder);
+ dispatchFinishedWhenDone();
+ }
+ }).start();
+ }
+
+ @Override
+ public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder,
+ int fromX, int fromY, int toX, int toY) {
+ if (oldHolder == newHolder) {
+ // Don't know how to run change animations when the same view holder is re-used.
+ // run a move animation to handle position changes.
+ return animateMove(oldHolder, fromX, fromY, toX, toY);
+ }
+ final float prevTranslationX = oldHolder.itemView.getTranslationX();
+ final float prevTranslationY = oldHolder.itemView.getTranslationY();
+ final float prevAlpha = oldHolder.itemView.getAlpha();
+ resetAnimation(oldHolder);
+ int deltaX = (int) (toX - fromX - prevTranslationX);
+ int deltaY = (int) (toY - fromY - prevTranslationY);
+ // recover prev translation state after ending animation
+ oldHolder.itemView.setTranslationX(prevTranslationX);
+ oldHolder.itemView.setTranslationY(prevTranslationY);
+ oldHolder.itemView.setAlpha(prevAlpha);
+ if (newHolder != null) {
+ // carry over translation values
+ resetAnimation(newHolder);
+ newHolder.itemView.setTranslationX(-deltaX);
+ newHolder.itemView.setTranslationY(-deltaY);
+ newHolder.itemView.setAlpha(0);
+ }
+ mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY));
+ return true;
+ }
+
+ void animateChangeImpl(final ChangeInfo changeInfo) {
+ final RecyclerView.ViewHolder holder = changeInfo.oldHolder;
+ final View view = holder == null ? null : holder.itemView;
+ final RecyclerView.ViewHolder newHolder = changeInfo.newHolder;
+ final View newView = newHolder != null ? newHolder.itemView : null;
+ if (view != null) {
+ final ViewPropertyAnimator oldViewAnim = view.animate().setDuration(
+ getChangeDuration());
+ mChangeAnimations.add(changeInfo.oldHolder);
+ oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX);
+ oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY);
+ oldViewAnim.alpha(0).setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animator) {
+ dispatchChangeStarting(changeInfo.oldHolder, true);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ oldViewAnim.setListener(null);
+ view.setAlpha(1);
+ view.setTranslationX(0);
+ view.setTranslationY(0);
+ dispatchChangeFinished(changeInfo.oldHolder, true);
+ mChangeAnimations.remove(changeInfo.oldHolder);
+ dispatchFinishedWhenDone();
+ }
+ }).start();
+ }
+ if (newView != null) {
+ final ViewPropertyAnimator newViewAnimation = newView.animate();
+ mChangeAnimations.add(changeInfo.newHolder);
+ newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration())
+ .alpha(1).setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animator) {
+ dispatchChangeStarting(changeInfo.newHolder, false);
+ }
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ newViewAnimation.setListener(null);
+ newView.setAlpha(1);
+ newView.setTranslationX(0);
+ newView.setTranslationY(0);
+ dispatchChangeFinished(changeInfo.newHolder, false);
+ mChangeAnimations.remove(changeInfo.newHolder);
+ dispatchFinishedWhenDone();
+ }
+ }).start();
+ }
+ }
+
+ private void endChangeAnimation(List infoList, RecyclerView.ViewHolder item) {
+ for (int i = infoList.size() - 1; i >= 0; i--) {
+ ChangeInfo changeInfo = infoList.get(i);
+ if (endChangeAnimationIfNecessary(changeInfo, item)) {
+ if (changeInfo.oldHolder == null && changeInfo.newHolder == null) {
+ infoList.remove(changeInfo);
+ }
+ }
+ }
+ }
+
+ private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) {
+ if (changeInfo.oldHolder != null) {
+ endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder);
+ }
+ if (changeInfo.newHolder != null) {
+ endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder);
+ }
+ }
+ private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, RecyclerView.ViewHolder item) {
+ boolean oldItem = false;
+ if (changeInfo.newHolder == item) {
+ changeInfo.newHolder = null;
+ } else if (changeInfo.oldHolder == item) {
+ changeInfo.oldHolder = null;
+ oldItem = true;
+ } else {
+ return false;
+ }
+ item.itemView.setAlpha(1);
+ item.itemView.setTranslationX(0);
+ item.itemView.setTranslationY(0);
+ dispatchChangeFinished(item, oldItem);
+ return true;
+ }
+
+ @Override
+ public void endAnimation(RecyclerView.ViewHolder item) {
+ final View view = item.itemView;
+ // this will trigger end callback which should set properties to their target values.
+ view.animate().cancel();
+ // TODO if some other animations are chained to end, how do we cancel them as well?
+ for (int i = mPendingMoves.size() - 1; i >= 0; i--) {
+ MoveInfo moveInfo = mPendingMoves.get(i);
+ if (moveInfo.holder == item) {
+ view.setTranslationY(0);
+ view.setTranslationX(0);
+ dispatchMoveFinished(item);
+ mPendingMoves.remove(i);
+ }
+ }
+ endChangeAnimation(mPendingChanges, item);
+ if (mPendingRemovals.remove(item)) {
+ view.setAlpha(1);
+ dispatchRemoveFinished(item);
+ }
+ if (mPendingAdditions.remove(item)) {
+ view.setAlpha(1);
+ dispatchAddFinished(item);
+ }
+
+ for (int i = mChangesList.size() - 1; i >= 0; i--) {
+ ArrayList changes = mChangesList.get(i);
+ endChangeAnimation(changes, item);
+ if (changes.isEmpty()) {
+ mChangesList.remove(i);
+ }
+ }
+ for (int i = mMovesList.size() - 1; i >= 0; i--) {
+ ArrayList moves = mMovesList.get(i);
+ for (int j = moves.size() - 1; j >= 0; j--) {
+ MoveInfo moveInfo = moves.get(j);
+ if (moveInfo.holder == item) {
+ view.setTranslationY(0);
+ view.setTranslationX(0);
+ dispatchMoveFinished(item);
+ moves.remove(j);
+ if (moves.isEmpty()) {
+ mMovesList.remove(i);
+ }
+ break;
+ }
+ }
+ }
+ for (int i = mAdditionsList.size() - 1; i >= 0; i--) {
+ ArrayList additions = mAdditionsList.get(i);
+ if (additions.remove(item)) {
+ view.setAlpha(1);
+ dispatchAddFinished(item);
+ if (additions.isEmpty()) {
+ mAdditionsList.remove(i);
+ }
+ }
+ }
+
+ // animations should be ended by the cancel above.
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ if (mRemoveAnimations.remove(item) && DEBUG) {
+ throw new IllegalStateException("after animation is cancelled, item should not be in "
+ + "mRemoveAnimations list");
+ }
+
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ if (mAddAnimations.remove(item) && DEBUG) {
+ throw new IllegalStateException("after animation is cancelled, item should not be in "
+ + "mAddAnimations list");
+ }
+
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ if (mChangeAnimations.remove(item) && DEBUG) {
+ throw new IllegalStateException("after animation is cancelled, item should not be in "
+ + "mChangeAnimations list");
+ }
+
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ if (mMoveAnimations.remove(item) && DEBUG) {
+ throw new IllegalStateException("after animation is cancelled, item should not be in "
+ + "mMoveAnimations list");
+ }
+ dispatchFinishedWhenDone();
+ }
+
+ private void resetAnimation(RecyclerView.ViewHolder holder) {
+ if (sDefaultInterpolator == null) {
+ sDefaultInterpolator = new ValueAnimator().getInterpolator();
+ }
+ holder.itemView.animate().setInterpolator(sDefaultInterpolator);
+ endAnimation(holder);
+ }
+
+ @Override
+ public boolean isRunning() {
+ return (!mPendingAdditions.isEmpty()
+ || !mPendingChanges.isEmpty()
+ || !mPendingMoves.isEmpty()
+ || !mPendingRemovals.isEmpty()
+ || !mMoveAnimations.isEmpty()
+ || !mRemoveAnimations.isEmpty()
+ || !mAddAnimations.isEmpty()
+ || !mChangeAnimations.isEmpty()
+ || !mMovesList.isEmpty()
+ || !mAdditionsList.isEmpty()
+ || !mChangesList.isEmpty());
+ }
+
+ /**
+ * Check the state of currently pending and running animations. If there are none
+ * pending/running, call {@link #dispatchAnimationsFinished()} to notify any
+ * listeners.
+ */
+ void dispatchFinishedWhenDone() {
+ if (!isRunning()) {
+ dispatchAnimationsFinished();
+ }
+ }
+
+ @Override
+ public void endAnimations() {
+ int count = mPendingMoves.size();
+ for (int i = count - 1; i >= 0; i--) {
+ MoveInfo item = mPendingMoves.get(i);
+ View view = item.holder.itemView;
+ view.setTranslationY(0);
+ view.setTranslationX(0);
+ dispatchMoveFinished(item.holder);
+ mPendingMoves.remove(i);
+ }
+ count = mPendingRemovals.size();
+ for (int i = count - 1; i >= 0; i--) {
+ RecyclerView.ViewHolder item = mPendingRemovals.get(i);
+ dispatchRemoveFinished(item);
+ mPendingRemovals.remove(i);
+ }
+ count = mPendingAdditions.size();
+ for (int i = count - 1; i >= 0; i--) {
+ RecyclerView.ViewHolder item = mPendingAdditions.get(i);
+ item.itemView.setAlpha(1);
+ dispatchAddFinished(item);
+ mPendingAdditions.remove(i);
+ }
+ count = mPendingChanges.size();
+ for (int i = count - 1; i >= 0; i--) {
+ endChangeAnimationIfNecessary(mPendingChanges.get(i));
+ }
+ mPendingChanges.clear();
+ if (!isRunning()) {
+ return;
+ }
+
+ int listCount = mMovesList.size();
+ for (int i = listCount - 1; i >= 0; i--) {
+ ArrayList moves = mMovesList.get(i);
+ count = moves.size();
+ for (int j = count - 1; j >= 0; j--) {
+ MoveInfo moveInfo = moves.get(j);
+ RecyclerView.ViewHolder item = moveInfo.holder;
+ View view = item.itemView;
+ view.setTranslationY(0);
+ view.setTranslationX(0);
+ dispatchMoveFinished(moveInfo.holder);
+ moves.remove(j);
+ if (moves.isEmpty()) {
+ mMovesList.remove(moves);
+ }
+ }
+ }
+ listCount = mAdditionsList.size();
+ for (int i = listCount - 1; i >= 0; i--) {
+ ArrayList additions = mAdditionsList.get(i);
+ count = additions.size();
+ for (int j = count - 1; j >= 0; j--) {
+ RecyclerView.ViewHolder item = additions.get(j);
+ View view = item.itemView;
+ view.setAlpha(1);
+ dispatchAddFinished(item);
+ additions.remove(j);
+ if (additions.isEmpty()) {
+ mAdditionsList.remove(additions);
+ }
+ }
+ }
+ listCount = mChangesList.size();
+ for (int i = listCount - 1; i >= 0; i--) {
+ ArrayList changes = mChangesList.get(i);
+ count = changes.size();
+ for (int j = count - 1; j >= 0; j--) {
+ endChangeAnimationIfNecessary(changes.get(j));
+ if (changes.isEmpty()) {
+ mChangesList.remove(changes);
+ }
+ }
+ }
+
+ cancelAll(mRemoveAnimations);
+ cancelAll(mMoveAnimations);
+ cancelAll(mAddAnimations);
+ cancelAll(mChangeAnimations);
+
+ dispatchAnimationsFinished();
+ }
+
+ void cancelAll(List viewHolders) {
+ for (int i = viewHolders.size() - 1; i >= 0; i--) {
+ viewHolders.get(i).itemView.animate().cancel();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * If the payload list is not empty, DefaultItemAnimator returns true.
+ * When this is the case:
+ *
+ *
If you override {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)}, both
+ * ViewHolder arguments will be the same instance.
+ *
+ *
+ * If you are not overriding {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)},
+ * then DefaultItemAnimator will call {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int)} and
+ * run a move animation instead.
+ *
+ *
+ */
+ @Override
+ public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder,
+ @NonNull List