mobile28365-365-365bet体育在线公司备用-英国365客服

android 超长图显示的几种方法

android 超长图显示的几种方法

问题:用ImageView控件加载长图的时候会遇到这样的一个问题,同一张长图在有些机型可以正常显示,但是在部分机型确显示不了。

原因:当APP开启硬件加速的时候,GPU对于openglRender 渲染有一个限制值,超过了这个限制值,就无法渲染,不同的手机会有不同的限制值;

j针对这一问题,统计了一下几种解决方法:

1.关闭硬件加速:

在清单文件AndroidManifest.xml中设置:

或者在对应的View中设置:

setLayerType(View.LAYER_TYPE_SOFTWARE, null);

注:这样的确解决了图片加载问题,但你会在app运行的时候,发现app变得十分卡顿,影响体验,不推荐使用。

2.通过获取手机openglRender 的限制值,判断超过这个限制的话,对图片进行压缩:

<1.获取限制值

/**

* 获取手机显示最长图片的限制值

* @return

*/

public static int getOpenglRenderLimitValue() {

int maxsize;

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

maxsize = getOpenglRenderLimitEqualAboveLollipop();

} else {

maxsize = getOpenglRenderLimitBelowLollipop();

}

return maxsize == 0 ? 4096 : maxsize;

}

private static int getOpenglRenderLimitBelowLollipop() {

int[] maxSize = new int[1];

GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, maxSize, 0);

return maxSize[0];

}

private static int getOpenglRenderLimitEqualAboveLollipop() {

EGL10 egl = (EGL10) EGLContext.getEGL();

EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);

int[] vers = new int[2];

egl.eglInitialize(dpy, vers);

int[] configAttr = {

EGL10.EGL_COLOR_BUFFER_TYPE, EGL10.EGL_RGB_BUFFER,

EGL10.EGL_LEVEL, 0,

EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT,

EGL10.EGL_NONE

};

EGLConfig[] configs = new EGLConfig[1];

int[] numConfig = new int[1];

egl.eglChooseConfig(dpy, configAttr, configs, 1, numConfig);

if (numConfig[0] == 0) {// TROUBLE! No config found.

}

EGLConfig config = configs[0];

int[] surfAttr = {

EGL10.EGL_WIDTH, 64,

EGL10.EGL_HEIGHT, 64,

EGL10.EGL_NONE

};

EGLSurface surf = egl.eglCreatePbufferSurface(dpy, config, surfAttr);

final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;// missing in EGL10

int[] ctxAttrib = {

EGL_CONTEXT_CLIENT_VERSION, 1,

EGL10.EGL_NONE

};

EGLContext ctx = egl.eglCreateContext(dpy, config, EGL10.EGL_NO_CONTEXT, ctxAttrib);

egl.eglMakeCurrent(dpy, surf, surf, ctx);

int[] maxSize = new int[1];

GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, maxSize, 0);

egl.eglMakeCurrent(dpy, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE,

EGL10.EGL_NO_CONTEXT);

egl.eglDestroySurface(dpy, surf);

egl.eglDestroyContext(dpy, ctx);

egl.eglTerminate(dpy);

return maxSize[0];

}

<2.通过Glide加载:

Glide.with(context).load(path).into(new SimpleTarget() {

@Override

public void onLoadStarted(Drawable placeholder) {

super.onLoadStarted(placeholder);

}

@Override

public void onLoadFailed(Exception e, Drawable errorDrawable) {

super.onLoadFailed(e, errorDrawable);

}

@Override

public void onResourceReady(GlideDrawable resource, GlideAnimation glideAnimation) {

dismissLoading();

//获取图片的宽高

int height = resource.getIntrinsicHeight();

int width = resource.getIntrinsicWidth();

//与限制值进行判断,重新设置宽高

if (height > getOpenglRenderLimitValue()) {

width = width * getOpenglRenderLimitValue() / height;

height = getOpenglRenderLimitValue();

//图片转bitmap

Bitmap bitmap = ImageUtil.drawable2Bitmap(resource);

//根据新的宽高比进行图片压缩

Bitmap result = ImageUtil.mixCompress(context,bitmap, null,height,width);

if (result != null) {

view.setImageBitmap(result);

}

}else {

//小于限制值,则直接显示

view.setImageDrawable(resource);

}

}

});

<3.Drawable转Bitmao

// Drawable转换成Bitmap

public static Bitmap drawable2Bitmap(Drawable drawable) {

Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),

drawable.getIntrinsicHeight(), drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);

Canvas canvas = new Canvas(bitmap);

drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());

drawable.draw(canvas);

return bitmap;

}

<4.图片压缩

/**

* 混合终极方法(尺寸、质量、JNI压缩)

*

* @param image bitmap对象

* @param filePath 要保存的指定目录

* @Description: 通过JNI图片压缩把Bitmap保存到指定目录

*/

public static Bitmap mixCompress(Context context,Bitmap image, String filePath,int Height,int Width ) {

// 最大图片大小 1000KB

int maxSize = 1000;

// 获取尺寸压缩倍数

int ratio = getRatioSize(context,Width, Height);

// 压缩Bitmap到对应尺寸

Bitmap result = Bitmap.createBitmap(Width / ratio, Height / ratio, Bitmap.Config.ARGB_8888);

Canvas canvas = new Canvas(result);

Rect rect = new Rect(0, 0, Width/ ratio, Height / ratio);

canvas.drawBitmap(image, null, rect, null);

ByteArrayOutputStream baos = new ByteArrayOutputStream();

// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中

int quality = 100;

result.compress(Bitmap.CompressFormat.JPEG, quality, baos);

// 循环判断如果压缩后图片是否大于最大值,大于继续压缩

while (baos.toByteArray().length / 1024 > maxSize) {

// 重置baos即清空baos

baos.reset();

// 每次都减少10

quality -= 10;

// 这里压缩options%,把压缩后的数据存放到baos中

result.compress(Bitmap.CompressFormat.JPEG, quality, baos);

}

return result;

}

/**

* 计算缩放比

*

* @param bitWidth 当前图片宽度

* @param bitHeight 当前图片高度

* @return

* @Description:函数描述

*/

public static int getRatioSize(Context context,int bitWidth, int bitHeight) {

// 图片最大分辨率

int imageHeight =ImageViewerUtil.getOpenglRenderLimitValue();

// 缩放比

int ratio = 1;

// 缩放比,由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可

if (bitWidth > bitHeight && bitWidth > imageHeight) {

// 如果图片宽度比高度大,以宽度为基准

ratio = bitWidth / imageHeight;

} else if (bitWidth < bitHeight && bitHeight > imageHeight) {

// 如果图片高度比宽度大,以高度为基准

ratio = bitHeight / imageHeight;

}

// 最小比率为1

if (ratio <= 0)

ratio = 1;

return ratio;

}

通过以上步骤,就可以正常显示了;

3.通过自定义View:

参考鸿洋大神的Android 高清加载巨图方案 拒绝压缩图片

4.引用第三方库:

工具类SubsamplingScaleImageView

总结:

2方法在imageview的基础上进行显示,可应用于显示的控件必须为ImageView的场景; 3,4的方法原理都是一样的,都是继承View,作用于直接显示图片,非常方便;

相关推荐