android 自定义控件实现3D画廊效果

今天来实现一个3D画廊的效果,这个效果的难点在于计算旋转角度,当然里面会有好几个知识点要讲,针对Paint的2个方法,一个是setShader(),一个是setXfermode(),首先看下大概的效果,


大概是这种,这是我在网上随便找了一个类似的图片,因为我的效果还没写,没关系,这没啥影响,这个效果我准备分开写,然后后面合成起来,上面的效果可以分为如下几步

1:首先是怎么截取一张图片中的一部分

2:怎么把多张图片合成一张图片

3:怎么生成倒影效果,

4:怎么改变倒影中的图片透明度

5:最后一步是怎么计算它滑动时候的旋转角度问题

首先把第一步的效果实现出来,就是怎么截图一张图片中的一部分,如图:


现在开始写代码

public class MainActivity extends Activity {
    private ImageView iv,originalIv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iv = (ImageView) findViewById(R.id.iv);
        originalIv = (ImageView) findViewById(R.id.originalIv);
        originalIv.setImageResource(R.mipmap.gird);
        Bitmap bitmap = compoundBitmap(R.mipmap.gird);
        iv.setImageBitmap(bitmap);
    }
    /**
     * 截图图片
     * @param resId 图片 id
     */
    public Bitmap compoundBitmap(int resId){
        Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(),resId);//把资源图片变成一个Bitmap对象
        //生成下面的一半图片
        Matrix matrix = new Matrix();
        Bitmap invertBitmap = Bitmap.createBitmap(originalBitmap,0,originalBitmap.getHeight()/2,originalBitmap.getWidth(),originalBitmap.getHeight()/2,matrix,false);
        return  invertBitmap;
    }
}
效果:第一个而是原图 第二张是截图一半的图,为了进行更好的对比,


上面就使用了一个Bitmap的createBitmap方法就可以实现截图了,现在对createBitmap的方法参数进行说明

public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,Matrix m, boolean filter)

参数说明:

source:原位图

x:位图的x轴坐标

y:位图的y轴坐标

width:新位图的宽度

height:新位图的高度

m:矩阵

filter:这个参数比较难懂 先看下google官网文档介绍

 true if the source should be filtered.
*                   Only applies if the matrix contains more than just
*                   translation
当进行的不只是平移变换时,filter参数为true可以进行滤波处理,有助于改善新图像质量;flase时,计算机不做过滤处理

画图解释下:


现在怎么考虑把这二张图片合成一张图片了,这个要用到Canvas了,之前我们canvas是从自定义view中的onDraw()方法给我们提供的,现在我们要创建一个画布,然后在这画布上把这二张图片画上去,

代码如下:

/**
 * 合成图片
 * @param resId 图片 id
 */
public Bitmap compoundBitmap(int resId){
    Paint paint = new Paint();
    Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(),resId);//把资源图片变成一个Bitmap对象
    //生成下面的一半图片
    Matrix matrix = new Matrix();
    Bitmap invertBitmap = Bitmap.createBitmap(originalBitmap,0,originalBitmap.getHeight()/2,originalBitmap.getWidth(),originalBitmap.getHeight()/2,matrix,false);
    //创建一个空的位图
    Bitmap compoundBitmap =  Bitmap.createBitmap(originalBitmap.getWidth(),originalBitmap.getHeight()+invertBitmap.getHeight(), Bitmap.Config.ARGB_8888);

    Canvas canvas = new Canvas(compoundBitmap);
    canvas.drawBitmap(originalBitmap,0,0,paint);
    canvas.drawBitmap(invertBitmap,0,originalBitmap.getHeight(),paint);

    return  compoundBitmap;
}
效果:


ok,现在我们实现了2张图片怎么合成一张图片,首先是先绘制一个空的位图,这个位图的宽和高要设置好,然后通过canvas的drawBitmap()把这二张图片绘制到画布上去,绘制上要注意坐标点就行,还有个问题就是截图的一半图片不是垂直的拼接在下面,上面我们讲截图图片一部分的方法createBitmap()方法进行参数说明的时候,其中有一个Matirs矩阵,当时为什么要使用这个方法呢?Bitmap的createBitmap有很多重载的方法,就是因为提供了Matris类,让我们可以对位图进行像动画那样操作,现在看下Matirs一些常用的方法:


我们发现Matris提供了平移,缩放,旋转,透明等操作,我们只要加入一行代码就可以让下面的一半图片改成在原来的图片上进行垂直后显示,

matrix.setScale(1,-1);
 public void setScale(float sx, float sy)

参数说明:

sx:x轴水平翻转 -1表示翻转 1表示不翻转

sy:y轴方向翻转  -1表示翻转 1表示不翻转

/**
 * 合成图片
 * @param resId 图片 id
 */
public Bitmap compoundBitmap(int resId){
    Paint paint = new Paint();
    Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(),resId);//把资源图片变成一个Bitmap对象
    //生成下面的一半图片
    Matrix matrix = new Matrix();
    matrix.setScale(1,-1);
    Bitmap invertBitmap = Bitmap.createBitmap(originalBitmap,0,originalBitmap.getHeight()/2,originalBitmap.getWidth(),originalBitmap.getHeight()/2,matrix,false);
    //创建一个空的位图
    Bitmap compoundBitmap =  Bitmap.createBitmap(originalBitmap.getWidth(),originalBitmap.getHeight()+invertBitmap.getHeight()+10, Bitmap.Config.ARGB_8888);//+10是为了2张图片之间有空隙

    Canvas canvas = new Canvas(compoundBitmap);
    canvas.drawBitmap(originalBitmap,0,0,paint);
    canvas.drawBitmap(invertBitmap,0,originalBitmap.getHeight()+10,paint);
    return  compoundBitmap;
}
效果:



现在我们把前三步实现了,还有个倒影图片的透明度问题,这就使用到Paint中的setShader()方法了,这是设置画笔的颜色渲染方法,发现Shader有5个子类,每一个子类实现的功能效果不一样,



Shader的直接子类以及作用:
BitmapShader    : 位图图像渲染
LinearGradient  : 线性渲染
RadialGradient  : 环形渲染
SweepGradient   : 扫描渐变渲染/梯度渲染
ComposeShader   : 组合渲染,可以和其他几个子类组合起来使用

现在举例讲每个大概的功能,见识下平时效果使我们想不到是通过这个api实现的,

BitmapShader 

先看下它的构造函数:

 public BitmapShader(@NonNull Bitmap bitmap, TileMode tileX, TileMode tileY)

参数说明:

bitmap:渲染器使用的位图

tileX:在位图x轴方向渲染器的平铺模式

tileY:在位图y轴方向渲染器的平铺模式

渲染器的模式有如下三种:

public enum TileMode {
    /**
     * replicate the edge color if the shader draws outside of its
     * original bounds
     */
    
  • 10
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值