一、有图有真相

二、简单分析

1. ListView 3D实现整体布局使用自定义ListView, 只是继承自ListView父类的父类AdapterView,具体实现可参考之前写的文章:

《Android 自己动手写ListView学习其原理 3 ItemClick,ItemLongClick,View复用》

2. 3D效果其实是伪3D,每个Item绘制两次并存垂直显示就是上面的效果。

三、具体实现步骤分析

1. 预留宽度和高度, 因为每一个Item都需要会滚动,需要宽和高都预留出来一些空间。

/**

* 向当前ListView添加子视图并负责Measure子视图操作

*

* @param child 需要添加的ListView子视图(Item)

* @param layoutMode 在顶部添加上面添加还是在底部下面添加子视图 , LAYOUT_MODE_ABOVE 或 LAYOUT_MODE_BELOW

*/

private void addAndMeasureChild(View child, int layoutMode) {

LayoutParams params = child.getLayoutParams();

if (params == null) {

params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

}

// addViewInLayout index?

final int index = layoutMode == LAYOUT_MODE_ABOVE ? 0: -1;

child.setDrawingCacheEnabled(true);

addViewInLayout(child, index, params, true);

final int itemWidth = (int) (getWidth() * ITEM_WIDTH);

child.measure(MeasureSpec.EXACTLY | itemWidth, MeasureSpec.UNSPECIFIED);

}

疑问?

MeasureSpec.EXACTLY | itemWidth 进行位运算,以后可分析下MeasureSpec.EXACTLY等三个模式具体的值相关知识。

private int getChildMargin(View child) {

return (int)(child.getMeasuredHeight() * (ITEM_VERTICAL_SPACE - 1) / 2);

}

private int getChildTop(View child) {

return child.getTop() - getChildMargin(child);

}

private int getChildBottom(View child) {

return child.getBottom() + getChildMargin(child);

}

private int getChildHeight(View child) {

return child.getMeasuredHeight() + 2 * getChildMargin(child);

}

效果图

四、改变移动界面效果

@Override

protected boolean drawChild(Canvas canvas, View child, long drawingTime) {

// 当前Item左侧顶部坐标值

int left = child.getLeft();

int top = child.getTop();

// 当前Item中部偏移

int centerX = child.getWidth() / 2;

int centerY = child.getHeight() / 2;

// 当前Item针对于ListView居中坐标

float pivotX = left + centerX;

float pivotY = top + centerY;

// 计算离中间位置的距离

float centerScreen = getHeight() / 2;

// ?

float distFromCenter = (pivotY - centerScreen) / centerScreen;

// 计算缩放和旋转

float scale = (float)(1 - SCALE_DOWN_FACTOR * (1 - Math.cos(distFromCenter)));

float rotation = 30 * distFromCenter;

canvas.save();

canvas.rotate(rotation, pivotX, pivotY);

canvas.scale(scale, scale, pivotX, pivotY);

super.drawChild(canvas, child, drawingTime);

canvas.restore();

return false;

}

效果图

疑问,这两个计算公式都不知道为什么要这样写,仅直到什么,怎样用,不知道为什么要这样写?

float distFromCenter = (pivotY - centerScreen) / centerScreen;

float scale = (float)(1 - SCALE_DOWN_FACTOR * (1 - Math.cos(distFromCenter)));

五、添加3D效果

@Override

