最近在做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. 秋季4类疾病患者忌吃螃蟹
  2. Unity3D笔记 愤怒的小鸟六 弹弓发射小鸟
  3. 我对“POST和GET的区别”的理解
  4. 深入java并发包源码(三)AQS独占方法源码分析
  5. hadoop之 Hadoop2.2.0中HDFS的高可用性实现原理
  6. linux ubuntu 12.04 下默认是安装了openjdk的
  7. linux vim个人配色方案
  8. 微软模拟飞行10 简体中文豪华版 2DVD
  9. 敏捷开发 SCRUM 简介
  10. DPDK ipv4 ip分片与重组
  11. 即时通讯软件到底有哪些呢?
  12. Linux命令:常用进程查看命令
  13. Unity引擎UI模块知识Tree
  14. 23行代码下载逆水寒壁纸图片
  15. 打印资料显示打印服务器错误,打印服务器错误
  16. 0.96寸OLED(二)SPI+DMA刷新OLED
  17. 互联网金融:为什么贷前风控需要进行手机号码验证(联通、移动、电信)
  18. Spring Cloud NetFilx学习
  19. 2021年京东双11购物节如何买才能最优惠?京东双11优惠规则规则
  20. 巧用免费crm系统培养客户忠诚度

热门文章

  1. CentOS-Stream 重置root密码
  2. python 函数计算乘积_Python函数——允许计算两个数的乘积,变成可接收一个或多个数并计算乘积:...
  3. Python用户自定义异常
  4. 广州酷狗计算机科技有限公司支付宝扣费,检查一下,支付宝这个功能你是不是忘了关,每个月都在扣费...
  5. (附源码)计算机毕业设计SSM基于的二手车商城
  6. mac mysql 服务启动不了_macbook:MySql 无法启动解决方法
  7. 宝塔 mysql 启动不了_宝塔面板MySQL无法启动(自动停止)!MySQL如何启动?
  8. 又一随机视频聊天网站内侧了,名字叫QQ偶遇,地址为:http://qq.17ouyu.com/
  9. 健身蓝牙耳机推荐,推荐五款适合健身的蓝牙耳机
  10. 一个生成代码图片的网站