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

相关推荐

  1. Android基础-定义view

    2024-04-05 04:20:03       11 阅读
  2. Android开发中定义View实现RecyclerView下划线

    2024-04-05 04:20:03       29 阅读
  3. Android定义View保存为Bitmap图片

    2024-04-05 04:20:03       30 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-05 04:20:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-05 04:20:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-05 04:20:03       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-05 04:20:03       20 阅读

热门阅读

  1. uniapp路由传参存在数据类型失真的问题

    2024-04-05 04:20:03       18 阅读
  2. 企业为什么选择高防服务器?

    2024-04-05 04:20:03       15 阅读
  3. postcss安装和使用

    2024-04-05 04:20:03       19 阅读
  4. 蓝桥杯复训之区间dp

    2024-04-05 04:20:03       20 阅读
  5. vector

    vector

    2024-04-05 04:20:03      19 阅读
  6. Redis 和 Memcached 之间有什么优点或缺点吗?

    2024-04-05 04:20:03       23 阅读
  7. 【前端开发】教程及案例.docx

    2024-04-05 04:20:03       21 阅读
  8. Go语言中如何正确使用getter和setter

    2024-04-05 04:20:03       18 阅读
  9. LeetCode //C - 981. Time Based Key-Value Store

    2024-04-05 04:20:03       21 阅读
  10. 【无标题】html中使用div标签的坏处

    2024-04-05 04:20:03       16 阅读
  11. 【积累】mysql

    2024-04-05 04:20:03       19 阅读
  12. mysql常见故障

    2024-04-05 04:20:03       24 阅读
  13. 4.2总结

    4.2总结

    2024-04-05 04:20:03      16 阅读
  14. 【leetcode面试经典150题】10.跳跃游戏 II(C++)

    2024-04-05 04:20:03       19 阅读