安卓3D效果的实现

说明:

        通过继承已有的控件,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()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

休以希

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值