最近遇到一个问题:
我们在显示一张图片时,需要的效果像:
使用ImageView需要固定宽高比,但给定图片的宽高比是不一样的,怎么使内容在view 中,且图片不变形呢?这时候,单纯的使用ImageView的ScaleType属性不是让图片变形就是我们要显示的内容点被切除出去了。
ios方面:图片根据内容中心点移动位置:
https://github.com/totemtec/UIImageViewAligned
android方面:我试过两种方法
一:在设置ImageView的图片前,先根据获取的BitMap重新切出一个新的bitmap
使用的方法是createBitmap(bitmap, x, y,bitmap.getWidth() - x, (int) (bitmap.getWidth() * 0.65526316d));x,y是计算出来要从该位置开始切出一个一个长宽比例为0.65526316d 的bitmap后放入ImageView 中。
这个方法目前只对长比宽大的情况下有效,当宽比长大时会出错。而且对内存也有影响。
代码如下:
//x1,y1是内容点在图片上的比例点
double x1 = 0.6;
double y1 = 0.7;
//拿到获得的bitmap的宽高
int imgw = bitmap.getWidth();
int imgh = bitmap.getHeight();
//计算内容点的坐标
int w = (int) (imgw * x1);
int h = (int) (imgh * y1);
//计算我们切出bitmap的起始点,如果内容点原本就在imageview
//的前半部分,我们就不需要在切出来了
int x = (show_img.getWidth() / 2 >= w) ? 0 : (w - show_img.getWidth() / 2);
int y = (show_img.getHeight() / 2 >= h) ? 0 : (h - show_img.getHeight() / 2);
//新建一个bitmap
Bitmap bi = Bitmap.createBitmap(bitmap, x, y, img1.getWidth() - x, (int) (img1.getWidth() * 0.65526316d));
show_img.setImageBitmap(bi);
二:使用ImageView 的setImageMatrix()方法,将图片按计算出来的数据平移,将内容移动到ImageView区域,这里必须要将ImageView的属性android:scaleType=”matrix”设置为matrix。
这里使用imageLoader三方库来加载图片,记得使用前初始化它
imageLoader的使用情趣看其他人的、、
//初始化imageLoader
imageLoader.init(ImageLoaderConfiguration.createDefault(ImgListviewActivity.this));
下面是关键代码:
//原图,我们常用的
imageLoader.displayImage(list.get(position), holder.img,getOptions());
//移动图,借用Listener能获取到它的bitmap
imageLoader.displayImage(list.get(position), holder.show_img, getOptions(), new SimpleImageLoadingListener() {
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap bitmap) {
super.onLoadingComplete(imageUri, view, bitmap);
ImageView imgv = (ImageView) view;
Matrix matrix = new Matrix();
float bitmapWidth = bitmap.getWidth();
float bitmapHeight = bitmap.getHeight();
//内容中心点所在图片的比例坐标
float Face_center_x = 0.5f;
float Face_center_y = 0.5f;
//缩放比例、使图片填充满view
float Scale = (imgv.getHeight() / bitmapHeight >= imgv.getWidth() / bitmapWidth) ? imgv.getHeight() / bitmapHeight : imgv.getWidth() / bitmapWidth;
matrix.postScale(Scale, Scale);
//缩放后的图片宽高
float scaleBitmapWidth = Scale * bitmapWidth;
float scaleBitmapHeight = Scale * bitmapHeight;
if (scaleBitmapWidth > scaleBitmapHeight) { //宽度图
//移动的距离计算,下方有解释
float translate = (imgv.getWidth() / 2 >= Face_center_x * scaleBitmapWidth) ? 0 : ((Face_center_x * scaleBitmapWidth) - imgv.getWidth() / 2);
if (scaleBitmapWidth - translate <= imgv.getWidth()) {
translate = scaleBitmapWidth - imgv.getWidth();
}
matrix.postTranslate(-translate, 0);
} else { //高度图
float translate = (imgv.getHeight() / 2 >= Face_center_y * scaleBitmapHeight) ? 0 : ((Face_center_y * scaleBitmapHeight) - imgv.getHeight() / 2);
if (scaleBitmapHeight - translate <= imgv.getHeight()) {
translate = scaleBitmapHeight - imgv.getHeight();
}
matrix.postTranslate(0, -translate);
}
imgv.setImageMatrix(matrix);
imgv.setImageBitmap(bitmap);
}
});
计算移动距离的公式
float translate = (imgv.getWidth() / 2 >= Face_center_x * scaleBitmapWidth) ? 0
: ((Face_center_x * scaleBitmapWidth) - imgv.getWidth() / 2);
if (scaleBitmapWidth - translate <= imgv.getWidth()) {
translate = scaleBitmapWidth - imgv.getWidth();
}
这是宽度图的计算公式
imgv.getWidth() / 2 >= Face_center_x * scaleBitmapWidth 是判断内容中心点在左边多远,需不需要平移。如图
下面是判断会不会移动过头,造成右边出现空白的情况
if (scaleBitmapWidth - translate <= imgv.getWidth()) {
translate = scaleBitmapWidth - imgv.getWidth();
}
getOptions()是图片加载的一些情况
public DisplayImageOptions getOptions() {
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.ic_launcher) // 设置图片下载期间显示的图片
.showImageForEmptyUri(R.drawable.ic_launcher) // 设置图片Uri为空或是错误的时候显示的图片
.showImageOnFail(R.drawable.ic_launcher) // 设置图片加载过程中发生错误显示的图片
.cacheInMemory(true) // 设置下载的图片是否缓存在内存中
.cacheOnDisc(true) // 设置下载的图片是否缓存在SD卡中
.build(); // 创建配置过得DisplayImageOption对象
return options;
}
设置View的宽高方法:
private int width = 0;
private int height = 0;
private void scaleImage(ImageView view) {
//获取屏幕的宽高
WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
if (width == 0) {
width = outMetrics.widthPixels;
}
if (height == 0) {
height = (int) (width * 0.65526316d);
}
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
if (params == null) {
params = new LinearLayout.LayoutParams(width, height);
} else {
params.height = height;
params.width = width;
}
view.setLayoutParams(params);
}
这个方法每个图片加载都会走三遍,我也不清楚情况、、、
如果有其他方法或者你发现的缺陷,请告知我,谢谢。