最近在做Gallery画廊效果时,搜索大量资料,发现很多博主都是2012年写的文章。对于现在的sdk版本,发现拿过来都没有用,效果变形:

非常遗憾,中间的图变形了,或者说没有把转角恢复。

查阅了大量资料后,发现,

4.0以下的版本,调用的是下面的方法:

    @Overrideprotected boolean getChildStaticTransformation(View child, Transformation t) {mMatrix = t.getMatrix();if (android.os.Build.VERSION.SDK_INT > 15) {return false;} else {<span style="white-space:pre">     </span>//操作代码}}

4.0以上版本,调用的是下面的方法:

    /*** 核心方法* @param canvas* @param child* @param drawingTime* @return*/@Overrideprotected boolean drawChild(Canvas canvas, View child, long drawingTime) {boolean ret;//Android SDK 4.1if (android.os.Build.VERSION.SDK_INT > 15) {//操作代码} else {ret = super.drawChild(canvas, child, drawingTime);}return ret;}

修改后兼容4.0以上版本得完整代码:

package com.znke.tv3_test.widgets;import android.content.Context;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Transformation;
import android.widget.Gallery;/*** 兼容4.0以上版本*/
@SuppressWarnings("deprecation")
public class CommonGallery extends Gallery {private Camera mCamera;//相机类private int mGalleryCenterX;//gallery容器的中心点位置private Matrix mMatrix;private int mMaxRotationAngle = 60;//最大转动角度private boolean isNeedScrollY = true;//是否需要y轴角度旋转private float xOffset = 80.0f;private float yOffset = 70.0f;private float zOffset = 50.0f;/*** 设置特定的参数* @param xOffset x轴偏移量* @param yOffset y轴偏移量* @param zOffset z轴偏移量* @param isNeedScrollY 是否需要两侧的图片旋转* @param mMaxRotationAngle 两侧图片旋转的最大角度*/public void setGalleryData(float xOffset,float yOffset,float zOffset,boolean isNeedScrollY,int mMaxRotationAngle){setxOffset(xOffset);setyOffset(yOffset);setzOffset(zOffset);setNeedScrollY(isNeedScrollY);setmMaxRotationAngle(mMaxRotationAngle);}public void setmMaxRotationAngle(int mMaxRotationAngle) {this.mMaxRotationAngle = mMaxRotationAngle;}public void setNeedScrollY(boolean needScrollY) {isNeedScrollY = needScrollY;}public void setxOffset(float xOffset) {this.xOffset = xOffset;}public void setyOffset(float yOffset) {this.yOffset = yOffset;}public void setzOffset(float zOffset) {this.zOffset = zOffset;}public CommonGallery(Context context) {this(context, null, 0);}public CommonGallery(Context context, AttributeSet attrs) {this(context, attrs, 0);}public CommonGallery(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init(context, attrs);}private void init(Context context, AttributeSet attrs) {//支持转换 ,执行getChildStaticTransformation方法this.setStaticTransformationsEnabled(true);this.setChildrenDrawingOrderEnabled(true);mCamera = new Camera();}@Overrideprotected int getChildDrawingOrder(int childCount, int i) {// Current selected index.int selectedIndex = getSelectedItemPosition() - getFirstVisiblePosition();if (selectedIndex < 0) {return i;}if (i < selectedIndex) {return i;} else if (i >= selectedIndex) {return childCount - 1 - i + selectedIndex;} else {return i;}}protected void onSizeChanged(int w, int h, int oldw, int oldh) {mGalleryCenterX = getGalleryCenterX();super.onSizeChanged(w, h, oldw, oldh);}//获取父控件中心点 X 的位置protected int getGalleryCenterX() {// + 比 >> 优先级高, x>>1等于x/2,效率高return ((getWidth() - getPaddingLeft() - getPaddingRight()) >> 1) + getPaddingLeft();}//获取 child 中心点 X 的位置protected int getChildCenterX(View child) {// + 比 >> 优先级高return (child.getWidth() >> 1) + child.getLeft();}//计算 child 偏离 父控件中心的 offset 值, -1 <= offset <= 1protected float calculateOffsetOfCenter(View view) {final int pCenter = getGalleryCenterX();final int cCenter = getChildCenterX(view);float offset = (cCenter - pCenter) / (pCenter * 1.0f);//下面两步操作处理,把offset拉回到[-1,1]之间,防止越界offset = Math.min(offset, 1.0f);//当超出1时,取1offset = Math.max(offset, -1.0f);//当小于-1时,取-1return offset;}/*** 计算该view对应的角度** @param child* @return*/private int calculateAngle(View child) {int rotateAngle = 0;//获取child的中心点int childCenterX = getChildCenterX(child);//如果当前child不在中心点,计算出对应的偏移的角度if (childCenterX != mGalleryCenterX) {// 两个中心点距离int distance = mGalleryCenterX - childCenterX;float percent = distance * 1.0f / child.getWidth();rotateAngle = (int) (percent * mMaxRotationAngle);// 得到旋转的角度// 因为distance有可能大于图片的宽度,所以得到角度有可能大于最大的角度if (Math.abs(rotateAngle) > mMaxRotationAngle) {rotateAngle = rotateAngle > 0 ? mMaxRotationAngle : -mMaxRotationAngle;}}return rotateAngle;}/*** 核心方法* @param canvas* @param child* @param drawingTime* @return*/@Overrideprotected boolean drawChild(Canvas canvas, View child, long drawingTime) {boolean ret;//Android SDK 4.1if (android.os.Build.VERSION.SDK_INT > 15) {//计算child与中心点的偏移量final float offset = calculateOffsetOfCenter(child);transformImageBitmap(child,offset);child.setAlpha(1 - Math.abs(offset));final int saveCount = canvas.save();canvas.concat(mMatrix);ret = super.drawChild(canvas, child, drawingTime);canvas.restoreToCount(saveCount);} else {ret = super.drawChild(canvas, child, drawingTime);}return ret;}@Overrideprotected boolean getChildStaticTransformation(View child, Transformation t) {mMatrix = t.getMatrix();if (android.os.Build.VERSION.SDK_INT > 15) {return false;} else {/*** 兼容老版本,VERSION <= 15 才执行*///设置变化之前,要把上面的一个动画清除t.clear();//设置变化的效果为矩阵类型t.setTransformationType(Transformation.TYPE_MATRIX);//计算child与中心点的偏移量final float offset = calculateOffsetOfCenter(child);transformImageBitmap(child,offset);//设置 alpha 变换t.setAlpha(1 - Math.abs(offset));return true;}}/*** 图像变换* @param child* @param offset*/private void transformImageBitmap(View child,float offset){//获取child的宽高的一半final int halfWidth = getChildCenterX(child);final int halfHeight = child.getMeasuredHeight() >> 1;mCamera.save();if(isNeedScrollY){//是否需要角度旋转if (halfWidth == mGalleryCenterX) {//正中间的childViewmCamera.rotateY(0);} else {//两侧的childViewint rotateAngle = calculateAngle(child);mCamera.rotateY(rotateAngle);}}// 平移 X、Y、Z 轴已达到立体效果mCamera.translate(-offset * xOffset, yOffset, Math.abs(offset) * zOffset);//也可设置旋转效果mCamera.getMatrix(mMatrix);//以 child 的中心点变换mMatrix.preTranslate(-halfWidth, -halfHeight);mMatrix.postTranslate(halfWidth, halfHeight);mCamera.restore();}
}

需要说明的是:

1、有的需求对两侧图片的要求是不需要转角,

2、有的对中间图片的大小有要求

3、有的对旁边图片的距离和层叠效果有要求

其实无非就是修改最大转角、是否需要转角、x轴偏移、y轴偏移、z轴偏移等5个参数的修改,故我提供方法:

    /*** 设置特定的参数* @param xOffset x轴偏移量* @param yOffset y轴偏移量* @param zOffset z轴偏移量* @param isNeedScrollY 是否需要两侧的图片旋转* @param mMaxRotationAngle 两侧图片旋转的最大角度*/public void setGalleryData(float xOffset,float yOffset,float zOffset,boolean isNeedScrollY,int mMaxRotationAngle){setxOffset(xOffset);setyOffset(yOffset);setzOffset(zOffset);setNeedScrollY(isNeedScrollY);setmMaxRotationAngle(mMaxRotationAngle);}

其他的逻辑代码都是通用的,根据你自己的需求,只需要设置好这5个参数就可以了。

Android Gallery画廊 兼容4.0以上版本相关推荐

  1. android 7.0 更新apk,Android更新apk兼容7.0和8.0

    /** * 判断版本 */ private void checkVersionUpdate(final Context mContext, final File file) { if (Build.V ...

  2. Android 获取系统语言(兼容7.0)

    转载连接:http://likfe.com/2017/05/10/android-sys-language/ 前言 获取系统当前语言是一个比较常用的功能,在 Android 7.0 系统上旧函数获取到 ...

  3. android SDK buid tools 27.0.3版本离线下载

    哈哈,没错,我就是这么乐于助人~ 免费分享 buid tools 27.0.3的下载地址,我自己也是花了5个积分买的 可以点击下面的链接在百度云盘下载哦~ 链接:https://pan.baidu.c ...

  4. Android开发之下载Apk安装的方法兼容Android7.0和8.0及以上

    具体查看代码: 首先在清单文件配置三个权限读写权限和请求安装权限(兼容Android8.0手机)如下: <!--安装apk权限--><uses-permission android: ...

  5. Android 实现个性的ViewPager切换动画 实战PageTransformer(兼容Android3.0以下)

    转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/40411921 ,本文出自: [张鸿洋的博客] 1.概述 之前写过一篇博文:An ...

  6. Android App 手机兼容平板横竖屏切换

    Android App兼容平板的开发.希望在手机上是竖屏显示,然后在平板上是横竖切换. /*** 判断是否平板设备* @param context* @return true:平板,false:手机* ...

  7. android 使用FileProvider 兼容apk 在7.0版本无法安装

    源头 都是因为一个bug android.os.FileUriExposedException: file:///storage/emulated/0/mwh/app.apk exposed beyo ...

  8. 解决Picasso在Android 5.0以下版本不兼容https导致图片不显示

    近期在项目中遇到了一个问题,使用picasso加载图片在Android5.0以下版本图片显示不来. 由于之前在几个项目中都使用过picasso而且未出现类似问题,觉得值得好好研究一下. 简单定位一下问 ...

  9. Android开发学习之基于ViewPager实现Gallery画廊效果

    通过我们前面的学习,我们知道ViewPager是可以做出近乎完美的滑动体验,回顾整个Android,我们发现Gallery具备同样的特点,于是我们大胆地猜想,Gallery是否和ViewPager之间 ...

最新文章

  1. python 玩公众号游戏_Python入门太难?不如从玩塔防小游戏开始,玩通关就能学会编程...
  2. Win10 UWP开发系列:解决Win10不同版本的Style差异导致的兼容性问题
  3. .NET WebBrowser不与IE或其他进程共享cookie(WebBrowser独立cookie方法)
  4. ie浏览器不支持多行隐藏显示省略号
  5. 八位图 16位图_了解位图
  6. zznu 1996 : 正三角形和圆的爱情
  7. Nginx - 配置
  8. mysql 电商项目(二)
  9. mysql中set names_深入理解mysql SET NAMES和mysql(i)_set_charset的区别
  10. 百度地图绘制大量标注点卡顿问题完美解决
  11. H3C WA4320H-ACN 无线AP改成12V DC供电
  12. 基于MFC的圆环的消隐实现
  13. 1638_chdir函数的功能
  14. 初入职场两件事 入对行,跟对人---Leo读 不是孙振耀写的职场感言 6
  15. 数据库系统概论(第十章: 数据库恢复技术)
  16. 英语这样学最有效------少走弯路的学习方法
  17. 安卓期末作业-仿外卖app-简单app(附下载资源)
  18. 基于Zedboard的PetaLinux
  19. 中国为什么生产不了复印机!
  20. 毕业设计——水库现场信息监控——实现温度、PH值测定——串口服务器转以太网实现数据传输——MySQL——云平台

热门文章

  1. NoteBurner Netflix Video Downloader for Mac(专业Netflix视频下载器)
  2. 删除本地分支和删除远程分支
  3. ASP.NET 调试出现%@ Application Codebehind=Global.asax.cs Inherits=XXX.XXX.Global Language=C# %...
  4. stm32学习笔记-7ADC模数转换器
  5. Pytorch Mobile 之Android Demo源码分析
  6. JavaScript编写的胸罩罩杯尺寸计算器
  7. 数学建模与MATLAB计算之007.MATLAB中的循环语句
  8. Java实现验证码验证功能
  9. 量子比特-智能财税大数据生态网络,8月8日首发上线FFEX
  10. MFC获取当前程序路径