protected boolean drawChild(Canvas canvas, View child, long drawingTime) {

final Bitmap bitmap = child.getDrawingCache();

if (bitmap == null) {

return super.drawChild(canvas, child, drawingTime);

}

// 当前Item左侧顶部坐标值

int left = child.getLeft();

int top = child.getTop();

// 当前Item中部偏移

int centerX = child.getWidth() / 2;

int centerY = child.getHeight() / 2;

// 计算离中间位置的距离

float centerScreen = getHeight() / 2;

// 计算缩放

// ?

float distFromCenter = (top + centerY - centerScreen) / centerScreen;

float scale = (float)(1 - SCALE_DOWN_FACTOR * (1 - Math.cos(distFromCenter)));

// 计算旋转

float childRotation = mListRotation - 20 * distFromCenter;

childRotation %= 90;

if (childRotation < 0) {

childRotation += 90;

}

// 绘制当前Item

if (childRotation < 45) {

// 菱角朝上时 - 下侧3D

drawFace(canvas, bitmap, top, left, centerX, centerY, scale, childRotation - 90);

// 正中心显示的Item

drawFace(canvas, bitmap, top, left, centerX, centerY, scale, childRotation);

} else {

// 正中心显示的Item

drawFace(canvas, bitmap, top, left, centerX, centerY, scale, childRotation);

// 菱角朝上时 - 上侧3D

drawFace(canvas, bitmap, top, left, centerX, centerY, scale, childRotation - 90);

}

return false;

}

/**

* 绘制3D界面块

*

* @param canvas drawChild回调提供的Canvas对象

* @param view

* @param top

* @param left

* @param centerX

* @param centerY

* @param scale

* @param rotation

*/

private void drawFace(final Canvas canvas, final Bitmap view, final int top, final int left,

final int centerX, final int centerY, final float scale, final float rotation) {

// 如果之前没有创建新对象

if (mCamera == null) {

mCamera = new Camera();

}

// 保存,以免以下操作对之后系统使用的Canvas造成影响

mCamera.save();

// 平移和旋转Camera

mCamera.translate(0, 0, centerY);

mCamera.rotateX(rotation);

mCamera.translate(0, 0, -centerY);

// 如果之前没有Matrix创建新对象

if (mMatrix == null) {

mMatrix = new Matrix();

}

mCamera.getMatrix(mMatrix);

mCamera.restore();

// 平移和缩放Matrix

mMatrix.preTranslate(-centerX, -centerY);

mMatrix.postScale(scale, scale);

mMatrix.postTranslate(left + centerX, top + centerY);

// 创建和初始化

if (mPaint == null) {

mPaint = new Paint();

mPaint.setAntiAlias(true);

mPaint.setFilterBitmap(true);

}

//

if (mLightEnabled) {

mPaint.setColorFilter(calculateLight(rotation));

} else {

//

mPaint.setAlpha(0xFF - (int)(2 * Math.abs(rotation)));

}

// 绘制Bitmap

canvas.drawBitmap(view, mMatrix, mPaint);

}

private LightingColorFilter calculateLight(final float rotation) {

final double cosRotation = Math.cos(Math.PI * rotation / 180);

int intensity = AMBIENT_LIGHT + (int)(DIFFUSE_LIGHT * cosRotation);

int highlightIntensity = (int)(SPECULAR_LIGHT * Math.pow(cosRotation, SHININESS));

if (intensity > MAX_INTENSITY) {

intensity = MAX_INTENSITY;

}

if (highlightIntensity > MAX_INTENSITY) {

highlightIntensity = MAX_INTENSITY;

}

final int light = Color.rgb(intensity, intensity, intensity);

final int highlight = Color.rgb(highlightIntensity, highlightIntensity, highlightIntensity);

return new LightingColorFilter(light, highlight);

}

六、扩展学习

1. Canvas与rotate等方法参数含义,作用与使用

2. Camera + Matirx如何使用,与Canvas区别

3. 何时使用Paint

4. 计算公式由来

七、源码下载

八、 参考资料

