说明:
通过继承已有的控件,Gallery,实现自定义的效果
效果展示:
二、创建适配器类,设置相应的相关
1、创建适配器,继承BaseAdapter
定义构造方法,传入上下文Context和图片ID的数组(int[] imageIDs)
在构造方法中创建ImageView的数组
2、重写适配器中的相关方法:
①getCount:返回的个数为ImageView数组的个数
②getItem:返回的对象为ImageView数组中对应的元素
③getItemId:返回的是对应的位置的view的id
④getView:返回的是ImageView数组中对应的元素
3、创建“生成带有倒影效果的图片”的方法:
通过for循环,对每个图片进行相似的操作:
①通过BitmapFactory的decodeResource方法,找到原始图片
需要使用到原始图片的宽和高,获取出来getWidth()和getHeight()
②生成倒影图片:通过Bitmap的createBitmap方法
参数:
* source 生成倒影图片所使用的原图片
* x, y 左上角位置
* width, height 倒影图片的宽高
* Matrix m, 图片样式
Matrix的setScale方法中的两个参数:
// x轴 -1 水平翻转
// y轴 -1 垂直翻转
// 1 正常
设置其中的矩阵Matrix水平和垂直的翻转值为-1(setScale方法),从而达到倒影的效果
③合成图片:
创建新的bitmap,传入画布canvas(),通过canvas绘制新图:
@绘制原始图片:drawBitmap,传入原始图片的对象
@绘制原图片与倒影图片之间的缝隙,调用drawRect的方法,通过画笔绘制(绘制矩形)
@绘制倒影图片:drawBitmap:传入倒影图片的对象
在倒影图片上进行遮盖和透明效果的绘制(即相同的画布区间上)
&创建新画笔(paint),绘制遮罩和渐变的效果,使得倒影更真实
¥遮罩:setXfermode(模式):将模式传入进去
¥渐变:setShader(着色器),需要线性渐变(LinearGradient);设置画笔的着色器:paint.setShader(shader);
其中LinearGradient构造函数接收的参数如下:
* x0, y0:第一个点的坐标
* x1, y1:第二个点的坐标
* color0:起始点的颜色
* color1:终止点的颜色
* tile :填充模式
线性渐变填充 shader着色器
//在位图上Y方向花砖模式 0x70ffffff, 0x00ffffff
TileMode:(一共有三种)
CLAMP :如果渲染器超出原始边界范围,会复制范围内边缘染色。
REPEAT :横向和纵向的重复渲染器图片,平铺。
MIRROR :横向和纵向的重复渲染器图片,这个和REPEAT 重复方式不一样,他是以镜像方式平铺。
@绘制矩形:drawRect:其中接收上面创建的画笔。
④显示合成图片:
创建ImageView
设置图片对象:bitmap(上面创建的bitmap)
将最终的ImageView添加到数组中
为了达到所有图片相同的宽高,设置布局参数:
imageView.setLayoutParams(new GalleryFlow.LayoutParams(160,240));
三、实现效果
1、初始化数据
定义方法initData(),初始化数据,定义数组,将对应的图片设置进去
imageIDs = new int[]{…..}
2、找到对应的控件,转换为Gallery
gallery = (GalleryFlow) findViewById(R.id.gallery);
3、创建适配器,传入定义的数组(填充了数据(图片))
adapter = new ImageAdapter(this, imageIDs);
4、调用适配器中生成带有倒影效果图片的方法,需要在添加适配器前调用的
adapter.createReflectionBitmap();
5、给Gallery设置适配器
gallery.setAdapter(adapter);
----------------------------------------带有倾斜效果的3D效果-----------------------------------------
一、处理构造方法
在构造方法中调用:,实现变形(倾斜)效果
二、创建获取控件(Gallery)和图片的中心点位置的方法
1、获取gallery中心点的位置
Tips:
*在实际开发中,控件并不是全部填充屏幕的,可能还有会边界,或者边上有抽屉,所有就不能使用getWidth()/2获取
*可以通过计算的方法,算出控件(gallery)的中心点的位置,如图:
要想获得蓝色(即gallery中心点位置)的距离,计算如下:
将边界的距离减去;再用整个距离除以2,就得到控件(Grally)的一半;
除以2是获得黄色的距离,还需要加上左边pidding的距离,就获得了蓝色的距离
【(getWidth() - getPaddingLeft() - getPaddingRight())/2 + getPaddingLeft()】
2、获取图片中心点的方法:
Tips:
可直接获取到图片距离左边的距离,加上图片宽度的一半即可:
【child.getLeft() + child.getWidth()/2】
三、定义变量:
1、需要用到一些值:
//最大旋转角度值
private int maxRotateAngle = 50;
//最大缩放值
private int maxZoom = -250;
//控件中心点的距离
private int galleryOfCenter;
//图片中心点的距离
private int childOfCenter;
//实现变形,是没有改变图片的,只是观察的角度的不同,这就可以通过摄像机,进行角度的观察,从而达到图片的变形
private Camera camera = new Camera();
2、给控件中心点位置赋值
复写onSizeChanged方法:控制尺寸大小,在改变的时候激活此方法
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
galleryOfCenter = galleryOfCenter();
四、图像变形
需要重写方法:protected boolean getChildStaticTransformation(View child, Transformation t)
参数1:接收的图像view
2:旋转的动画?
返回值:true:动作不需要向下传递,即销毁;false:动作不销毁
1、变量赋值:
①、给图片的中心点位置赋值:childOfCenter = ViewOfCenter(child);
②、获取图片的宽度
2、指定图片变化的风格:
①、为了防止重叠,清空上次的参数:t.clear()
②、在变形前,需要指定变形的风格
3、对图片进行变形:
①、图片处于控件(Gallery)的正中心,即控件和图片的中心点重合时,不变形,即变形的角度值设置为0
②、图片和控件两者的中心点不同,需要变形,变形的角度随着图片所处的位置计算
角度值(rotateAngle) = (屏幕中心点距离—图像中心点距离)/ 当前图片宽度* 最大旋转角度值
将此值进行强转,获得一个具体的角度,而不是int类型,
需要将角度值控制在正负50度之间;如果角度大于50度,设置为50度
五、图像变形的方法
1、创建对应变形的方法:
①、先录制下记录的效果:保存下来:camera.save()
②、获取相应参数:
通过传入的Transformation获取矩阵Matrix【imageMatrix】
得到旋转的角度(不看方向):Math.abs(rotate):传入的角度
图片的宽高
初始化变形图片(即图片为原始状态):指定摄像机观察的角度为正常角度?:camera.translate(0.0f, 0.0f, 100.0f);
③、当旋转角度小于最大旋转角度(50度)
缩放处理:通过其对应的角度值计算缩放值【需要设置为float类型】,然后通过translate设置
透明度处理:通过对应的角度值计算透明度:child.setAlpha((int) (255 - rotateAngle * 2.5));
2、可以分别参照X、Y、Z三个轴进行倾斜旋转(以摄像机的角度)
3、将当前效果应用在矩阵上:camera.getMatrix(imageMatrix);
4、以图片中心点进行缩放:
需要以中心为轴,让上下进行缩放;在图像变化之前,将参照点设置到图像的最中间
就需要将图像向左移动一半,向上移动一半
在缩放之后,还需要还原回去,在将图像向右移动一半,在向下移动一半
添加两个方法:
imageMatrix.preTranslate(-(imageWidth/2), -(imageHeight/2));
imageMatrix.postTranslate((imageWidth/2), (imageHeight/2));
Tips:
①、不加此方法:
默认情况下,动画是以对象的左上角为起点的,如果这样的话,动画的效果就变成了可见对象在它的左上角开始,逐渐向右下角扩大,这显然不是我们期望的。
②、使用此方法:
所以我们前面用到的halfWidth,halfHeight就用到了,这里保存了可见对象的一半宽度和高度,也就是中点,使用上面这两个方法后,就会改变动画的起始位置,动画默认是从右下角开始扩大的,使用matrix.preTranslate(-halfWidth, -halfHeight) 就把扩散点移到了中间。同样,动画的起始点为左上角,使用matrix.postTranslate(halfWidth, halfHeight)就把起始点移到了中间;这样就实现我们期望的效果了。
Preconcats matrix相当于右乘矩阵
Postconcats matrix相当于左乘矩阵
5、图像还原:
将上次记录的效果还原:还原
camera.restore()