android 继承面试题,【继承移动面试题】面试问题:Android… - 看准网

package com.example.splash.pictureselecters.view;

import android.support.annotation.NonNull;

import android.support.v4.animation.AnimatorCompatHelper;

import android.support.v4.view.ViewCompat;

import android.support.v4.view.ViewPropertyAnimatorCompat;

import android.support.v4.view.ViewPropertyAnimatorListener;

import android.support.v7.widget.RecyclerView;

import android.support.v7.widget.SimpleItemAnimator;

import android.view.View;

import java.util.ArrayList;

import java.util.List;

/**

* Created by chenliguan on 2017/5/3 0003.

*/

public class NoAlphaItemAnimator extends SimpleItemAnimator {

private static final boolean DEBUG = false;

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 (NoAlphaItemAnimator.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 (NoAlphaItemAnimator.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 ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);

mRemoveAnimations.add(holder);

animation.setDuration(getRemoveDuration())

.setListener(new NoAlphaItemAnimator.VpaListenerAdapter() {

@Override

public void onAnimationStart(View view) {

dispatchRemoveStarting(holder);

}

@Override

public void onAnimationEnd(View view) {

animation.setListener(null);

ViewCompat.setAlpha(view, 1);

dispatchRemoveFinished(holder);

mRemoveAnimations.remove(holder);

dispatchFinishedWhenDone();

}

}).start();

}

@Override

public boolean animateAdd(final RecyclerView.ViewHolder holder) {

resetAnimation(holder);

ViewCompat.setAlpha(holder.itemView, 0);

mPendingAdditions.add(holder);

return true;

}

void animateAddImpl(final RecyclerView.ViewHolder holder) {

final View view = holder.itemView;

final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);

mAddAnimations.add(holder);

animation.setDuration(getAddDuration()).

setListener(new NoAlphaItemAnimator.VpaListenerAdapter() {

@Override

public void onAnimationStart(View view) {

dispatchAddStarting(holder);

}

@Override

public void onAnimationCancel(View view) {

ViewCompat.setAlpha(view, 1);

}

@Override

public void onAnimationEnd(View view) {

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 += ViewCompat.getTranslationX(holder.itemView);

fromY += ViewCompat.getTranslationY(holder.itemView);

resetAnimation(holder);

int deltaX = toX - fromX;

int deltaY = toY - fromY;

if (deltaX == 0 && deltaY == 0) {

dispatchMoveFinished(holder);

return false;

}

if (deltaX != 0) {

ViewCompat.setTranslationX(view, -deltaX);

}

if (deltaY != 0) {

ViewCompat.setTranslationY(view, -deltaY);

}

mPendingMoves.add(new NoAlphaItemAnimator.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) {

ViewCompat.animate(view).translationX(0);

}

if (deltaY != 0) {

ViewCompat.animate(view).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 ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);

mMoveAnimations.add(holder);

animation.setDuration(getMoveDuration()).setListener(new NoAlphaItemAnimator.VpaListenerAdapter() {

@Override

public void onAnimationStart(View view) {

dispatchMoveStarting(holder);

}

@Override

public void onAnimationCancel(View view) {

if (deltaX != 0) {

ViewCompat.setTranslationX(view, 0);

}

if (deltaY != 0) {

ViewCompat.setTranslationY(view, 0);

}

}

@Override

public void onAnimationEnd(View view) {

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 = ViewCompat.getTranslationX(oldHolder.itemView);

final float prevTranslationY = ViewCompat.getTranslationY(oldHolder.itemView);

final float prevAlpha = ViewCompat.getAlpha(oldHolder.itemView);

resetAnimation(oldHolder);

int deltaX = (int) (toX - fromX - prevTranslationX);

int deltaY = (int) (toY - fromY - prevTranslationY);

// recover prev translation state after ending animation

ViewCompat.setTranslationX(oldHolder.itemView, prevTranslationX);

ViewCompat.setTranslationY(oldHolder.itemView, prevTranslationY);

ViewCompat.setAlpha(oldHolder.itemView, prevAlpha);

if (newHolder != null) {

// carry over translation values

resetAnimation(newHolder);

ViewCompat.setTranslationX(newHolder.itemView, -deltaX);

ViewCompat.setTranslationY(newHolder.itemView, -deltaY);

ViewCompat.setAlpha(newHolder.itemView, 0);

}

mPendingChanges.add(new NoAlphaItemAnimator.ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY));

return true;

}

void animateChangeImpl(final NoAlphaItemAnimator.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 ViewPropertyAnimatorCompat oldViewAnim = ViewCompat.animate(view).setDuration(

getChangeDuration());

mChangeAnimations.add(changeInfo.oldHolder);

oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX);

oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY);

oldViewAnim.setListener(new NoAlphaItemAnimator.VpaListenerAdapter() {

@Override

public void onAnimationStart(View view) {

dispatchChangeStarting(changeInfo.oldHolder, true);

}

@Override

public void onAnimationEnd(View view) {

oldViewAnim.setListener(null);

ViewCompat.setAlpha(view, 1);

ViewCompat.setTranslationX(view, 0);

ViewCompat.setTranslationY(view, 0);

dispatchChangeFinished(changeInfo.oldHolder, true);

mChangeAnimations.remove(changeInfo.oldHolder);

dispatchFinishedWhenDone();

}

}).start();

}

if (newView != null) {

final ViewPropertyAnimatorCompat newViewAnimation = ViewCompat.animate(newView);

mChangeAnimations.add(changeInfo.newHolder);

newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()).

setListener(new NoAlphaItemAnimator.VpaListenerAdapter() {

@Override

public void onAnimationStart(View view) {

dispatchChangeStarting(changeInfo.newHolder, false);

}

@Override

public void onAnimationEnd(View view) {

newViewAnimation.setListener(null);

ViewCompat.setAlpha(newView, 1);

ViewCompat.setTranslationX(newView, 0);

ViewCompat.setTranslationY(newView, 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--) {

NoAlphaItemAnimator.ChangeInfo changeInfo = infoList.get(i);

if (endChangeAnimationIfNecessary(changeInfo, item)) {

if (changeInfo.oldHolder == null && changeInfo.newHolder == null) {

infoList.remove(changeInfo);

}

}

}

}

private void endChangeAnimationIfNecessary(NoAlphaItemAnimator.ChangeInfo changeInfo) {

if (changeInfo.oldHolder != null) {

endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder);

}

if (changeInfo.newHolder != null) {

endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder);

}

}

private boolean endChangeAnimationIfNecessary(NoAlphaItemAnimator.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;

}

ViewCompat.setAlpha(item.itemView, 1);

ViewCompat.setTranslationX(item.itemView, 0);

ViewCompat.setTranslationY(item.itemView, 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.

ViewCompat.animate(view).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--) {

NoAlphaItemAnimator.MoveInfo moveInfo = mPendingMoves.get(i);

if (moveInfo.holder == item) {

ViewCompat.setTranslationY(view, 0);

ViewCompat.setTranslationX(view, 0);

dispatchMoveFinished(item);

mPendingMoves.remove(i);

}

}

endChangeAnimation(mPendingChanges, item);

if (mPendingRemovals.remove(item)) {

ViewCompat.setAlpha(view, 1);

dispatchRemoveFinished(item);

}

if (mPendingAdditions.remove(item)) {

ViewCompat.setAlpha(view, 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--) {

NoAlphaItemAnimator.MoveInfo moveInfo = moves.get(j);

if (moveInfo.holder == item) {

ViewCompat.setTranslationY(view, 0);

ViewCompat.setTranslationX(view, 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)) {

ViewCompat.setAlpha(view, 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) {

AnimatorCompatHelper.clearInterpolator(holder.itemView);

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--) {

NoAlphaItemAnimator.MoveInfo item = mPendingMoves.get(i);

View view = item.holder.itemView;

ViewCompat.setTranslationY(view, 0);

ViewCompat.setTranslationX(view, 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);

View view = item.itemView;

ViewCompat.setAlpha(view, 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--) {

NoAlphaItemAnimator.MoveInfo moveInfo = moves.get(j);

RecyclerView.ViewHolder item = moveInfo.holder;

View view = item.itemView;

ViewCompat.setTranslationY(view, 0);

ViewCompat.setTranslationX(view, 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;

ViewCompat.setAlpha(view, 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--) {

ViewCompat.animate(viewHolders.get(i).itemView).cancel();

}

}

/**

* {@inheritDoc}

*

* If the payload list is not empty, NoAlphaItemAnimator 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 NoAlphaItemAnimator 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 payloads) {

return !payloads.isEmpty() || super.canReuseUpdatedViewHolder(viewHolder, payloads);

}

private static class VpaListenerAdapter implements ViewPropertyAnimatorListener {

VpaListenerAdapter() {

}

@Override

public void onAnimationStart(View view) {}

@Override

public void onAnimationEnd(View view) {}

@Override

public void onAnimationCancel(View view) {}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值