自定义ImageView实现局部截图功能

本文介绍了如何在Android中实现自定义ImageView以实现局部截图功能,允许用户通过拖拽选择截图区域,无论是矩形还是其他形状。文章详细讲解了截图的基础知识和自定义View的关键技术,并给出了实现效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


1、前言


最近在做一个能够自选区域进行局部截图的功能,接下来,会给大家讲解,整个截图的实现过程。笔者这边实现的自选区域的形状是矩形,读者如果有需要,可以根据我给大家讲解的思路,修改成适合自己的截图工具。先来看看效果图



2、效果图




这里的图片是来自笔者对webView的截图产生的,读者可以根据自己的需要,替换上面的图片。

通过拖拽四条边框,可以实现屏幕的局部截图:




拖拽之后,只有需要截图的部分才会高亮显示,其余部分用遮罩掩盖。笔者实现的拖拽四条边都可以任意拖拽,并不一定要正方形或者长方形。也可以如下:






3、截图的基本知识


实现截图功能之前,我们需要了解View为我们提供的截图方法的使用。笔者会尽量详细讲述各个方法,让读者可以比较明白的去自由结合各截图方法的使用。


3.1、截图的基本知识点


在对View进行截图的时候,系统需要将当前View的内容缓存下来,因此,在截图之前,我们需要判断当前View是否允许视图缓存。

public boolean isDrawingCacheEnabled()

如果当前View允许进行视图缓存,会返回true否则返回false。如果返回false,我们就需要设置当前的视图,让它允许视图缓存。


 public void setDrawingCacheEnabled(boolean enabled)

通过设置true来设置当前View,让它可以进行视图缓存。当设置为true,那么接下来调用getDrawingCache或者buildDrawingCache方法,就会给当前视图的内容生成一个bitmap图像。

给当前视图强制生成缓存

public void buildDrawingCache(boolean autoScale)

此方法在视图不可缓存的时候,会强制生成一个视图缓存,autoScale表示是否自适应缩放缓存视图,如果为false的生成的视图大小和View的大小是一致的,true的话,则会根据内容生成自适应大小的图片。但是如果在调用此方法的之前,你没有调用setDrawingEnabled(true)的话,在对生成的视图使用完毕之后,应该对强制生成的视图缓存进行一个清理。清理的方法如下:


public void destroyDrawingCache()


此方法会将缓存的视图内容进行清理,从而对bitmap的资源进行释放回收利用。

获取缓存图像的方法:


public Bitmap getDrawingCache(boolean autoScale)


此方法会将View的视图缓存生成一个bitmap对象并返回,这样我们就可以对view的内容进行截图了。autoscale参数和前面讲述的功能一样。

综合上述知识,使用方法如下:

 if(!webView.isDrawingCacheEnabled())
             webView.setDrawingCacheEnabled(true);
        webView.buildDrawingCache();
        Bitmap cropBitmap = webView.getDrawingCache(true);




4、自定义View的知识点要求


由于我们将会对View的视图内容进行部分截图,所以需要我们自定义一个能够监听用户动作从而产生对应响应的View。关于自定义View的基础知识,读者如果不明白的,可以看笔者的这篇文章 自定义View的基本思路,如果读者有这些基础知识,那么可以接着往下看。

先给一个下面讲解会遇到的局部变量和常量的含义说明,这样会比较容易理解下面的操作逻辑:


//移动过程的xy,imageView的canvas的宽高,点击事件的宽高,源图片的宽高。
    private float moveX,moveY,startWidth,startHeight,downX,downY,bitmapWidth,bitmapHeight;
    private Context context;
    //当前手机的像素密度
    private float density;
    //是否可以开始拖拽选择框
    private boolean isStart=true;
    //分别表示上线,下线,左线,右线
    private Line upLine,downLine,leftLine,rightLine;
    //是否是上线移动,是否是垂直移动,是否是左线移动,是否是水平移动
    //垂直移动分为上线移动和下线移动,垂直移动同理
    private boolean isMovingUpLine=false,isMovingVertical=false,isMovingLeftLine=false,isMovingHorizontal=false;
   //用来给点击点的坐标预留一些空间,便于判断移动时间的判断
    private float padding;
    private Paint paint = new Paint();




笔者将通过实现一个自定义ImageView,来实现一个可拖拽矩形边框,对选中内容高亮显示,对不选的内容进行遮罩掩饰。由于需要监听用户的触摸行为,我们需要实现OnTouchListener接口,如下:


public class ClipImageView extends ImageView implements View.OnTouchListener

当ClipImageView第一次展示的时候,我们需要在它的四周画上矩形边框,如图:




可以看到,在图片和四周的边框之间是有一定的留白的,便于分辨边框和图片的部分。所以我们需要重写OnDraw方法:


 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if(isStart&&moveY==0) {
            //初次布局,绘画四周的边线
            initCanvas(canvas);

        }
        else
        {
            //重画边线和遮罩
            reDraw(canvas);
        }
    }
我们关注iniCanvas方法即可,当前imageView如果是刚刚显示出来并且没有用户触摸动作的产生,就绘制四周的边框。为什么需要判断是否有用户触摸动作呢,因为用户产生触摸动作的时候,View一定是处于可见生命周期,此时就不是第一次绘制视图了,而是需要响应用户触摸行为来绘制视图了。

 /**
     * 初始化布局
     * @param canvas
     */
    private void initCanvas(Canvas canvas) {
        //获取画布的宽高,用于初始化边线的宽高
        startWidth = canvas.getWidth();
        startHeight = canvas.getHeight();
        upLine=new Line(0,0,startWidth,0);
        downLine=new Line(0, startHeight, startWidth, startHeight);
        leftLine=new Line(0,0,0,startHeight);
        rightLine=new Line(startWidth,0,startWidth,startHeight);
        Log.i("上线坐标",upLine.getLeft()+" "+upLine.getTop()+" "+upLine.getRight()+" "+upLine.getBottom() );
        Log.i("下线坐标",downLine.getLeft()+" "+downLine.getTop()+" "+downLine.getRight()+" "+downLine.getBottom() );
        Log.i("左线坐标",leftLine.getLeft()+" "+leftLine.getTop()+" "+leftLine.getRight()+" "+leftLine.getBottom());
        Log.i("右线坐标",rightLine.getLeft()+" "+rightLine.getTop()+" "+rightLine.getRight()+" "+rightLine.getBottom());
        //画出上下左右四条线
        paint.setStrokeWidth(4);
     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值