显示长图的imageView
目前存在的问题是显示过程较慢,日后改进
参考:Android 一个Imageview加载长图,android 加载大图长图失真或者不显示
public class BigImageView extends AppCompatImageView {
public static final int MAX_BITMAP_IMAGE_HEIGHT = 4000;
private int windowWidth;
private BitmapRegionDecoder mDecoder;
private Rect bsrc;
private Rect src;
private Rect dst;
private Paint paint;
private ArrayList<Bitmap> bmps;
public BigImageView(Context context) {
super(context);
init();
}
public BigImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
windowWidth = getResources().getDisplayMetrics().widthPixels;
bmps = new ArrayList<Bitmap>();
src = new Rect();
dst = new Rect();
bsrc = new Rect();
paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
}
@Override
protected void onDraw(Canvas canvas) {
int count = bmps.size();
int drawnHeight = 0;
for (int i = 0; i < count; i++) {
Bitmap bmp = bmps.get(i);
src.left = 0;
src.top = 0;
src.right = bmp.getWidth();
src.bottom = bmp.getHeight();
dst.left = 0;
dst.top = drawnHeight;
dst.right = getWidth();
dst.bottom = dst.top + bmp.getHeight();
drawnHeight = dst.bottom;
canvas.drawBitmap(bmp, src, dst, paint);
}
}
@Override
public void setImageBitmap(final Bitmap bm) {
super.setImageBitmap(bm);
if (bm != null) {
ViewGroup.LayoutParams lp = this.getLayoutParams();
lp.width = windowWidth;
lp.height = bm.getHeight();
this.setLayoutParams(lp);
}
Observable.just(bm)
.map(new Function<Bitmap, Bitmap>() {
@Override
public Bitmap apply(Bitmap bitmap) throws Exception {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
InputStream isBm = new ByteArrayInputStream(baos.toByteArray());
//BitmapRegionDecoder newInstance(InputStream is, boolean isShareable)
//用于创建BitmapRegionDecoder,isBm表示输入流,只有jpeg和png图片才支持这种方式,
// isShareable如果为true,那BitmapRegionDecoder会对输入流保持一个表面的引用,
// 如果为false,那么它将会创建一个输入流的复制,并且一直使用它。即使为true,程序也有可能会创建一个输入流的深度复制。
// 如果图片是逐步解码的,那么为true会降低图片的解码速度。如果路径下的图片不是支持的格式,那就会抛出异常
BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(isBm, false);
final int imgWidth = decoder.getWidth();
final int imgHeight = decoder.getHeight();
BitmapFactory.Options opts = new BitmapFactory.Options();
//计算图片要被切分成几个整块,
// 如果sum=0 说明图片的长度不足MAX_BITMAP_IMAGE_HEIGHTpx,不进行切分 直接添加
// 如果sum>0 先添加整图,再添加多余的部分,否则多余的部分不足MAX_BITMAP_IMAGE_HEIGHT时底部会有空白
int sum = imgHeight / MAX_BITMAP_IMAGE_HEIGHT;
int redundant = imgHeight % MAX_BITMAP_IMAGE_HEIGHT;
//说明图片的长度 < MAX_BITMAP_IMAGE_HEIGHT
if (sum == 0) {
//直接加载
bmps.add(bm);
} else {
//说明需要切分图片
Rect mRect = new Rect();
for (int i = 0; i < sum; i++) {
//需要注意:mRect.set(left, top, right, bottom)的第四个参数,
//也就是图片的高不能大于这里的4096
mRect.set(0, i * MAX_BITMAP_IMAGE_HEIGHT, imgWidth,
(i + 1) * MAX_BITMAP_IMAGE_HEIGHT);
Bitmap bm = decoder.decodeRegion(mRect, opts);
bmps.add(bm);
}
//将多余的不足MAX_BITMAP_IMAGE_HEIGHT的部分作为尾部拼接
if (redundant > 0) {
mRect.set(0, sum * MAX_BITMAP_IMAGE_HEIGHT, imgWidth, imgHeight);
Bitmap bm = decoder.decodeRegion(mRect, opts);
bmps.add(bm);
}
}
postInvalidate();
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
})
.subscribeOn(Schedulers.io())
.subscribe();
}