android listview立体效果,Android 实现ListView 3D效果 - 1相关推荐

  1. Android手机与vr交互暴风魔镜3D效果显示原理

    首先讲到VR,谈谈个人体会,半年前看到淘宝上的vr眼镜盒为了促销标题图片都是非常性感的,还有海量你懂得资源.到最近在淘宝搜索vr暴风魔镜都正规了,而且销售量庞大 还有新闻上很多vr的科技前沿资讯可以看 ...

  2. android之向Gallery中添加倒影3D效果

    step1:新建项目MyGallery3D step2:设计应用的UI界面   /layout/gallery3d.xml <?xml version="1.0" encod ...

  3. Android OpenGL 仿自如 APP 裸眼 3D 效果

    概述 之前看到 自如团队 发布的 自如客APP裸眼3D效果的实现 ,非常有趣,不久后,社区内 Android 的开发者们陆续提供了 Flutter. Android 原生 .Android Jetpa ...

  4. 卷起来了!Android OpenGL仿自如APP裸眼3D效果

    /   今日科技快讯   / 近日,"乘联会"微信公众号发布消息,2021年12月新能源乘用车市场多元化发力,厂商批发销量突破万辆的企业有14家,较前期大幅增多,其中:比亚迪933 ...

  5. html立体魔方图片制作,AI软件如何打造立体魔方 Ai如何使用3D效果快速生成三个面贴图立体魔方...

    矢量图制作软件Adobe Illustrator如何快速生成立体魔方?魔方是立体.多面的,使用Ai软件自带的3D效果三种之一的凸出和斜角,能创建具有凸出和斜角效果的立体魔方.在3D效果中,选择三个面贴 ...

  6. 给你的2D游戏添加3D效果

    作者:numenzq 原文链接:http://www.j2medev.com/Article/ShowArticle.asp?ArticleID=1135 有两种方法给你的2D游戏添加3D效果.你可以 ...

  7. windows真正体验3D效果桌面

    Yod m 3D V1.20_多国语言绿色免费版_系统桌面呈现3D的效果.真正体验3D效果桌面 软件大小:4.1 MB 软件类型:绿色软件 / 免费软件 运行环境:Win2000/WinXP/Win2 ...

  8. android gridview item 点击,Android-取消GridView/ListView item被点击时的效果

    方法一,在控件被初始化的时候设置 gridView.setSelector(new ColorDrawable(Color.TRANSPARENT)); listView.setSelector(ne ...

  9. Android 使用NineOldAndroids实现绚丽的ListView左右滑动删除Item效果

    转载请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/18311877),请尊重他人的辛勤劳动成果,谢谢! 今天还是 ...

最新文章

  1. 8.Deep Interest Evolution Network for Click-Through Rate Prediction论文详解
  2. 大数据时代,如何构建精准用户画像,直击精细化运营
  3. matlab条形图添加误差线_在Excel图表中添加误差线和对误差线进行设置的技巧
  4. Python Django 获取多条记录API
  5. 01_反射_02_反射类的构造方法
  6. c++《VS2008 快捷键大全》
  7. JS原型链原理(链表)
  8. 开源:OpenJDK8 MIPS64(龙芯)
  9. python-网易云简单爬虫
  10. 静态多层Map缓存清除
  11. 盛金公式解一元三次方程_一元三次方程的解法
  12. 工程经济—技术方案经济效果评价
  13. 人体内部可视化系统市场深度研究分析报告
  14. hadoop生态系统的详细介绍-详细一点
  15. Bootstrap3 Font Awesome 字体图标的基本图标
  16. 层压结构及参数(PCB板层厚度)收集
  17. python数据处理——取dataframe的一列或一行
  18. UART/USRAT协议
  19. php时间戳与日期格式比大小,比较两个时间戳的大小
  20. 清理Xcode占用的Mac硬盘空间

热门文章

  1. 大讲台大数据运维学习笔记
  2. 如何写好技术文档 - 来自 Google 十多年的文档经验!
  3. 关于C语言刷题(#define宏定义函数的常见错误)
  4. WebGIS实战:Vue+Openlayers实现网络地图的加载与切换
  5. Java学习之路:少走弯路,就是捷径
  6. 现行ISO/IEC软件工程国际标准
  7. php多种注释,PHP注释有几种?该如何表示?
  8. 选购投影仪的注意事项都有哪些?详细攻略来了!
  9. ipv6抓包 tcpdump_网络抓包工具tcpdump图文教程
  10. AIX 系统故障之--hd5修复