搜了半天 终于找到关键字 掌阅 . ireader  可惜放到项目炸了,,,,


完整代码


// 万能适配器compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.50'implementation 'com.android.support:design:28.0.0'
  maven { url "https://jitpack.io" }

item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_weight="1"android:gravity="center"android:layout_width="match_parent"android:layout_height="wrap_content"><ImageViewandroid:layout_margin="20dp"android:id="@+id/iv"android:scaleType="fitXY"android:src="@mipmap/ic_launcher"android:layout_width="50dp"android:layout_height="50dp"/></LinearLayout>

public class MyAdapter extends BaseQuickAdapter<String, BaseViewHolder> {public MyAdapter(int layoutResId, @Nullable List<String> data) {super(layoutResId, data);}@Overrideprotected void convert(@NonNull BaseViewHolder helper, String item) {}
}

public class ContentScaleAnimation extends Animation {private float mPivotX;private float mPivotY;private float mPivotXValue; // 控件左上角Xprivate float mPivotYValue;private final float scaleTimes;private boolean mReverse;public ContentScaleAnimation(float mPivotXValue, float mPivotYValue, float scaleTimes, boolean mReverse) {this.mPivotXValue = mPivotXValue;this.mPivotYValue = mPivotYValue;this.scaleTimes = scaleTimes;this.mReverse = mReverse;}@Overrideprotected void applyTransformation(float interpolatedTime, Transformation t) {Matrix matrix=t.getMatrix();//缩放方法if (mReverse) {matrix.postScale(1 + (scaleTimes - 1) * (1.0f - interpolatedTime), 1 + (scaleTimes - 1) * (1.0f - interpolatedTime), mPivotX - mPivotXValue, mPivotY - mPivotYValue);} else {//  matrix.postScale(1 + (scaleTimes - 1) * interpolatedTime, 1 + (scaleTimes - 1) * interpolatedTime, mPivotX, mPivotY);matrix.postScale(1 + (scaleTimes - 1) * interpolatedTime, 1 + (scaleTimes - 1) * interpolatedTime, mPivotX - mPivotXValue , mPivotY - mPivotYValue );}float a = mPivotX - mPivotXValue;float b = mPivotY - mPivotYValue;// Log.d("scaleAnimation","mPivotX - mPivotXValue ="+a);// Log.d("scaleAnimation","mPivotY - mPivotYValue ="+b);}//缩放点坐标值@Overridepublic void initialize(int width, int height, int parentWidth, int parentHeight) {super.initialize(width, height, parentWidth, parentHeight);mPivotX = resolvePivotX(mPivotXValue, parentWidth, width);mPivotY = resolvePivoY(mPivotYValue, parentHeight, height);// Log.d("scaleAnimation","mPivotX is"+mPivotX);//  Log.d("scaleAnimation","mPivotY is"+mPivotY);// Log.d("scaleAnimation","mPivotXValue is"+mPivotXValue);//  Log.d("scaleAnimation","mPivotYValue is"+mPivotYValue);//  Log.d("scaleAnimation","width ="+width);// Log.d("scaleAnimation","width ="+height);// Log.d("scaleAnimation","width ="+parentWidth);//  Log.d("scaleAnimation","width ="+parentHeight);}//缩放点坐标值   缩放点到自身左边距离/缩放点到父控件左边的距离=缩放点自身右侧距离/缩放点到父控件右边的距离private float resolvePivotX(float margingLeft, int parentWidth, int width) {return (margingLeft * parentWidth) / (parentWidth - width);}private float resolvePivoY(float marginTop, int parentHeight, int height) {return (marginTop * parentHeight) / (parentHeight - height);}public void reverse() {mReverse = !mReverse;}public boolean getMReverse() {return mReverse;}public void setmPivotXValue (float mPivotXValue1) {this.mPivotXValue = mPivotXValue1;}public void setmPivotYValue (float mPivotYValue1) {this.mPivotYValue = mPivotYValue1;}
}
public class Rotate3DAnimation extends Animation {private Camera mCamera;private final float mFromDegrees;private final float mToDegrees;private float mPivotXValue;// 控件左上角Xprivate float mPivotYValue;//private final float mDepthZ;   //不需要用到此参数private final float scaleTimes;private boolean mReverse;private float mPivotX;      //缩放点Xprivate float mPivotY;      //缩放点Y/*** cover 动画构造方法,一边放大,一边翻转* @param mFromDegrees* @param mToDegrees* @param mPivotXValue  控件左上角X* @param mPivotYValue  控件左上角Y* @param scaleTimes    缩放比例* @param mReverse   动画是否逆向进行*/public Rotate3DAnimation(float mFromDegrees, float mToDegrees, float mPivotXValue, float mPivotYValue, float scaleTimes, boolean mReverse) {this.mFromDegrees = mFromDegrees;this.mToDegrees = mToDegrees;this.mPivotXValue = mPivotXValue;this.mPivotYValue = mPivotYValue;this.scaleTimes = scaleTimes;this.mReverse = mReverse;}@Overridepublic void initialize(int width, int height, int parentWidth, int parentHeight) {super.initialize(width, height, parentWidth, parentHeight);mCamera = new Camera();mPivotX = resolvePivotX(mPivotXValue, parentWidth, width);  //计算缩放点XmPivotY = resolvePivoY(mPivotYValue, parentHeight, height);   //计算缩放点Y}/*** 执行顺序 matrix.preTranslate() -->  camera.rotateY(degrees) -->   matrix.postTranslate() -->   matrix.postScale()* @param interpolatedTime* @param t*/@Overrideprotected void applyTransformation(float interpolatedTime, Transformation t) {float degrees = mReverse ? mToDegrees + (mFromDegrees - mToDegrees) * interpolatedTime : mFromDegrees + (mToDegrees - mFromDegrees) * interpolatedTime;final Matrix matrix = t.getMatrix();final Camera camera = mCamera;camera.save();camera.rotateY(degrees);camera.getMatrix(matrix);camera.restore();//  matrix.preTranslate(-mPivotXValue, 0);      //在进行rotateY之前需要移动物体,让物体左边与Y轴对齐//  matrix.postTranslate(mPivotXValue, 0);      //还原物体位置if (mReverse) {matrix.postScale(1 + (scaleTimes - 1) * (1.0f - interpolatedTime), 1 + (scaleTimes - 1) * (1.0f - interpolatedTime), mPivotX - mPivotXValue , mPivotY - mPivotYValue);} else {// matrix.postScale(1 + (scaleTimes - 1) * interpolatedTime, 1 + (scaleTimes - 1) * interpolatedTime, mPivotX, mPivotY);matrix.postScale(1 + (scaleTimes - 1) * interpolatedTime, 1 + (scaleTimes - 1) * interpolatedTime, mPivotX - mPivotXValue , mPivotY - mPivotYValue );}}private float resolvePivotX(float margingLeft, int parentWidth, int width) {return (margingLeft * parentWidth) / (parentWidth - width);}private float resolvePivoY(float marginTop, int parentHeight, int height) {return (marginTop * parentHeight) / (parentHeight - height);}public void reverse() {mReverse = !mReverse;}public boolean getMReverse() {return mReverse;}public void setmPivotXValue (float mPivotXValue1) {this.mPivotXValue = mPivotXValue1;}public void setmPivotYValue (float mPivotYValue1) {this.mPivotYValue = mPivotYValue1;}
}
public class Main2Activity extends AppCompatActivity implements Animation.AnimationListener {private int[] location = new int[2];private ContentScaleAnimation contentAnimation;private Rotate3DAnimation coverAnimation;private boolean mIsOpen = false;private int animationCount = 0;  //动画加载计数器  0 默认  1一个动画执行完毕   2二个动画执行完毕private AbsoluteLayout wmRootView;private WindowManager mWindowManager;private View rootView;private ImageView content;private TextView cover;private View iv;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main2);mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);wmRootView = new AbsoluteLayout(this);rootView = getWindow().getDecorView();initRecycler();}private void initRecycler() {List<String> list = new ArrayList<>();for (int i = 0; i < 20; i++) {list.add(" " + i);}MyAdapter myAdapter = new MyAdapter(R.layout.item_iv, list);RecyclerView recycler = findViewById(R.id.recycler);recycler.setAdapter(myAdapter);recycler.setLayoutManager(new GridLayoutManager(this, 3));myAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {@Overridepublic void onItemClick(BaseQuickAdapter adapter, View view, int position) {iv = view.findViewById(R.id.iv);iv.getLocationInWindow(location);mWindowManager.addView(wmRootView, getDefaultWindowParams());content = new ImageView(Main2Activity.this);content.setBackgroundColor(getResources().getColor(R.color.colorPrimary));cover = new TextView(getApplicationContext());cover.setBackgroundResource(R.mipmap.ic_launcher);AbsoluteLayout.LayoutParams params = new AbsoluteLayout.LayoutParams(iv.getLayoutParams());params.x = location[0];params.y = location[1];wmRootView.addView(content, params);wmRootView.addView(cover, params);initAnimation();if (contentAnimation.getMReverse()) {contentAnimation.reverse();}if (coverAnimation.getMReverse()) {coverAnimation.reverse();}cover.clearAnimation();cover.startAnimation(coverAnimation);content.clearAnimation();content.startAnimation(contentAnimation);}});}private void initAnimation() {AccelerateInterpolator interpolator = new AccelerateInterpolator();float scale1 = rootView.getWidth() / (float) iv.getMeasuredWidth();float scale2 = rootView.getHeight() / (float) iv.getMeasuredHeight();float scaleTimes = scale1 > scale2 ? scale1 : scale2;  //计算缩放比例contentAnimation = new ContentScaleAnimation(location[0], location[1], scaleTimes, false);contentAnimation.setInterpolator(interpolator);  //设置插值器contentAnimation.setDuration(1000);contentAnimation.setFillAfter(true);  //动画停留在最后一帧contentAnimation.setAnimationListener(this);coverAnimation = new Rotate3DAnimation(0, -180, location[0], location[1], scaleTimes, false);coverAnimation.setInterpolator(interpolator);coverAnimation.setDuration(1000);coverAnimation.setFillAfter(true);coverAnimation.setAnimationListener(this);}private WindowManager.LayoutParams getDefaultWindowParams() {WindowManager.LayoutParams params = new WindowManager.LayoutParams(WindowManager.LayoutParams.MATCH_PARENT,WindowManager.LayoutParams.MATCH_PARENT,0, 0,WindowManager.LayoutParams.TYPE_APPLICATION_PANEL,//windown类型,有层级的大的层级会覆盖在小的层级WindowManager.LayoutParams.FLAG_FULLSCREEN,PixelFormat.RGBA_8888);return params;}@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {//有两个动画监听会执行两次,所以要判断if (!mIsOpen) {animationCount++;if (animationCount >= 2) {mIsOpen = true;Intent intent = new Intent();intent.setClass(Main2Activity.this, MainActivity.class);startActivity(intent);overridePendingTransition(android.support.v7.appcompat.R.anim.abc_grow_fade_in_from_bottom, android.support.v7.appcompat.R.anim.abc_shrink_fade_out_from_bottom);}} else {animationCount--;if (animationCount <= 0) {mIsOpen = false;wmRootView.removeView(content);mWindowManager.removeView(wmRootView);}}}@Overridepublic void onAnimationRepeat(Animation animation) {}@Overrideprotected void onRestart() {closeBookAnimation();super.onRestart();}public void closeBookAnimation() {if (mIsOpen && wmRootView != null) {//因为书本打开后会移动到第一位置,所以要设置新的位置参数contentAnimation.setmPivotXValue(location[0]);contentAnimation.setmPivotYValue(location[1]);coverAnimation.setmPivotXValue(location[0]);coverAnimation.setmPivotYValue(location[1]);AbsoluteLayout.LayoutParams params = new AbsoluteLayout.LayoutParams(iv.getLayoutParams());params.x = location[0];params.y = location[1];//firstLocation[1]在滑动的时候回改变,所以要在dispatchDraw的时候获取该位置值wmRootView.updateViewLayout(cover, params);wmRootView.updateViewLayout(content, params);//动画逆向运行if (!contentAnimation.getMReverse()) {contentAnimation.reverse();}if (!coverAnimation.getMReverse()) {coverAnimation.reverse();}//清除动画再开始动画content.clearAnimation();content.startAnimation(contentAnimation);cover.clearAnimation();cover.startAnimation(coverAnimation);}}
}

