美文网首页Android知识互联网科技Android开发经验谈
Android自定义View_BitmapShader实现望远镜

Android自定义View_BitmapShader实现望远镜

作者: 付十一v | 来源:发表于2019-03-06 21:52 被阅读14次

    日拱一卒,功不唐捐

    一、背景

    这个特效来源于有一天逛网站的时候,一家网站实现了这样的一个效果:在你向下滚动页面的时候,他的背景的图片随着你的滑动,以窗口的方式展示着图片的某一部分。浏览完就想着以Android的方式能不能实现,也就演变成了以下的效果。


    Telescope

    二、知识点BitmapShader

    【官方】Shader用于绘制位图作为纹理。位图可以设置模式为重复或镜像或平铺。

    简单来说,Shader可以用来实现一些渐变,反转,镜像,重复等效果。本文的效果核心使用的是Shader中的BitmapShader——位图Shader。

    BitmapShader(Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY)

    从构造方法可以看出,第一个参数为位图bitmap,第二个和第三个参数分别为横方向和纵方向的平铺模式。
    平铺模式有如下几种模式:

    • CLAMP :拉伸,水平拉伸图片左右方向最后一个像素,,垂直拉伸图片上下方向的最后一个像素。
    • MIRROR:镜像,水平和垂直方向重复图像,交替镜像,使相邻的图像始终相连。
    • REPEAT:重复,水平和垂直方向不断重复图片。

    三、基本思路

    1、创建一张图片,将画笔设置为带有图像填充功能;
    2、根据获取手指所点击位置的坐标,根据获得的坐标绘制圆形或者其他图形。

    四、实现

    从上述基本思路来看,步骤还是很简单,那么接下来分析实现的代码。

            mPaint = new Paint();
            mBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.photo2);
    

    首先就是初始化画笔和创建一张位图。接下来为核心内容。

            mPaint.setShader(new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
            canvas.drawCircle(400,400,300,mPaint);
    

    BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)新创建一个BitmapShader,并将水平和垂直方向的平铺模式设置为CLAMP拉伸模式,将BitmapShader属性设置给画笔,使画笔具有图像填充功能,这是后面画笔可以绘制出一个带有图片的圆形的原因。接着利用Canvas在坐标(400,400)处绘制出一个半径为300的圆形。
    目前基本的绘制已经结束,运行代码可以看出会有圆形图片在界面显示,如下图:

    Paint.jpeg
    从上面的图片来看,是不是发现其实这就是一个圆形的头像,到这里我们可以想到前面有一篇Android自定义菱形图片使用PorterDuffXfermode的相关属性绘制菱形的头像,其实这里我们也可以使用BitmapShader进行操作,代码相比较更加简洁。
    目前实现的是静态的图像,接下来实现随着手指动态移动的效果。
    private float mTouchEventY = -1;
    private float mTouchEventX = -1;
     ......
    
     @Override
        public boolean onTouchEvent(MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mTouchEventX = event.getX();
                    mTouchEventY = event.getY();
                    return true;
                case MotionEvent.ACTION_MOVE:
                    mTouchEventX = event.getX();
                    mTouchEventY = event.getY();
                    postInvalidate();
                    break;
            }
            postInvalidate();
            return super.onTouchEvent(event);
        }
    

    首先我们创建两个全局变量mTouchEventX,mTouchEventY。在onTouchEvent事件中,手指MotionEvent.ACTION_DOWN的时候,动态获取手指的位置,在ACTION_DOWN的代码中记得return true,这涉及到事件的分发机制,当return false时,代表手指的down事件未完成,那么事件将不会继续向下传递,也就是说ACTION_DOWN动作后的ACTION_MOVE是不会触发的。
    同样的,我们在MotionEvent.ACTION_MOVE中也动态获取手指的位置,也就是随着手指动态调整圆形的位置。
    最后在Canvas绘制圆形的时候,将获取到的位置设置进去,随着手指的不断移动,不断获取到位置值,也就实现了动态绘制图像的效果。

    canvas.drawCircle(mTouchEventX,mTouchEventY,300,mPaint);
    

    五、最后

    在上述的过程中,发现BitmapShader可以很容易的实现不规则头像。另外,上述也只使用了BitmapShader的拉伸模式,还有镜像和重复模式可以实现更多的特效,有待发掘。

    文章同步个人博客:https://fuusy.github.io
    项目地址:https://github.com/fuusy/ShaderTelescope.git
    公众号:小猿说

    小猿说.jpg

    相关文章

      网友评论

        本文标题:Android自定义View_BitmapShader实现望远镜

        本文链接:https://www.haomeiwen.com/subject/meztpqtx.html