先说一下问题背景
最近接到一个平板适配需求,其中有一个难点是网络过来的图片如果宽度不够,则要进行在某一位置的横向拉伸。以使其充满view宽度。同时要支持横竖屏切换时宽度变化的场景。在安卓中系统并没有给出相关的东西能实现此功能。于是乎只能自己寻找解决方案。
于是想到一种拉伸bitmap图片以适配view宽度的方法。
- 下面是工具代码:
ini
private Bitmap ninePatchCrop(BitmapPool pool, Bitmap source, int outWidth, int outHeight) {
if (source == null) return null;
// 获取原始图片的宽度和高度
int width = source.getWidth();
int height = source.getHeight();
//原始图片宽,则用原始图片,直接return
if (width >= mImageWidth) {
return source;
} else {
if (outHeight < height) {
source = scaleBitmap(source, outHeight);
}
int newWidth = source.getWidth();
int newHeight = source.getHeight();
// 创建一个新的 Bitmap 用于存储拉伸后的图片,高度直接用原始图片的
Bitmap stretchedBitmap = Bitmap.createBitmap(mImageWidth, outHeight, Bitmap.Config.ARGB_8888);
int length = mImageWidth - newWidth;
// 获取原始图片的像素数组
int[] pixels = new int[newWidth * newHeight];
source.getPixels(pixels, 0, newWidth, 0, 0, newWidth, newHeight);
int size = (int) (newWidth * mPercent);
// 横向拉伸指定区间的像素点
for (int y = 0; y < newHeight; y++) {
for (int x = 0; x < newWidth; x++) {
if (x < size) {
int pixel = pixels[y * newWidth + x];
stretchedBitmap.setPixel(x, y, pixel);
} else if (x == size) {
for (int i = 0; i < length; i++) {
int pixel = pixels[y * newWidth + x];
stretchedBitmap.setPixel(x + i, y, pixel);
}
} else {
int pixel = pixels[y * newWidth + x];
stretchedBitmap.setPixel(x + length - 1, y, pixel);
}
}
}
return stretchedBitmap;
}
}
- 缩小原始bitmap代码。不缩小在遇到原始图片大于实际布局图片时会有问题。
java
/**
* 缩小原始bitmap到指定高度
*
* @param originalBitmap
* @param targetHeight
* @return
*/
private Bitmap scaleBitmap(Bitmap originalBitmap, int targetHeight) {
int originalWidth = originalBitmap.getWidth();
int originalHeight = originalBitmap.getHeight();
// 计算目标宽度,保持原始宽高比
int targetWidth = (int) ((float) originalWidth / originalHeight * targetHeight);
// 使用 Bitmap.createScaledBitmap() 进行缩小
Bitmap scaledBitmap = Bitmap.createScaledBitmap(originalBitmap, targetWidth, targetHeight, true);
// 返回缩小后的 Bitmap
return scaledBitmap;
}
- 将此工具运用到Glide中 GlideNinePatchTransform.java
ini
import android.content.Context;
import android.graphics.Bitmap;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
/**
* Created by lvlufei on 2018/1/8.
* 将图片转化为圆形
*/
public class GlideNinePatchTransform extends BitmapTransformation {
private String mId;
/**
* 外界传过来的图片宽度。高度由于默认不变,所以就不用外面传进来了。另一个原因是算出的高度跟glide中的不太一样
*/
private int mImageWidth;
/**
* 百分比,图片在何处开始拉伸
*/
private float mPercent;
public GlideNinePatchTransform(Context context, String id, int imageWidth, float percent) {
super(context);
this.mId = id;
this.mImageWidth = imageWidth;
this.mPercent = percent;
}
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
return ninePatchCrop(pool, toTransform, outWidth, outHeight);
}
private Bitmap ninePatchCrop(BitmapPool pool, Bitmap source, int outWidth, int outHeight) {
if (source == null) return null;
// 获取原始图片的宽度和高度
int width = source.getWidth();
int height = source.getHeight();
//原始图片宽,则用原始图片,直接return
if (width >= mImageWidth) {
return source;
} else {
if (outHeight < height) {
source = scaleBitmap(source, outHeight);
}
int newWidth = source.getWidth();
int newHeight = source.getHeight();
// 创建一个新的 Bitmap 用于存储拉伸后的图片,高度直接用原始图片的
Bitmap stretchedBitmap = Bitmap.createBitmap(mImageWidth, outHeight, Bitmap.Config.ARGB_8888);
int length = mImageWidth - newWidth;
// 获取原始图片的像素数组
int[] pixels = new int[newWidth * newHeight];
source.getPixels(pixels, 0, newWidth, 0, 0, newWidth, newHeight);
int size = (int) (newWidth * mPercent);
// 横向拉伸指定区间的像素点
for (int y = 0; y < newHeight; y++) {
for (int x = 0; x < newWidth; x++) {
if (x < size) {
int pixel = pixels[y * newWidth + x];
stretchedBitmap.setPixel(x, y, pixel);
} else if (x == size) {
for (int i = 0; i < length; i++) {
int pixel = pixels[y * newWidth + x];
stretchedBitmap.setPixel(x + i, y, pixel);
}
} else {
int pixel = pixels[y * newWidth + x];
stretchedBitmap.setPixel(x + length - 1, y, pixel);
}
}
}
return stretchedBitmap;
}
}
/**
* 缩小原始bitmap到指定高度
*
* @param originalBitmap
* @param targetHeight
* @return
*/
private Bitmap scaleBitmap(Bitmap originalBitmap, int targetHeight) {
int originalWidth = originalBitmap.getWidth();
int originalHeight = originalBitmap.getHeight();
// 计算目标宽度,保持原始宽高比
int targetWidth = (int) ((float) originalWidth / originalHeight * targetHeight);
// 使用 Bitmap.createScaledBitmap() 进行缩小
Bitmap scaledBitmap = Bitmap.createScaledBitmap(originalBitmap, targetWidth, targetHeight, true);
// 返回缩小后的 Bitmap
return scaledBitmap;
}
@Override
public String getId() {
return mId;
}
}
- 具体使用
scss
int imageWidth = screenWidth - SizeUtils.dp2px(10);
Glide.with(mActivity)
.load(bgUrl)
.placeholder(R.mipmap.image_promotion_item_default)
.error(R.mipmap.image_promotion_item_default)
.transform(new GlideNinePatchTransform(mActivity, bgUrl + screenWidth,imageWidth,0.5f))
.into(holder.ivItemPromotionImage);
注意,横竖屏需要处理成不同的bitmap,所以GlideNinePatchTransform的id外界根据width进行了区分。
注意,此拉伸只是在你设置的某一个像素点位置拉伸。如果要拉伸给定的一段位置,还需在此基础上进行改造