Android自定义view;实现掌阅打开书籍动画效果

news2024/11/20 21:24:55

这里利用自定义view的方式来处理,初始化数据,camera通过setLocation调整相机的位置,但是Camera 的位置单位是英寸,英寸和像素的换算单位在 Skia 中被写成了72 像素,8 x 72 = 576,所以它的默认位置是 (0, 0, -576)。所以这里需要做一个位置的适配。

public OpenBookView(Context context) {
super(context);
}

public OpenBookView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}

private void init() {
camera = new Camera();
pageBackgroundPaint = new Paint();
pageBackgroundPaint.setColor(0xffFFD700);
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
float newZ = -displayMetrics.density * 6;
camera.setLocation(0, 0, newZ);
refreshData();
}

接下来看打开书籍的动画,很简单设置一个动画系数。

openBookview.setVisibility(View.VISIBLE);
Bitmap bitmap = ((BitmapDrawable) bookshlefBook.getBackground()).getBitmap();
openBookview.openAnimation(bitmap, bookshlefBook.getLeft(), bookshlefBook.getTop(), bookshlefBook.getWidth(), bookshlefBook.getHeight(), new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
Intent intent = new Intent(MainActivity.this, BrowserBookActivity.class);
startActivityForResult(intent, RESULT_FIRST_USER);
overridePendingTransition(0, 0);
}
});

public void openAnimation(Bitmap coverBitmap, float left, float top, float width, float height, AnimatorListenerAdapter adapter) {
this.coverBitmap = coverBitmap;
coverWidth = width;
coverHeight = height;
coverLeft = left;
coverTop = top;
isOpen = true;
refreshData();
startAnim(adapter);
}

private void startAnim(AnimatorListenerAdapter adapter) {
ObjectAnimator animator = ObjectAnimator.ofFloat(this, “scaleX”, 0f, 1f);
animator.setDuration(DURATION);
animator.addListener(adapter);
animator.start();
}

@Keep
public void setScaleX(float scale) {
if (isOpen) {
this.scale = scale;
} else {
this.scale = 1f - scale;
}
postInvalidate();
}

自定义view核心部分

最后核心绘制代码,本质是将画布扩大并且使用camera旋转y轴进行投影操作。首先通过动画的scale平移当前的画布,然后根据bitmap的像素值和总大小判断扩大的比例,通过canvas.drawRect(bookRect, pageBackgroundPaint)绘制对应的黄色画纸,通过canvas.translate(0, -coverHeight / 2);调整camera轴心。从而实现效果。

canvas.save();

canvas.translate(coverLeft - coverLeft * scale, coverTop - coverTop * scale);
float scaleX = viewScaleWidth + (maxScaleWidth - viewScaleWidth) * scale;
float scaleY = viewScaleHeight + (maxScaleHeight - viewScaleHeight) * scale;

Log.e(“scaleX”, “” + scaleX);

canvas.scale(scaleX, scaleY);
canvas.drawRect(bookRect, pageBackgroundPaint);
camera.save();

canvas.save();
canvas.translate(0, -coverHeight / 2);
camera.rotateY(-180 * scale);
camera.applyToCanvas(canvas);
canvas.translate(0, coverHeight / 2);

canvas.drawBitmap(coverBitmap, 0, 0, pageBackgroundPaint);
camera.restore();
canvas.restore();
canvas.restore();

设置比例

最后说一下,bitmap显示的比例,因为从原始书籍比例与达到最终效果的比例,在这里viewScaleWidth和viewScaleHeight bitmap和外部控件的比例,maxScaleWidth和maxScaleHeight是最终达到效果的比例,也就是说画布在扩大的时候按照原始书籍通过动画系数一直到最终比例。

private void refreshData() {
if (coverBitmap == null) {
return;
}
viewScaleWidth = coverWidth / coverBitmap.getWidth();
viewScaleHeight = coverHeight / coverBitmap.getHeight();
bookRect = new Rect(0, 0, coverBitmap.getWidth(), coverBitmap.getHeight());
resetWidthHeight();
}

