Android阅读器放大镜

目录

前言

效果图

实现思路

理解Canvas与Bitmap

Android PorterDuffXfermode模式理解

文末彩蛋

前言

文字选择放大镜,类似于微信阅读器移动选择文字圆形放大镜效果.

扫描二维码关注公众号,回复: 8485947 查看本文章

效果图

 长按移动选择文字,圆形放大镜的作用是为了方便选择文字,效果如下图gif.

实现思路

  当前手指所选中的文字,以这个字为中心,画一个圆圈,上面的圆就实现了.里面的内容,获取的是当前界面的截图,往绘制的圆圈里填充即可,简单的理解你手指移动到哪个位置,就以这个位置为中心截取该圆形大小的内容即可.(当然实现方法较多,这个只是其中一个思路).

理解Canvas与Bitmap

  老生常谈,canvas大家都知道,canvas是画布,bitmap就是字面的意思bit(位)map(图) = 位图.这两者有什么关联吗?

  在Android关于Canvas的API描述中,一开始就如下描述:

To draw something, you need 4 basic components: A Bitmap to hold the pixels, a Canvas to host the draw calls (writing into the bitmap), 
a drawing primitive (e.g. Rect, Path, text, Bitmap), and a paint (to describe the colors and styles for the drawing).

谷歌翻译如下:

想画一些东西的时候,你需要4个基本的组件,一个Bitmap来存储像素,一个Canvas来接收draw的调用(draw的结果是将像素给画到前面所讲的Bitmap中,
一个源,即是你想画的东西(比如矩形,路径,文本,抑或另一个位图),最后就是一个画笔(描述想画的颜色和风格等)

简单这样理解下:canvas就仅仅是画布,类似于你画画所需要的外边框,承载内容的画板,bitmap相当于一个空白的画纸,承载你画画的内容,即你在canvas画的内容,都存储在bitmap上,最后你画完后,需要返回的是这个bitmap,而不是canvas,因为用户直观的看到的是位图bitmap,而不是画布canvas.

因此,Canvas canvas = new Canvas();这种写法没有意义,这个没有bitmap来承载画的内容,严格意义上来说,不可以这样写.

  一般写法

//创建一个width,height的位图
Bitmap bitmap = Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);
//创建一个画布,传入创建好的位图
Canvas canvas = new Canvas(bitmap);

那么此时这个画布的大小就是这个bitmap的大小,此时可以调用canvas.drawCircle,drawRect等方法在bitmap上画所需要的内容了,最后画完后,返回此bitmap.

Android PorterDuffXfermode模式理解

上面对于canvas和bitmap理解后,下面的就好处理了,这个圆形的效果我使用的Android 系统api porterDuffXfermode这个类来实现的.

对于这个类的理解 大家可以看下我这边博客 https://blog.csdn.net/shenshibaoma/article/details/52291620,这篇博客写的比较早,就是使用xfermode来制作特定形状的头像,建议大家码起来.

放大镜效果使用的xfermode src_in模式,即两个图层图片交集后,显示src源图.

 1.获取屏幕截图方法

private Bitmap getScreenBitmap(View view, int x, int y) {
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        Bitmap bmp = view.getDrawingCache();
        if (x + floatViewWidth > bmp.getWidth()) {
            x = bmp.getWidth() - floatViewWidth;
        }
        if (y + floatViewHeight > bmp.getHeight()) {
            y = bmp.getHeight() - floatViewHeight;
        }
        if (x <= 0) {
            x = 0;
        }
        if (y <= 0) {
            y = 0;
        }
        Bitmap bitmap = Bitmap.createBitmap(bmp, x, y, floatViewWidth, floatViewHeight);
        view.setDrawingCacheEnabled(false);
        return bitmap;
    }

 2. 获取屏幕截图后,利用xfermode,最终获取放大镜bitmap,代码如下:

   private Bitmap getMagnifierBitmap(Bitmap source, View view) {
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        Bitmap target = Bitmap.createBitmap(source.getWidth() + 2, source.getHeight() + 2, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(target);
        canvas.drawCircle((source.getWidth() + 2) / 2, (source.getHeight() + 2) / 2, source.getHeight() / 2, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(source, 1, 1, paint);
        paint.setXfermode(null);
        paint.setColor(view.getContext().getResources().getColor(R.color.lib_reader_page_background_night));
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setFilterBitmap(true);
        paint.setDither(true);
        paint.setStrokeCap(Paint.Cap.ROUND);
        canvas.drawCircle((source.getWidth() + 2) / 2, (source.getWidth() + 2) / 2, source.getHeight() / 2 + 1, paint);
        return target;
    }

 上述两个方法就是核心方法,不超过50行代码,主要是实现的思路.

  3.最后在onTouchMove的时候不断刷新圆心位置,不断的刷新放大镜里面的bitmap即可实现该效果.

  建议大家码起来!

文末彩蛋

 厉害的是,谷歌在Android P增加了文字的放大镜效果,提升了用户体验.

https://mp.weixin.qq.com/s/UDXOw7ArKzvESSt65Ln4fw

或许实现的思路和我的类似吧!

发布了60 篇原创文章 · 获赞 109 · 访问量 36万+

猜你喜欢

转载自blog.csdn.net/shenshibaoma/article/details/81329680