Android 仿掌阅 小说阅读器 书籍打开动画相关推荐

  1. 仿掌阅实现书籍打开动画

    一. 前言 上次打开掌阅的时候看到书籍打开动画的效果还不错,正好最近也在做阅读器的项目,所以想在项目中实现一下. 二. 思路 讲思路之前,先看一下实现效果吧: 书籍打开关闭动画.gif 看完实现效果, ...

  2. android 上下滚动文字_计算机毕设项目004之Android系统在线小说阅读器

    计算机毕设项目004之Android系统在线小说阅读器 一. 项目名称 基于Android系统的在线小说阅读器 二. 项目简介 项目中的角色功能: 支持翻页动画:仿真翻页.覆盖翻页.上下滚动翻页等翻页 ...

  3. android优化中国风应用、完整NBA客户端、动态积分效果、文件传输、小说阅读器等源码...

    Android精选源码 android拖拽下拉关闭效果源码 一款优雅的中国风Android App源码 EasySignSeekBar一个漂亮而强大的自定义view15 android仿蘑菇街,蜜芽宝 ...

  4. 免费小说阅读器(Android版本)全站开源

    此小说阅读器只追求两项 极简(无广告,无添加) 丰富(内容丰富,只有你想不到的,没有它没有的) 漫品客户端 全站开源 开源地址: https://github.com/AnyMarvel/ManPin ...

  5. Android小说阅读器

    这是早期做的一个 android小说阅读器项目,是本地阅读器,没有联网功能,目前只支持txt格式. 但项目功能是比较齐全的: 文件预览 导入书籍 创建分类 批量管理书架上的图书 小说阅读 查看书籍目录 ...

  6. 基于Android的看小说APP源码Android本科毕业设计Android小说阅读器、小说APP源码

    基于kotlin + 协程 + MVVM 模式来编写的看小说APP. 完整代码下载地址:基于Android的看小说APP源码Android本科毕业设计Android小说阅读器.小说APP源码 主要框架 ...

  7. android txt小说阅读器的实现

    一分钟让你的app快速集成漂亮简洁的小说阅读器!!请进: https://github.com/bifan-wei/HwTxtReader 2021-06-12更新,适配Android X! 目前实现 ...

  8. PC免费简约开源的TXT小说阅读器(提取章节、书籍分组管理、记忆阅读进度、换肤、换字体、换主题)仅支持Windows

    最近自己做了个小说阅读器,就是下面这个东西啦,目前仅支持Window系统 个人喜欢在电脑.平板上等大屏幕设备上阅读小说或电子书籍.原因其一是屏幕足够大,可以选择更舒服的字体大小:其二是觉得小屏幕看字体 ...

  9. android 阅读器自动滚动,Android编程实现小说阅读器滑动效果的方法

    本文实例讲述了Android编程实现小说阅读器滑动效果的方法.分享给大家供大家参考,具体如下: 看过小说都知道小说阅读器翻页有好多种效果,比如仿真翻页,滑动翻页,等等.由于某种原因,突然想写一个简单点 ...

