Android 长图大图加载

本文详细介绍了在Android中处理长图和大图的加载与显示,包括只加载可视区域以优化内存使用,实现手势滑动、惯性滑动以及长图加载的完整代码示例。此外,还提到了大图加载和缩放的实现思路。

长图大图加载

需求:在项目开发中需要长图显示以及大图、巨图显示。

1.长图加载

长图加载显示

由于长图大小比较大,占用的内存比较多,所以需要优化加载。

理论:我们只加载需要显示的大小,其他部分不加载。

1.1画出图形

创建一个自定义控件继承View,它需要的参数:

//需要显示的区域
   private Rect mRect;
   //由于需要复用,所有需要option
   private BitmapFactory.Options mOption;
   //长图需要通过手势滑动来操作
   private GestureDetector mGestureDetector;
   //滑动帮助类
   private Scroller mScroller;
   //图片的宽度
   private int mImageWidth;
   //图片的高度
   private int mImageHeight;
   //控件的宽度
   private int mViewWidth;
   //控件的高度
   private int mViewHeight;
   //图片缩放因子
   private float mScale;
   //区域解码器
   private BitmapRegionDecoder mDecode;
   //需要展示的图片,是被复用的
   private Bitmap mBitmap;

构造函数中初始化需要显示的矩形区域、手势识别类、滑动帮助类等

public BigView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        mRect = new Rect();
        mOption = new BitmapFactory.Options();
        mGestureDetector = new GestureDetector(context, this);
        setOnTouchListener(this);
        mScroller = new Scroller(context);
    }

为使用者提供一个输入图片的方法,参数使用输入流,方便使用。

/**
    * 由使用者输入一张图片
    *
    * @param is 图片输入流
    */
   public void setImage(InputStream is) {
       mOption.inJustDecodeBounds = true;
       BitmapFactory.decodeStream(is, null, mOption);

       mImageWidth = mOption.outWidth;
       mImageHeight = mOption.outHeight;
       //开启复用内存
       mOption.inMutable = true;
       //设置格式,减少内存
       mOption.inPreferredConfig = Bitmap.Config.RGB_565;
       mOption.inJustDecodeBounds = false;

       //创建一个区域解码器
       try {
           mDecode = BitmapRegionDecoder.newInstance(is, false);
       } catch (IOException e) {
           e.printStackTrace();
       }
       //刷新
       requestLayout();
   }

在自定义控件测量方法中,得到需要展示区域的大小,保存在Rect中。

/**
     * 在控件测量中把需要内存区域获取,保存在Rect中
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //获取测量的view的大小
        mViewWidth = getMeasuredWidth();
        mViewHeight = getMeasuredHeight();

        mRect.top = 0;
        mRect.left = 0;
        mRect.right = mImageWidth;
        mScale = mViewWidth / (float) mImageWidth;
        mRect.bottom = (int) (mViewHeight / mScale);
    }

在onDraw中画出需要展示的内容

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //如果没有解码器 说明还没有图片,不需要绘制
    if (null == mDecode) {
        return;
    }
    mOption.inBitmap = mBitmap;
    //通过解码器把图解码出来,只加载矩形区域的内容
    mBitmap = mDecode.decodeRegion(mRect, mOption);
    //把得到的矩形局域大小的图片通过缩放因子,缩放成控件大小
    Matrix matrix = new Matrix();
    matrix.setScale(mScale, mScale);
    canvas.drawBitmap(mBitmap, matrix, null);
}

1.2滑动图形

将控件的onTouch事件交给手势识别来处理。

@Override
    public boolean onTouch(View v, MotionEvent event) {
        //将onTouch事件交给手势处理
        return mGestureDetector.onTouchEvent(event);
    }

如果控件由于惯性正在滑动,需要用户在点击的时候,立刻停止滑动,需要使用滑动帮助类强制停止滑动。

/**
    * 手指按下的回调
    */
   @Override
   public boolean onDown(MotionEvent e) {
       //如果移动还没有停止,强制停止
       if (!mScroller.isFinished()) {
           mScroller.forceFinis
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值