private void resetWidthHeight() {
if (coverBitmap != null) {
maxScaleWidth = (float) width / coverBitmap.getWidth();
maxScaleHeight = (float) height / coverBitmap.getHeight();
}
}

float scaleX = viewScaleWidth + (maxScaleWidth - viewScaleWidth) * scale;
float scaleY = viewScaleHeight + (maxScaleHeight - viewScaleHeight) * scale;

canvas.scale(scaleX, scaleY);

链接地址
github链接
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

总结

【Android 详细知识点思维脑图(技能树)】

image

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

虽然 Android 没有前几年火热了,已经过去了会四大组件就能找到高薪职位的时代了。这只能说明 Android 中级以下的岗位饱和了,现在高级工程师还是比较缺少的,很多高级职位给的薪资真的特别高(钱多也不一定能找到合适的),所以努力让自己成为高级工程师才是最重要的。

这里附上上述的面试题相关的几十套字节跳动,京东,小米,腾讯、头条、阿里、美团等公司19年的面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。

由于篇幅有限,这里以图片的形式给大家展示一小部分。

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

id的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1572663.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STL--deque

deque 容器deque是一个双向队列(double-ended queue),可以在队列的两端进行元素的插入和删除操作。deque 和 vector 非常相似。也采用dynamic array(动态数组) 来管理元素,提供随机访向,并有着和 vector 几乎一模一样…

jenkins+docker实现可持续自动化部署springboot项目

目录 一、前言 二、微服务带来的挑战 2.1 微服务有哪些问题 2.2 微服务给运维带来的挑战 三、可持续集成与交付概述 3.1 可持续集成与交付概念 3.1.1 持续集成 3.1.2 持续交付 3.1.3 可持续集成与交付核心理念 3.2 可持续集成优点 3.3 微服务为什么需要可持续集成 四…

anaconda虚拟环境安装apex0.1教程win10

我安装apex0.1的环境是:torch(gpu)1.8.0,cuda10.2,cuda7.6.5。 第一步:下载对应的pytorch、cuda、cudnn版本 这里就不详细介绍了,具体可以参考我的这篇博文win10中anaconda创建虚拟环境配置py…

Redis(性能管理、主从复制、哨兵模式)概述及部署

目录 一、性能管理 1、查看Redis内存使用 2、内存碎片率 3、跟踪内存碎片率 4、内存使用率 5、内回收key 二、Redis集群有三种模式 三、Redis主从复制 1、主从复制的概念 2、主从复制的作用 3、主从复制的流程 4、搭建Redis主从复制 1.环境准备 2.安装Redis&#…

如何选择和注册域名,域名有什么作用,什么是域名解析?域名的需要多少钱?

大家好欢迎来到易极赞,今天我们来跟大家聊一下“如何选择和注册域名”这个话题。 域名用来做什么? 域名对您的网站至关重要,因为它代表您的品牌名称并充当网站的地址。对于企业主来说,一个令人难忘的域名有助于建立在线形象和客户…

RabbitMQ3.13.x之七_RabbitMQ消息队列模型

