Android学习 图片折叠效果的实现
来源:互联网 发布:c语言心形图案代码 编辑:程序博客网 时间:2024/04/29 22:59
上一篇文章,我们利用Matrix的setPolyToPoly来实现图片的3D旋转,这一次,我们来实现一个漂亮一点的效果,让一张图片像折扇一样可以折叠起来。
具体的效果如下
这个效果是我有一次在DevBytes上看到的一个视频,由Google Android Team的员工介绍的一个效果,不过它们是把这个做成了一个可重复利用的自定义ViewGroup,我当时看了,发现这效果真是太帅了。于是自己就琢磨着应该怎么实现,不过最后,还是跑去GitHub下了它的一份代码,参考着,争取把里面主要的逻辑给理清了,给大家介绍一下。
其实我之所以写前面那篇文章《Android学习小Demo(5)结合Matrix跟Porperty Animatin 实现推拉门效果》,目的只是为了先让大家先熟悉一下matrix的setPolyToPoly方法,因为这个效果的实现就是利用matrix的这个方法的。
下面我们结合一下代码来讲一下思路,然后在最后,大家再下载源代码去学习吧。
在主Activity上,有一个自定义的FoldingView,主要是实现折叠效果的自定义View,下面有一个输入框,用户可以输入数字,表明是要将这张图片分成多少部分,然后点击按钮,开始动画。
1)我们先看一下主Activity中的代码:
- public class MainActivity extends Activity {
- private ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f,1f);
- private PolyToPolyView polyView;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- ...
- valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator arg0) {
- float rotateFactor = (Float)arg0.getAnimatedValue();
- polyView.setRotateFactor(rotateFactor);
- }
- });
- ...
- btnRotate.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- valueAnimator.start();
- }
- });
- }
- ...
- }
这代码其实跟我们前面一篇文章的代码是一样的:
a)定义一个ValueAnimator,在其AnimatorUpdateListener中设置自定义View的旋转因子,并设置图片折叠的份数
b)点击按钮,开始动画。
2)在自定义View中,
a)我们会从资源中获取一张图片,然后根据Activity中输入框的值,将图片分成等宽的长方形,如下:
代码如下:
- bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.photo1);
- bitmapWidth = bitmap.getWidth();
- bitmapHeight = bitmap.getHeight();
- widthPerFold = Math.round((float)bitmapWidth /(float)folds);
- heightPerFold = bitmapHeight;
- for (int i = 0; i < folds; i++) {
- rects[i] = new Rect(i * widthPerFold, 0, i* widthPerFold + widthPerFold, heightPerFold);
- }
- for(int i=0;i<folds;i++){
- matrices[i] = new Matrix();
- }
2)分成相同的等份之后,我们就要考虑如何为每一个长方形设置变化的矩阵了。
2.1)分析拆分出来的矩形区域及折叠时候的效果,可以发现,偶数位(从0开始)的矩形是右边的那两个角往后推,而奇数位的矩形则刚好相反,当偶数位的矩形在往后推的时候,奇数位的矩形则相对着其也在往后推,并且在往后推的同时,每个矩形的宽度缩小的比例也是一致的。所以根据这几点,我们可以先算出一些公用的参数变化,比如每个矩形旋转的比例,平移的距离等等,下面看一下代码:
- translateFactor = 1 - foldFactor;
- translateWidth = bitmapWidth * translateFactor;
- translateWidthPerFold = Math.round(translateWidth / folds);
- foldDrawWidth = widthPerFold < translateWidthPerFold ? translateWidthPerFold : widthPerFold;
- foldDrawHeight = heightPerFold;
- float translateWidthPerfoldsquare = translateWidthPerFold * translateWidthPerFold;
- float deepth = (float)Math.sqrt(foldDrawWidth * foldDrawWidth - translateWidthPerfoldsquare);
- scaleFactor = DEPTH_CONSTANT / (DEPTH_CONSTANT + deepth);
- float scaleWidth = foldDrawWidth * translateFactor; // from 1 to 0, means width becomes small
- float scaleHeight = foldDrawHeight * scaleFactor;
- float topScaleHeightPoint = (foldDrawHeight - scaleHeight) / 2.f;
- float bottomScaleHeightPoint = topScaleHeightPoint + scaleHeight;
- srcPoly[0] = 0;
- srcPoly[1] = 0;
- srcPoly[2] = 0;
- srcPoly[3] = foldDrawHeight;
- srcPoly[4] = foldDrawWidth;
- srcPoly[5] = 0;
- srcPoly[6] = foldDrawWidth;
- srcPoly[7] = foldDrawHeight;
- for (int i = 0; i < folds; i++) {
- matrices[i].reset();
- boolean isEven = (i % 2 == 0);
- dstPoly[0] = i * scaleWidth;
- dstPoly[1] = isEven ? 0 : topScaleHeightPoint;
- dstPoly[2] = dstPoly[0];
- dstPoly[3] = isEven ? foldDrawHeight : bottomScaleHeightPoint;
- dstPoly[4] = (i + 1) * scaleWidth;
- dstPoly[5] = isEven ? topScaleHeightPoint : 0;
- dstPoly[6] = dstPoly[4];
- dstPoly[7] = isEven ? bottomScaleHeightPoint : foldDrawHeight;
- if(dstPoly[4] <= dstPoly[0] || dstPoly[6] <= dstPoly[2]){
- shouldDraw = false;
- return;
- }
- matrices[i].setPolyToPoly(srcPoly, 0, dstPoly, 0, POLY_POINTS / 2);
- }
大家如果仔细看一下,会发现前面计算缩放比例及深度变化等,都跟前面的文章是一样的,关键是后面设置坐标数组的时候,会根据奇偶来判断。
2.2)在数组中,前面4位,分别是左上角,左下角的x,y座标,后面下位,则是右上角和右下角的坐标。对于偶数位矩形来说,在变化的过程中,其x坐标会根据平移和缩放的比例慢慢缩小并往左移,而左边的y坐标则是保持不变的,因为它们是这个矩形的轴,而右边的y坐标,则会根据缩放比例变小,而对于奇数位来说,则刚好相反。
3)第三步,分别利用canvas的save和restore函数保存各个矩形自己的matrix变化,利用clipRect剪裁出各个矩形区域,交将图片的对应的部分画到canvas上。
4)加上一些阴影和渐变交果,让其看起来是有纵容变化的感觉。
- int alpha = (int) (foldFactor * 255 * SHADOW_APLHA);
- paintSolid.setColor(Color.argb(alpha, 0, 0, 0));
- matrixShadowGradient.setScale(foldDrawWidth, 1);
- linearGradientShadow.setLocalMatrix(matrixShadowGradient);
- paintGradientShadow.setAlpha(alpha);
- ...
- if (i % 2 == 0) {
- canvas.drawRect(0, 0, foldDrawWidth, foldDrawHeight, paintSolid);
- } else {
- canvas.drawRect(0, 0, foldDrawWidth, foldDrawHeight, paintGradientShadow);
- }
- Android学习 图片折叠效果的实现
- Android学习小Demo(6)图片折叠效果的实现
- Android使用ExpandableListView实现折叠的效果
- 图片折叠效果CSS实现
- IOS 图片折叠效果实现
- iOS - 图片实现多层折叠效果
- iOS - 图片实现多层折叠效果
- 实现折叠的uitableviewcell效果
- Android使用CollapsingToolbarLayout实现折叠效果
- iOS 图片折叠效果
- jQuery实现的简单折叠菜单(折叠面板)效果代码
- 用javascript实现菜单折叠的效果
- iOS如何实现表格的折叠效果?
- Axure折叠与展开效果的实现
- iOS如何实现表格的折叠效果?
- 补间动画实现折叠的效果
- Android 标题下的内容折叠效果
- android具有折叠效果的控件
- Android头像更换
- HTTP 的keepalive模式
- POJ 2070 Filling Out the Team(水题)
- Oracle 11g Express在Linux下安装配置注意事项
- 数组与指针
- Android学习 图片折叠效果的实现
- 学习OpenCV的学习笔记系列(三)显示图片及视频
- 上传应用程序到App Store 的具体操作流程
- K2 BPM Activity 节点 规则属性
- pthread_cond_timedwait返回EINVAL
- java 集合补充
- TCP/IP详解学习笔记(7)-广播和多播,IGMP协议
- 关于Android SQLite3多线程并发问题,学习笔记。
- ios 自定义Button 不能点击问题