最新文章

  1. 【Linux】数据库管理
  2. 织梦dedecms如何对列表添加判断语句
  3. Foundation框架
  4. 数据结构:排序算法之堆排序和选择排序
  5. STM32H743+CubeMX-双路FDCAN同时工作的终极方案(裸机)
  6. java 滚动显示信息_滚动显示文本的Java程序
  7. mysql 5.7.10免安装_免安装版mysql5.7.10-16配置教程(2)
  8. php替换图片_php实现图片上传并进行替换操作
  9. MacOS入门技巧分享
  10. PHP substr(),mb_substr(),mb_strcut()比较
  11. VMware解决黑屏
  12. 查询mysql表的所有字段名_查询数据库中所有表名,查询表中所有字段名
  13. 弯头lisp_(最全的)管道材料代号说明
  14. 在麒麟桌面操作系统编译安装postgresql的经历
  15. 360全景拼接 opencv_GitHub - hellojiawa/AndroidPanoDemo: 使用Opencv全景照片拼接
  16. Vue + Element UI 实现权限管理系统(更换皮肤主题)
  17. 两个L组成的括号?(取整符号)
  18. python技术线上培训
  19. 学生类定义(类和对象) Python
  20. 狂赚 1200 亿,差点收购苹果,影响千万程序员,那个叫做太阳的公司却陨落了!...

热门文章

  1. 【Graphormer阅读笔记、实验与刷榜】《Do Transformers Really Perform Bad for Graph Representation?》
  2. 【编码】csv文件打开是乱码
  3. shopify订单管理软件,获取订单方法
  4. SEO优化之充分理解“四处一词”
  5. 中值联认证中心发布的区块链证书验证真伪的办法
  6. excel功能小技巧:自动求和的注意事项
  7. win7 64 系统中打开或关闭windows功能空白
  8. argument type mismatch 参数类型不匹配
  9. android中实现毛笔效果(View 中绘图)
  10. nodejs在windows下安装后npm命令无法使用的解决方法