您好,欢迎来到源码搜藏!分享精神,快乐你我!提示:担心找不到本站?在百度搜索“源码搜藏”,网址永远不丢失!
  • 首 页
  • 在线工具
  • Android 加载大图 可以高清显示10000*10000像素的图片,轻松实现

    时间:2017-01-03 09:24 来源:互联网 作者:源码搜藏 浏览:收藏 挑错 推荐 打印

    LargeImage

    Android的加载大图可以高清显示10000 * 10000的像素图片
    可以滑动,放大缩小具有的PhotoView效果的
    普通图片也。可以用它展示

    摇篮

     compile 'com.shizhefei:LargeImageView:1.0.4'
    

    下载演示APK

    效果

    图片

    使用方法

    <com.shizhefei.view.largeimage.LargeImageView
        android:id="@+id/imageView"
        android:scrollbars="vertical|horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    

    代码

    largeImageView = (LargeImageView) findViewById(R.id.imageView);
    
    //通过文件的方式加载sd卡中的大图
    largeImageView.setImage(new FileBitmapDecoderFactory(file));
    
    //通过流的方式加载assets文件夹里面的大图
    largeImageView.setImage(new InputStreamBitmapDecoderFactory(getAssets().open(ss[position])))
    
    //加载普通大小图片
    largeImageView.setImage(R.drawable.cat);
    largeImageView.setImage(drawable);
    largeImageView.setImage(bitmap);
    

    支持的事件

        largeImageView.setOnClickListener(onClickListener);
        largeImageView.setOnLongClickListener(onLongClickListener);
    

    设置是否可以缩放

     largeImageView.setEnabled(true);
    

    钩临界值(不设置的话会使用默认的计算缩放最小倍数和最大倍数)

    /**
     * Hook临界值
     */
    public interface CriticalScaleValueHook {
    
        /**
         * 返回最小的缩放倍数
         * scale为1的话表示,显示的图片和View一样宽
         *
         * @param largeImageView
         * @param imageWidth
         * @param imageHeight
         * @param suggestMinScale 默认建议的最小的缩放倍数
         * @return
         */
        float getMinScale(LargeImageView largeImageView, int imageWidth, int imageHeight, float suggestMinScale);
    
        /**
         * 返回最大的缩放倍数
         * scale为1的话表示,显示的图片和View一样宽
         *
         * @param largeImageView
         * @param imageWidth
         * @param imageHeight
         * @param suggestMaxScale 默认建议的最大的缩放倍数
         * @return
         */
        float getMaxScale(LargeImageView largeImageView, int imageWidth, int imageHeight, float suggestMaxScale);
    
    }
    

    例如

       largeImageView.setCriticalScaleValueHook(new LargeImageView.CriticalScaleValueHook() {
            @Override
            public float getMinScale(LargeImageView largeImageView, int imageWidth, int imageHeight, float suggestMinScale) {
                return 1;
            }
    
            @Override
            public float getMaxScale(LargeImageView largeImageView, int imageWidth, int imageHeight, float suggestMaxScale) {
                return 4;
            }
        });
    

    加载网络的图片,先下载本地,通过再加载图片的文件
    比如滑行加载图片,具体代码查看演示

        String url = "http://img.tuku.cn/file_big/201502/3d101a2e6cbd43bc8f395750052c8785.jpg";
        Glide.with(this).load(url).downloadOnly(new ProgressTarget<String, File>(url, null) {
            @Override
            public void onLoadStarted(Drawable placeholder) {
                super.onLoadStarted(placeholder);
                ringProgressBar.setVisibility(View.VISIBLE);
                ringProgressBar.setProgress(0);
            }
    
            @Override
            public void onProgress(long bytesRead, long expectedLength) {
                int p = 0;
                if (expectedLength >= 0) {
                    p = (int) (100 * bytesRead / expectedLength);
                }
                ringProgressBar.setProgress(p);
            }
    
            @Override
            public void onResourceReady(File resource, GlideAnimation<? super File> animation) {
                super.onResourceReady(resource, animation);
                ringProgressBar.setVisibility(View.GONE);
                largeImageView.setImage(new FileBitmapDecoderFactory(resource));
            }
    
            @Override
            public void getSize(SizeReadyCallback cb) {
                cb.onSizeReady(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
            }
        });
    

    实现原理

    只加载显示的区域的图片,切成小块拼接。

    LargeImageView

    根据滚动和缩放事件scrollTo对应的位置,计算当前显示区域的图片绘制出来

    UpdateImageView

    监听视图的显示区域的变化,然后加载显示区域内应该显示的图片区域,然后绘制到视图上
    的UpdateView负责监听显示区域的变化的视图,子类通过重写onUpdateWindow(矩形visiableRect)监听显示区域,大部分代码源于SurfaceView监听代码

    BlockImageLoader负责加载显示区域的图片块。

    实现细节:

    每次LargeImageView的的onDraw方法都会调用ImageManagerd的getDrawData(浮动imageScale,矩形imageRect)方法,imageRect为在视图上图片显示的区域(需要加载的图片区域),imageScale假设等于4的话,就是查看上显示1像素,图像要加载4个像素的区域(缩小4倍的图片)
    getDrawData(浮动imageScale,矩形imageRect)实现细节:
    。手势移动,图片显示区域会变化比如显示区域是800 800,向右移动2像素,难道要重新加载800 800的图片区域?所以我采用了图片切块的操作,分块的优化

    1.比如图片显示比例是1,那么要横向分多少份才,纵向分多少分,才合理?图片显示比例是4,横向分多少份才,纵向分多少分,才合理。

    所以我采用了基准块(图片比例是1,一个图片块的宽高的合理SISE)BASE_BLOCKSIZE = context.getResources()getDisplayMetrics()heightPixels / 2 + 1; 
    图片缩放比例为1的话,图片块宽高是BASE_BLOCKSIZE 
    图片缩放比例为4的话,图片块宽高是4 * BASE_BLOCKSIZE 
    图片没被位移,那么屏幕上显示横向2列,纵向getDisplayMetrics()。heightPixels / BASE_BLOCKSIZE行

    2.因为手势放大缩小操作要加载不同清晰度的图片区域,比如之前的图片缩放是4,现在缩放是4.2,难道要重新加载?

    通过公众诠释getNearScale(浮动imageScale)方法计算趋于2的指数次方的值(1,2,4,8,16),
    比如3.9和4.2和4比较接近,就直接加载图片显示比例为4的图片块

    3.之前没加载的区域,难道要空白显示么?

    为了避免加载出现白色块,我会缓存当前比例的加载的图片块,以及2倍比例的图片块(之前加载过,并且当前还属于当前显示区域的,如果不是的话也不缓存它),所以发现没有的话去拿其他比例的图片区去显示

    4.难道只加载显示区域?

    当然,还会去加载旁边一部分没显示的区域的图片块

    5.onDraw方法是UI线程,调用getDrawData(浮动imageScale,矩形imageRect)加载图片块的方法怎么不卡住

    getDrawData只返回之前加载过的图片块,而没有加载的是通过LoadHandler.sendMessage去加载LoadHandler的循环是通过HandlerThread线程创建的循环,也就是开个线程加载。

    每加载一个图片块通过onImageLoadListenner.onBlockImageLoadFinished();的onDraw重绘
    的onDraw又调用getDrawData加载,直至需要显示的图片块加载完成

    Android 加载大图 可以高清显示10000*10000像素的图片,轻松实现转载请注明出处http://www.codesocang.com/kj/imageview/34276.html 源码搜藏网所有源码来自用户上传分享,版权问题及牵扯到商业纠纷均与源码搜藏网无关
    标签: