Bitmap之巨图加载

本文介绍了如何在Android中使用BitmapRegionDecoder处理巨图加载,实现长图的上下左右滑动、双击放大缩小及手指缩放功能。关键步骤包括初始化变量、设置图片、测量控件大小、计算缩放比例、绘制内容及处理各种手势事件。通过内存复用和合理计算采样率,有效减轻内存压力。

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

前言

在Android开发中,有时候会有加载巨图(长图)的需求,可以上下左右滑动,双击放大或缩小,手指缩放。如何加载一个大图而不产生OOM呢?使用体统提供的BitmapRegionDecoder,区域解码器,可以用来解码一个矩形区域(Rect)的图像,有了这个类我们就可以自定义一块矩形的区域,然后根据手势来移动矩形区域的位置就能慢慢看到整张图片了。

效果演示:
在这里插入图片描述

1.初始化变量

public BigImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
   
        super(context, attrs, defStyleAttr);
        //第1步:设置bigImageView需要的成员变量
        //加载显示的区域
        mRect = new Rect();
        mOptions = new BitmapFactory.Options();
        //手勢识别
        mGestureDetector = new GestureDetector(context, this);
        //滚动类
        mScroller = new Scroller(context);
        //缩放手势识别
        mScaleGestureDetector = new ScaleGestureDetector(context, new ScaleGesture() );
        //设置触摸监听
        setOnTouchListener(this);
    }

BitmapFactory.Options我们很熟悉,用来配置Bitmap相关的参数,比如获取Bitmap的宽高,内存复用等参数。

GestureDetector用来识别双击事件,ScaleGestureDetector用来监听手指的缩放事件,都是系统提供的类,比较方便使用。

2.设置需要加载的图片

public void setImage(InputStream is) {
   
        //获取图片的信息,不会将整张图片加载到内存
        mOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(is, null, mOptions);
        //获取图片的宽高信息
        mImageWidth = mOptions.outWidth;
        mImageHeight = mOptions.outHeight;
        //开启内存复用
        mOptions.inMutable = true;
        //设置像素格式
        mOptions.inPreferredConfig = Bitmap.Config.RGB_565;
        //真正意义加载图片
        mOptions.inJustDecodeBounds = false;
        try {
   
            //创建一个区域解码器
            mDecoder = BitmapRegionDecoder.newInstance(is, false);
        } catch (IOException e) {
   
            e.printStackTrace();
        }
        //刷新页面,与invalidate方法相反,只会触发onMeasure和onLayout方法,不会触发onDraw
        requestLayout();
    }

设置需要要加载的图片,无论图片放到哪里都可以拿到图片的一个输入流,所以参数使用输入流,通过BitmapFactory.Options拿到图片的真实宽高。

接下来是设置inMutable,开启内存复用。

关于像素格式设置,inPreferredConfig这个参数默认是Bitmap.Config.ARGB_8888,这里将它改成Bitmap.Config.RGB_565,去掉透明通道,可以减少一半的内存使用。

最后初始化区域解码器BitmapRegionDecoder。需要注意的是newInstance方法中参数false表示不共享输入流,可以理解为BitmapRegionDecoder拷贝了一份输入流,即获得的图片输入流close了,仍然可以进行解码操作。

requestLayout()刷新页面,需要注意与invalidate()的区别,后者请求重绘View树,即onDraw方法,不会触发onMeasure和onLayout方法,刚好相反。

3.测量控件View的宽高,计算缩放因子/比例


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值