RabbitMQ3.13.x之七_RabbitMQ消息队列模型 文章目录 RabbitMQ3.13.x之七_RabbitMQ消息队列模型1. RabbitMQ消息队列模型1. 简单队列2. Work Queues(工作队列)3. Publish/Subscribe(发布/订阅)4. Routing(路由)5. Topics(主题)6. RPC(远程过程调用)7. Publisher Confirms(发布者…

嵌入式Qt QGridLayout网格布局管理器

一.QGridLayout网格布局管理器 //以行为单位 设置比例系数 void QGridLayout::setRowStretch ( int row, int stretch ) //以列为单位 设置比例系数 void QGridLayout::setColumnStretch ( int column, int stretch ) 实验: Widget.h: #ifndef _WIDGE…

了解强化学习算法 PPO

🍉 CSDN 叶庭云:https://yetingyun.blog.csdn.net/ 介绍: PPO 算法,即 Proximal Policy Optimization(近端策略优化),是一种强化学习算法。它的主要目的是改进策略梯度方法,使得训练…

numpy二维与三维数组简单操作示例

1.运行PowerShell然后输入python 2.在python命令行输入 import numpy as np进入导入numpy库并添加别名为np 3.使用numpy的zeros函数创建一个2行4列的全0矩阵 4.查看上面创建的全0矩阵 5.查看矩阵类型 6.使用numpy的ones函数创建一个2行4列全1的矩阵 ,并查看类型及矩阵中的数据 …

JavaScript中堆栈内存管理机制及其在深拷贝与浅拷贝场景中的应用与解析

一.堆栈的定义 1.栈是一种特殊的线性表。其特殊性在于限定插入和删除数据元素的操作只能在线性表的一端进行。 结论:后进先出(Last In First Out),简称为LIFO线性表。 栈的应用有:数制转换,语法词法分析&…

小小总结之二分查找三种情况

小小总结之二分查找三种情况 二分查找主要难点在于: 起始条件 left,right的取值,一般若闭合区间,则0, length(nums)。如果涉及边界位置代入计算,则0,length(nums)。循环条件,第一要能够避免死循环,第二要看…

最优乘车

题目描述 H 城是一个旅游胜地,每年都有成千上万的人前来观光。为方便游客,巴士公司在各个旅游景点及宾馆,饭店等地都设置了巴士站并开通了一些单程巴上线路。每条单程巴士线路从某个巴士站出发,依次途经若干个巴士站,…

网络网络层之(3)IPv6地址

网络网络层之(3)IPv6协议 Author: Once Day Date: 2024年4月2日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 全系列文档可参考专栏:通信网络技术_Once-Day的…

JQuery(一)---【JQuery简介、安装、初步使用、各种事件】

零.前言 在学习JQuery前,您需要具备以下知识: HTML相关知识(DOM)CSS相关知识JavaScript相关知识 一.JQuery 1.1JQuery简介 JQuery是一个JavaScript的“函数库”,不是JavaScript的一个框架,与“VUE、REACT”有本质区别&#x…

Java栈和队列的实现

目录 一.栈(Stack) 1.1栈的概念 1.2栈的实现及模拟 二.队列(Queue) 2.1队列的概念 2.2队列的实现及模拟 2.3循环队列 2.4双端队列(Deque) 一.栈(Stack) 1.1栈的概念 栈:一种特殊的线性表,其 只允许在固定的一端进行插入和删除元素操作…

【详细讲解0基础如何进入IT行业】

🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…

【HTML】常用CSS属性

文章目录 前言1、字体和文本属性2、边距和填充3、border边框4、列表属性 前言 上一篇我们学习了CSS扩展选择器以及它的继承性,对于页面元素样式设置相信大家都不陌生了。 这一篇我们就来看看具体都有哪些样式可以设置?又该如何设置? 喜欢的【…

爬虫 新闻网站 以湖南法治报为例(含详细注释,控制台版) V2.0 升级自定义查询关键词、时间段

目标网站:湖南法治报 爬取目的:为了获取某一地区更全面的在湖南法治报已发布的宣传新闻稿,同时也让自己的工作更便捷 环境:Pycharm2021,Python3.10, 安装的包:requests,csv&#xff…

Tailwind 4.0 即将到来:前端开发的“速度与激情”

随着前端开发技术的不断进步,我们每天都在寻找更快、更简洁的解决方案来提升我们的开发效率和用户体验。今天,我要为大家介绍一项令人振奋的新技术进展——Tailwind 4.0的来临! 对于经常使用Tailwind的朋友们来说,这个消息无疑是激…

java 常见API(Objects)

定义 API就是别人定义好的工具类和工具包目的:避免重复造轮子,提升开发效率,更加专注于实现业务逻辑 Object 类 object类是所有类的祖宗类,所有的类型都是可以使用Object的方法的 最常见的三个方法: toString:print就会…