转载请注明出处,谢谢:https://blog.csdn.net/HarryWeasley/article/details/89449919
源码地址为:https://github.com/HarryWeasley/KuaishouDemo
首先看快手的动图展示
然后是我做的demo动图效果
前因:作为一个中二中年人,某次机缘巧合之下,下载了快手这个app,然后发现了他这个动画,就觉得这个动画运用的地方挺多的,微信的图片退出动画也是这个,所以决定如何实现该功能。
其实本篇文章的难度并不是很大,主要是解决的一个思路问题。
首先第一个要使用转场动画:
Intent intent = new Intent(MainActivity.this, DetailActivity2.class);
intent.putExtra("url",datas.get(position));
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this, v, "sharedView").toBundle());
要在xml中加入
android:transitionName="sharedView"
转场动画不是本文的重点,不会详细描述。
当我们滑动视图,让视图跟着手指的操作而滑动的时候,可以使用GestureDetector类实现,在onScroll方法中回调,进行滑动操作。
在实现GestureDetector.OnGestureListener方法的时候,一定要将onDown方法的返回值变为true,否则可能onScroll方法不会被执行
视图的变大变小,使用view.setScaleX方式来实现
视图的滚动滑动,使用view.setTranslationX方式来实现
而视图的背景,使用一个自定义的TypeEvaluator来实现
代码如下所示:
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if (parent == null) {
parent = getChildAt(0);
}
if (viewHeight == 0) {
viewHeight = parent.getHeight();
}
float moveX = e2.getX() - e1.getX();
float moveY = e2.getY() - e1.getY();
mExitScalingRef = 1;
mExitScalingRef = mExitScalingRef - moveY / viewHeight;
parent.setTranslationX(moveX);
parent.setTranslationY(moveY);
parent.setScaleX(mExitScalingRef);
parent.setScaleY(mExitScalingRef);
if (mExitScalingRef > 1) {
//当用户往上滑动的时候
frameLayout.setBackgroundColor(mColorEvaluator.evaluate(2 - mExitScalingRef, 0x00000000, 0xFF000000));
} else {
//当用户往下滑动的时候
frameLayout.setBackgroundColor(mColorEvaluator.evaluate(mExitScalingRef, 0x00000000, 0xFF000000));
}
return false;
}
其中mColorEvaluator的实现代码如下所示:
TypeEvaluator<Integer> mColorEvaluator = new TypeEvaluator<Integer>() {
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int startColor = startValue;
int endColor = endValue;
int alpha = (int) (Color.alpha(startColor) + fraction * (Color.alpha(endColor) - Color.alpha(startColor)));
int red = (int) (Color.red(startColor) + fraction * (Color.red(endColor) - Color.red(startColor)));
int green = (int) (Color.green(startColor) + fraction * (Color.green(endColor) - Color.green(startColor)));
int blue = (int) (Color.blue(startColor) + fraction * (Color.blue(endColor) - Color.blue(startColor)));
return Color.argb(alpha, red, green, blue);
}
};
当我们松开手指,来判断缩小的进度,当小于某个进度值的时候,退出该activity,否则执行返回动画:
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (mExitScalingRef < DEFAULT_EXIT_SCALE) {
//缩小到一定的程度,将其关闭
if (finishListener != null) {
finishListener.finish();
}
} else {
//如果拉动距离不到某个角度,则将其动画返回原位置
final float moveX = parent.getTranslationX();
final float moveY = parent.getTranslationY();
final float scaleX = parent.getScaleX();
final float scaleY = parent.getScaleY();
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.setDuration(500);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float p = (float) animation.getAnimatedValue();
float animationMoveX = moveX + (0 - moveX) * p;
parent.setTranslationX(animationMoveX);
parent.setTranslationY(moveY + (0 - moveY) * p);
parent.setScaleX(scaleX + (1 - scaleX) * p);
parent.setScaleY(scaleY + (1 - scaleY) * p);
}
});
valueAnimator.start();
}
}
return mGestureDetector.onTouchEvent(event);
}
为了使该控件更有集成性,我自定义了一个FrameLayout,AnimationFrameLayout
在Activity的xml布局中只是放一个com.example.kuaishoudemo.AnimationFrameLayout控件
然后在onCreate方法中,通过以下的方式,来实现真正的视图
AnimationFrameLayout frameLayout = findViewById(R.id.frame_layout);
//将内部的布局item_linear_layout,放入AnimationFrameLayout中
View view = LayoutInflater.from(this).inflate(R.layout.item_linear_layout, frameLayout);
frameLayout.setDefaultExitScale(0.8f);
ImageView imageView = view.findViewById(R.id.image);
String url = getIntent().getStringExtra("url");
Glide.with(this).load(url).into(imageView);
frameLayout.setFinishListener(new AnimationFrameLayout.FinishListener() {
@Override
public void finish() {
onBackPressed();
}
});
文章源码地址在上部,具体的源码信息,大家去github下载下来看就可以了,谢谢。