内容简介:我偶尔一次发现掌阅的打开书本动画不错,然后度娘了一下,发现一个链接:一共就是2个类+2个跳转动画
Github地址 ,欢迎点赞,fork
我偶尔一次发现掌阅的打开书本动画不错,然后度娘了一下,发现一个链接: download.csdn.net/download/we… , 下载下来学习膜拜了一下,发现有些动画过度和掌阅有点不一样,所以我就拷贝源码并略微修改了下,如果想看原著,上面已经贴了,这个效果是GIF,真机更流畅一些.
一共就是2个类+2个跳转动画
首先,看看 BookOpenView
public class BookOpenView extends FrameLayout implements Animator.AnimatorListener { private BookOpenViewValue mStartValue; private AnimatorSet mAnimatorSet1, mAnimatorSet2; private TextView tv_book_name; private ImageView iv_book_content; private View iv_book_cover; private ConstraintLayout cl_book_container; // 默认打开书本动画是关闭的 private AtomicBoolean isOpened = new AtomicBoolean(false); public BookOpenView(@NonNull Context context) { super(context); initView(context); } public BookOpenView(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); initView(context); } public BookOpenView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { super(context, attrs, defStyleAttr); initView(context); } public void initView(Context context) { LayoutInflater.from(context).inflate(R.layout.book_open_close, this); setBackgroundColor(Color.TRANSPARENT); tv_book_name = (TextView) findViewById(R.id.tv_book_name); iv_book_content = (ImageView) findViewById(R.id.iv_book_content); iv_book_cover = (View) findViewById(R.id.iv_book_cover); cl_book_container = (ConstraintLayout) findViewById(R.id.cl_book_container); } /** * 开启动画 */ public synchronized void startAnim(final BookOpenViewValue startValue, BookOpenViewValue endValue) { if (!isOpened.get()) { if (!TextUtils.isEmpty(startValue.getBookName())){ tv_book_name.setText(startValue.getBookName()); } // 如果有图片,可以在此给 iv_book_cover 设置,图解尽量不要太大,10K以内为佳 mStartValue = startValue; System.out.println("startAnim===========mStartValue: " + mStartValue.toString() + " ========startValue: " + startValue.toString()); LayoutParams layoutParams = (LayoutParams) cl_book_container.getLayoutParams(); layoutParams.width = startValue.getRight() - startValue.getLeft(); layoutParams.height = startValue.getBottom() - startValue.getTop(); cl_book_container.setLayoutParams(layoutParams); iv_book_content.setLayoutParams(layoutParams); cl_book_container.setTranslationX(startValue.getLeft()); cl_book_container.setTranslationY(startValue.getTop()); // 计算缩放的起始位置和缩放中心点 final int x1 = ((layoutParams.width * (endValue.getRight() - layoutParams.width)) - layoutParams.width * (endValue.getRight() - startValue.getRight())) / (endValue.getRight() - layoutParams.width); final float sX1 = (layoutParams.width - x1 + endValue.getRight() - startValue.getRight()) * 1.0f / (layoutParams.width - x1); final float sX2 = (x1 + startValue.getLeft()) * 1.0f / x1; final float sX = Math.max(sX1, sX2); final int y1 = ((layoutParams.height * (endValue.getBottom() - layoutParams.height)) - layoutParams.height * (endValue.getBottom() - startValue.getBottom())) / (endValue.getBottom() - layoutParams.height); final float sY1 = (layoutParams.height - y1 + endValue.getBottom() - startValue.getBottom()) * 1.0f / (layoutParams.height - y1); final float sY2 = (y1 + startValue.getTop()) * 1.0f / y1; final float sY = Math.max(sY1, sY2); mStartValue.setX(x1); mStartValue.setsX(sX); mStartValue.setY(y1); mStartValue.setsY(sY); cl_book_container.setPivotX(0); cl_book_container.setPivotY(y1); // 对 封面进行缩放 ObjectAnimator scaleX = ObjectAnimator.ofFloat(cl_book_container, "scaleX", 1.0f, sX * 0.8f); scaleX.setDuration(1000); ObjectAnimator scaleY = ObjectAnimator.ofFloat(cl_book_container, "scaleY", 1.0f, sY); scaleY.setDuration(1000); // 对 封面进行平移 ObjectAnimator translationLine = ObjectAnimator.ofFloat(cl_book_container, "translationX", startValue.getLeft(), 0); translationLine.setDuration(1000); // 对封面进行旋转 ObjectAnimator rotationY = ObjectAnimator.ofFloat(cl_book_container, "rotationY", 0, -150); rotationY.setDuration(600); mAnimatorSet1 = new AnimatorSet(); mAnimatorSet1.playTogether(scaleX, scaleY, translationLine, rotationY); mAnimatorSet1.start(); /* ------------------------------------------------ */ // 对 内部内容进行缩放,必须和封面保持一致的动作 iv_book_content.setPivotX(x1); iv_book_content.setPivotY(y1); iv_book_content.setTranslationX(startValue.getLeft()); iv_book_content.setTranslationY(startValue.getTop()); ObjectAnimator scaleX2 = ObjectAnimator.ofFloat(iv_book_content, "scaleX", 1.0f, sX); scaleX2.setDuration(1000); ObjectAnimator scaleY2 = ObjectAnimator.ofFloat(iv_book_content, "scaleY", 1.0f, sY); scaleY2.setDuration(1000); mAnimatorSet2 = new AnimatorSet(); mAnimatorSet2.playTogether(scaleX2, scaleY2); mAnimatorSet2.addListener(this); mAnimatorSet2.start(); } } /** * 关闭动画 , 逻辑和开始动画相反 */ public synchronized void closeAnim() { if (isOpened.get()) { setVisibility(VISIBLE); setAlpha(1.0f); cl_book_container.setScaleX(mStartValue.getsX() * 0.8f); cl_book_container.setScaleY(mStartValue.getsY()); cl_book_container.setRotationY(-150); ObjectAnimator scaleX = ObjectAnimator.ofFloat(cl_book_container, "scaleX", mStartValue.getsX() * 0.8f, 1.0f); scaleX.setDuration(1000); ObjectAnimator scaleY = ObjectAnimator.ofFloat(cl_book_container, "scaleY", mStartValue.getsY(), 1.0f); scaleY.setDuration(1000); ObjectAnimator translationLine = ObjectAnimator.ofFloat(cl_book_container, "translationX", 0, mStartValue.getLeft()); translationLine.setDuration(1000); ObjectAnimator rotationY = ObjectAnimator.ofFloat(cl_book_container, "rotationY", -150, 0); rotationY.setDuration(600); rotationY.setStartDelay(400); mAnimatorSet1 = new AnimatorSet(); mAnimatorSet1.playTogether(scaleX, scaleY, translationLine, rotationY); mAnimatorSet1.start(); /* ------------------------------------------------ */ iv_book_content.setScaleX(mStartValue.getsX()); iv_book_content.setScaleY(mStartValue.getsY()); ObjectAnimator scaleX2 = ObjectAnimator.ofFloat(iv_book_content, "scaleX", mStartValue.getsX(), 1.0f); scaleX2.setDuration(1000); ObjectAnimator scaleY2 = ObjectAnimator.ofFloat(iv_book_content, "scaleY", mStartValue.getsY(), 1.0f); scaleY2.setDuration(1000); mAnimatorSet2 = new AnimatorSet(); mAnimatorSet2.playTogether(scaleX2, scaleY2); mAnimatorSet2.start(); mAnimatorSet2.addListener(this); } } @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { System.out.println("onAnimationEnd========== " + isOpened.get()); if (isOpened.get()) { // 关闭书本动画执行了 isOpened.set(false); if (null != mEndListener) { mEndListener.onRemove(); } } else { // 打开书本动画 isOpened.set(true); if (null != mEndListener) { mEndListener.onAnimationEnd(); } } } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } public void cancel() { mAnimatorSet1.cancel(); mAnimatorSet2.cancel(); } public interface OnAnimationEndListener { void onAnimationEnd(); void onRemove(); } private OnAnimationEndListener mEndListener; public void setEndListener(OnAnimationEndListener endListener) { mEndListener = endListener; } } 复制代码
内容略多,主要涉及计算,这个细节调整,大家可根据自己喜欢的效果调整试试
再来看一个类: BookOpenViewValue ,一目了然啊
public class BookOpenViewValue { private int left; private int top; private int right; private int bottom; private float x; private float y; private float sX; private float sY; private String bookName; private String bookCover; public BookOpenViewValue(){} public BookOpenViewValue(int left, int top, int right, int bottom){ this.left = left; this.top = top; this.right = right; this.bottom = bottom; } public int getRight() { return right; } public void setRight(int right) { this.right = right; } public int getBottom() { return bottom; } public void setBottom(int bottom) { this.bottom = bottom; } public int getLeft() { return left; } public void setLeft(int left) { this.left = left; } public int getTop() { return top; } public void setTop(int top) { this.top = top; } public float getX() { return x; } public void setX(float x) { this.x = x; } public float getY() { return y; } public void setY(float y) { this.y = y; } public float getsX() { return sX; } public void setsX(float sX) { this.sX = sX; } public float getsY() { return sY; } public void setsY(float sY) { this.sY = sY; } public String getBookName() { return bookName; } public void setBookName(String bookName) { this.bookName = bookName; } public String getBookCover() { return bookCover; } public void setBookCover(String bookCover) { this.bookCover = bookCover; } } 复制代码
最后来看看在 Activity 中用法,其实和一般普通 EditText 用法一致啦!
class MainActivity : AppCompatActivity() { private var mBookOpenView: BookOpenView? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) ll_contain.setOnClickListener { val window = window.decorView as ViewGroup val location = IntArray(2) ll_contain.getLocationInWindow(location) val startValue = BookOpenViewValue(location[0], location[1], location[0] + (ll_contain.right - ll_contain.left), location[1] + (ll_contain.bottom - ll_contain.top)) val endValue = BookOpenViewValue(window.left, window.top, window.right, window.bottom) mBookOpenView = BookOpenView(this@MainActivity) window.addView(mBookOpenView) mBookOpenView?.startAnim(startValue, endValue) mBookOpenView?.setEndListener(object : BookOpenView.OnAnimationEndListener { override fun onAnimationEnd() { println("onAnimationEnd========== onAnimationEnd") startActivity(Intent(this@MainActivity, ReadActivity::class.java)) overridePendingTransition(R.anim.read_fade_in, R.anim.read_fade_out) } override fun onRemove() { println("onAnimationEnd========== onRemove") window.removeView(mBookOpenView) } }) } } override fun onResume() { super.onResume() println("onAnimationEnd========== onResume") mBookOpenView?.closeAnim() } } 复制代码
跳转的 Activity 更简单了:
class ReadActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_read) } // 重写主要是去掉系统默认跳转动画,方便那边执行closeAnim override fun finish() { super.finish() overridePendingTransition(0, 0) } } 复制代码
最后贴上2个跳转动画: res/anim/
read_fade_in.xml
<?xml version="1.0" encoding="utf-8"?> <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="200" android:fromAlpha="1.0" android:interpolator="@android:anim/accelerate_interpolator" android:toAlpha="1.0" > </alpha> 复制代码
read_fade_out.xml
<?xml version="1.0" encoding="utf-8"?> <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="200" android:fromAlpha="1.0" android:interpolator="@android:anim/accelerate_interpolator" android:toAlpha="0.0" > </alpha> 复制代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 书本上学不到:万台服务器下运维怎样做好监控?
- 受启于做梦,DeepMind 提出压缩 Transformer,并开源书本级数据集PG-19
- Android获取软键盘的高度、键盘的打开与关闭、监听键盘处于打开还是关闭状态
- 关于python关闭
- Swift关闭UITextView键盘
- CentOS 7 关闭透明大页
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
C语言程序设计现代方法
K. N. King / 人民邮电出版社 / 2007-11 / 55.00元
《C语言程序设计现代方法》最主要的一个目的就是通过一种“现代方法”来介绍C语言,实现客观评价C语言、强调标准化C语言、强调软件工程、不再强调“手工优化”、强调与c++语言的兼容性的目标。《C语言程序设计现代方法》分为C语言的基础特性。C语言的高级特性、C语言标准库和参考资料4个部分。每章都有“问与答”小节,给出一系列与本章内容相关的问题及其答案,此外还包含适量的习题。一起来看看 《C语言程序设计现代方法》 这本书的介绍吧!