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

这里利用自定义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学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux基础篇:Linux网络yum源——以配置阿里云yum源为例

Linux网络yum源——以阿里云为例 一、网络yum源介绍 Linux中的YUM(Yellowdog Updater, Modified)源是一个软件包管理器,它可以自动处理依赖关系并安装、更新、卸载软件包。YUM源是一个包含软件包的远程仓库,它可以让用户轻松地安…

用户账号和组账号及管理

用户账号和组账号 Linux中每个用户是通过 User Id (UID)来唯一标识的 新建用户 1-60000 自动分配 0-65535 端口号,系统是靠uid来区分用户身份的,用户的uid 为0 就是超级管理员 1.用户账号的类型 超级管理员:权限最高的用户,roo…

Flutter Web 的未来,Wasm Native 即将到来

早在去年 Google I/O 发布 Flutter 3.10 的时候就提到过, Flutter Web 的未来会是 Wasm Native ,当时 Flutter 团队就表示,Flutter Web 的定位不是设计为通用 Web 的框架,类似的 Web 框架现在有很多,而 Flutter 的定位…

[lesson06]内联函数分析

内联函数分析 常量与宏回顾 C中的const常量可以替代宏常数定义,如: C中是否有解决方案替代宏代码片段? 内联函数 C中推荐使用内联函数替代宏代码片段 C中使用inline关键字声明内联函数 内联函数声明时inline关键字必须和函数定义结合在…

营销中的归因人工智能

Attribution AI in marketing 归因人工智能作为智能服务的一部分,是一种多渠道算法归因服务,根据特定结果计算客户互动的影响和增量影响。有了归因人工智能,营销人员可以通过了解每个客户互动对客户旅程每个阶段的影响来衡量和优化营销和广告…

深入理解计算机系统 家庭作业 2.83

要读懂题目挺难的 A. 假设我们要求的无穷串是x0.yyyyyyy... Y(0.y<<ky) (由YB2Uk(y)得到,B2Uk是一个截断成k位的函数) x0.yyyyy...(这是我们假设的) 于是有 Yx y.yyyyyy... Yx y.yyyyyy... x<<k Yx-x xY(-1) B. a.Y5 k3 ,x5/7 b.Y6 k4 ,x6/152/5 c…

JavaScript权威指南(第7版) 笔记 - 扩展操作符总结

扩展操作符 ... &#xff0c;不是真正意义上的JavaScript操作符。 let str "0123ABC" console.log(typeof ...str);// Uncaught SyntaxError: Unexpected token ... 上面的第2行代码会报错&#xff0c;… 操作符只能在数组字面量、对象字面量、函数调用中使用。 在…

python-基础篇-字符串、列表、元祖、字典-字符串

文章目录 2.3字符串、列表、元祖、字典2.3.1字符串2.3.1.1字符串介绍2.3.1.1.1python中字符串的格式&#xff1a;2.3.1.1.2字符串在内存中的存储方式 2.3.1.2字符串的输入输出2.3.1.2.1字符串输出2.3.1.2.2字符串输入2.3.1.2.3组字符串的方式 2.3.1.3下标和切片2.3.1.3.1下标索…

vscode 连接远程服务器 服务器无法上网 离线配置

离线配置 vscode 连接远程服务器 .vscode-server 1. .vscode-server下载 使用vscode连接远程服务器时会自动下载配置.vscode-server文件夹&#xff0c;如果远程服务器无法联网&#xff0c;则需要手动下载 1&#xff09;网址&#xff1a;https://update.code.visualstudio.com…

AttributeError: ‘Text‘ object has no property ‘FontSize‘

在学习《机器学习理论与实践》——1 机器学习编程语言基础中&#xff0c;使用Matplotlib画图&#xff08;在坐标轴或绘图区显示中文&#xff09;时&#xff0c;产生AttributeError: Text object has no property FontSize 错误解决。 AttributeError: Text object has no prop…

响应跨域的两种方式

第一种&#xff1a; Configuration public class CorsConfication {Beanpublic CorsWebFilter corsWebFilter() {UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource();CorsConfiguration corsConfiguration new CorsConfiguration();//1、配置跨…

【随笔】Git 高级篇 -- 整理提交记录(上)(十五)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

蓝桥集训之垒骰子

蓝桥集训之垒骰子 核心思想&#xff1a;矩阵乘法 f[i]存顶面数值 构造a矩阵 使得*f[i] f[i-1]a 则f[i] f[1] * an 快速幂优化 #include <iostream>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;const int N 6,m…

虚良SEO-蜘蛛池的作用与工作原理

蜘蛛池是一种SEO优化工具&#xff0c;其主要作用是吸引搜索引擎蜘蛛到特定网站进行爬行和索引&#xff0c;从而提高网站的可见性和排名。下面分别介绍蜘蛛池的作用和工作原理。 蜘蛛池的作用&#xff1a; 提高网站收录&#xff1a; 当一个网站新发布时&#xff0c;或者长时间…

Revit模型进入虚幻引擎UE5教程

一、背景 小伙伴们是否有Revit进入虚幻引擎交互的需求呢&#xff1f; 二、实现功能 1.Revit进入虚幻UE5,包含模型属性&#xff0c;材质等 2.实现BIM构件点选&#xff0c;高亮&#xff0c;属性展示 3.实现BIM模型分层显示&#xff0c;爆炸等效果 三、教程地址 教程&#x…

前端三剑客 —— CSS (第四节)

目录 内容回顾&#xff1a; 1.常见样式 2.特殊样式 特殊样式 过滤效果 动画效果 动画案例&#xff1a; 渐变效果 其他效果&#xff1a; 多列效果 字体图标&#xff08;icon&#xff09; 内容回顾&#xff1a; 1.常见样式 text-shadow x轴 y轴 阴影的模糊程度 阴影的…

C++设计模式:策略模式(二)

1、定义与动机 定义一系列算法&#xff0c;把它们一个个封装起来&#xff0c;并且使它们可互相替换&#xff08;变化&#xff09;&#xff0c;该模式使得算法可独立于使用它的客户程序&#xff08;稳定&#xff09;而变化&#xff08;扩展&#xff0c;子类化&#xff09; 在软…

【QT入门】 Qt代码创建布局综合运用:仿写腾讯会议登陆界面

往期回顾&#xff1a; 【QT入门】 Qt代码创建布局之水平布局、竖直布局详解-CSDN博客 【QT入门】 Qt代码创建布局之栅格布局详解-CSDN博客 【QT入门】 Qt代码创建布局之分裂器布局详解-CSDN博客 【QT入门】 Qt代码创建布局综合运用&#xff1a;仿写腾讯会议登陆界面 一、界面分…

YOLO V8-Detection 【单张图片】 推理详解及部署实现

前言 在实际处理过程中&#xff0c;我们使用YOLO V8进行推理时&#xff0c;通常会针对一张图片进行推理。如果需要对多张图片进行推理&#xff0c;则可以通过一个循环来实现对图片逐张进行推理。 单张图片推理时&#xff0c;需要注意图片的尺寸必须是32的倍数&#xff0c;否则…

【氮化镓】缓冲层结构对GaN HEMT射频性能的影响

【Effect of different layer structures on the RF performance of GaN HEMT devices】 研究总结&#xff1a; 本研究探讨了不同缓冲层结构对氮化镓高电子迁移率晶体管&#xff08;GaN HEMT&#xff09;射频性能的影响。通过对比三种不同缓冲层结构的GaN HEMT设备&#xff0…