Git Product home page Git Product logo

largeimage's Introduction

LargeImage

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

 compile 'com.shizhefei:LargeImageView:1.1.0'

Download Demo apk

效果

image

使用方法

<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临界值(不设置的话会使用默认的计算缩放最小倍数和最大倍数)

/**
 * 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;
        }
    });

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

    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

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

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

实现细节:

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

  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,难道要重新加载?

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

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

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

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

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

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

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

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

主力类库

1.https://github.com/LuckyJayce/ViewPagerIndicator
Indicator 取代 tabhost,实现网易顶部tab,新浪微博主页底部tab,引导页,无限轮播banner等效果,高度自定义tab和特效

2.https://github.com/LuckyJayce/MVCHelper
实现下拉刷新,滚动底部自动加载更多,分页加载,自动切换显示网络失败布局,暂无数据布局,支持任意view,支持切换主流下拉刷新框架。

3.https://github.com/LuckyJayce/MultiTypeView
简化RecyclerView的多种type的adapter,Fragment可以动态添加到RecyclerView上,实现复杂的界面分多个模块开发

4.https://github.com/LuckyJayce/EventBus
事件总线,通过动态代理接口的形式发布,接收事件。定义一个接口把事件发给注册并实现接口的类

5.https://github.com/LuckyJayce/LargeImage
大图加载,可供学习

6.https://github.com/LuckyJayce/GuideHelper
新手引导页,轻松的实现对应的view上面的显示提示信息和展示功能给用户

7.https://github.com/LuckyJayce/HVScrollView
可以双向滚动的ScrollView,支持嵌套ScrollView联级滑动,支持设置支持的滚动方向

8.https://github.com/LuckyJayce/CoolRefreshView
下拉刷新RefreshView,支持任意View的刷新 ,支持自定义Header,支持NestedScrollingParent,NestedScrollingChild的事件分发,嵌套ViewPager不会有事件冲突

有了这些类库,让你6的飞起

说明

其中 android-gesture-detectors-lib 手势类库
源地址https://github.com/Almeros/android-gesture-detectors

联系方式和问题建议

License

Copyright 2015 shizhefei(LuckyJayce)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

largeimage's People

Contributors

luckyjayce avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

largeimage's Issues

关闭硬件加速就显示了

加载大图,关闭硬件加速就可以了!今天我尝试加载688x5360的图片,而Bitmap 最大能显示4096x4096的。而我关闭硬件加速就显示了。。。。。

设置合适的缩放大小应该能够显示全部图片到 view 中

修改如下,当layout的宽大于高的时候,测试没有问题,使用largeImageView.setScale(largeImageView.getFitScale());
设置图片缩放比例时,能够将图片完整显示

设置 0.9 的原因是:如果不设置,则会感觉图片占得太满,0.9 看起来刚刚好

    private void initFitImageScale(int imageWidth, int imageHeight) {
        final int layoutWidth = getMeasuredWidth();
        final int layoutHeight = getMeasuredHeight();
        if (imageWidth < imageHeight) {
            fitScale = 0.9f * imageWidth / imageHeight * layoutHeight / layoutWidth;
        } else {
            fitScale = 0.9f;
        }
        minScale = 0.25f;
        maxScale = 1.0f * imageWidth / layoutWidth;
        float a = (0.9f * imageWidth / layoutWidth) * layoutHeight / imageHeight;
        float density = getContext().getResources().getDisplayMetrics().density;
        maxScale = maxScale * density;
        if (maxScale < 4) {
            maxScale = 4;
        }
        if (minScale > a) {
            minScale = a;
        }
        if (criticalScaleValueHook != null) {
            minScale = criticalScaleValueHook.getMinScale(this, imageWidth, imageHeight, minScale);
            maxScale = criticalScaleValueHook.getMaxScale(this, imageWidth, imageHeight, maxScale);
        }
    }

定位到区域块

你好,我这边需要第一次加载大图,然后中心区域显示大图的某一块,要怎么处理,我这边能先知道left,top, right,bottom

滑动冲突

和Recyclerview,PagerSnapHelper,结合起来做左右滑动,显示大图,有滑动冲突,怎么解决,求

大图加载的时候滑动不流畅

  1. 放大之后滑动图片,不能够流畅地滑动
  2. 缩小图片,会导致图片在屏幕内不见
  3. 如果要实现新浪里面的从中心位置开始缩放,应该要怎么实现呢(大图缩放的时候没有滚动条,想要滚动条出现应该怎么办呢)

请教实现图片循环展示

@LuckyJayce 看到更新了,最近一直在研究这个库,有注释清晰了许多,感谢。

最近项目需求:滑动时将图片进行循环展示,如下示意图所示。
shiyitu

我想在这个库的基础上进行扩展,目前的做法是在ScrollView中添加两个LargeImageView,基本能实现出效果,但是总感觉不是最优解。而且后续还有添加图片覆盖物等各种需求,感觉这个方式不太好处理。

另一个想法是在getDrawData中进行处理,将x轴方向超出图片边界的部分,用图片头部或尾部进行补充,可是一直没实现出来。

而且如果用这种方式的话,如果一直向一个方向滑动,Scale的fromX是会一直增加或一直减少的,如何重置状态也没有想出好的办法。

请问@LuckyJayce能否指点一二,万分感谢。

请问为什么小图片显示不出来?

大图显示效果很不错,但是几百kb的小图片反而显示不了,问什么呢?

我看到了ReadMe有如下内容:
//加载普通大小图片
largeImageView.setImage(R.drawable.cat);
largeImageView.setImage(drawable);
largeImageView.setImage(bitmap);

怎么判断图片是大图还是普通大小?

图片无法解码

03-08 10:43:05.672 809-1142/com.huanmedia.yourchum.debug D/ONE SDK: [2017/3/8 10:43:5:679]: [net] has wifi connection
03-08 10:43:05.672 809-14006/com.huanmedia.yourchum.debug W/System.err:     at android.graphics.BitmapRegionDecoder.nativeNewInstance(Native Method)
03-08 10:43:05.672 809-14006/com.huanmedia.yourchum.debug W/System.err:     at android.graphics.BitmapRegionDecoder.newInstance(BitmapRegionDecoder.java:124)
03-08 10:43:05.682 809-14006/com.huanmedia.yourchum.debug W/System.err:     at android.graphics.BitmapRegionDecoder.newInstance(BitmapRegionDecoder.java:150)
03-08 10:43:05.682 809-14006/com.huanmedia.yourchum.debug W/System.err:     at com.shizhefei.view.largeimage.factory.FileBitmapDecoderFactory.made(FileBitmapDecoderFactory.java:23)
03-08 10:43:05.682 809-14006/com.huanmedia.yourchum.debug W/System.err:     at com.shizhefei.view.largeimage.BlockImageLoader$LoadHandler.handleMessage(BlockImageLoader.java:805)
03-08 10:43:05.692 809-14006/com.huanmedia.yourchum.debug W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
03-08 10:43:05.692 809-14006/com.huanmedia.yourchum.debug W/System.err:     at android.os.Looper.loop(Looper.java:136)
03-08 10:43:05.692 809-14006/com.huanmedia.yourchum.debug W/System.err:     at android.os.HandlerThread.run(HandlerThread.java:61)

OOM问题

ViewPager+fragment配合这个控件做的一个图片浏览效果
前面10几个可能内存还能接受,后面滑动到了20几个的时候就开始OOM异常了。
请教优化方案。谢谢

allowBackup 是否必要

你好,library项目里的 mainfest 里的 allowBackup=true 与 我们的项目产生冲突,请问这个是否可以去除

缩放

长图怎样实现缩放呢?求解。而且,缩放过程没有缩放动画,看起来很僵硬

Image failed to decode using JPEG decoder

09-20 15:55:41.808 14992-15304/W/System.err: java.io.IOException: Image failed to decode using JPEG decoder
09-20 15:55:41.808 14992-15304/W/System.err: at android.graphics.BitmapRegionDecoder.nativeNewInstance(Native Method)
09-20 15:55:41.808 14992-15304/ W/System.err: at android.graphics.BitmapRegionDecoder.newInstance(BitmapRegionDecoder.java:124)
09-20 15:55:41.808 14992-15304/ W/System.err: at com.shizhefei.view.largeimage.factory.InputStreamBitmapDecoderFactory.made(InputStreamBitmapDecoderFactory.java:22)
09-20 15:55:41.808 14992-15304/ W/System.err: at com.shizhefei.view.largeimage.BlockImageLoader$LoadImageInfoTask.doInBackground(BlockImageLoader.java:793)
09-20 15:55:41.808 14992-15304/ W/System.err: at com.shizhefei.view.largeimage.TaskQueue$Task.doInBackground(TaskQueue.java:44)
09-20 15:55:41.808 14992-15304/ W/System.err: at com.shizhefei.view.largeimage.TaskQueue$Task.doInBackground(TaskQueue.java:31)
09-20 15:55:41.808 14992-15304/W/System.err: at android.os.AsyncTask$2.call(AsyncTask.java:292)
09-20 15:55:41.808 14992-15304/ W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:237)
09-20 15:55:41.808 14992-15304/W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
09-20 15:55:41.808 14992-15304/ W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
09-20 15:55:41.808 14992-15304/ W/System.err: at java.lang.Thread.run(Thread.java:818)

OOM

一张图放大缩小这样到处滚动,大图也会OOM

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.