用代码横向拉伸Bitmap来实现类似于点9效果

先说一下问题背景

最近接到一个平板适配需求,其中有一个难点是网络过来的图片如果宽度不够,则要进行在某一位置的横向拉伸。以使其充满view宽度。同时要支持横竖屏切换时宽度变化的场景。在安卓中系统并没有给出相关的东西能实现此功能。于是乎只能自己寻找解决方案。

于是想到一种拉伸bitmap图片以适配view宽度的方法。

  1. 下面是工具代码:
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;
        }
    }
  1. 缩小原始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;
    }
  1. 将此工具运用到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;
    }
}
  1. 具体使用
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进行了区分。

注意,此拉伸只是在你设置的某一个像素点位置拉伸。如果要拉伸给定的一段位置,还需在此基础上进行改造

相关推荐
顾北川_野13 分钟前
Android CALL关于电话音频和紧急电话设置和获取
android·音视频
&岁月不待人&23 分钟前
Kotlin by lazy和lateinit的使用及区别
android·开发语言·kotlin
Winston Wood2 小时前
Android Parcelable和Serializable的区别与联系
android·序列化
清风徐来辽2 小时前
Android 项目模型配置管理
android
帅得不敢出门3 小时前
Gradle命令编译Android Studio工程项目并签名
android·ide·android studio·gradlew
problc3 小时前
Flutter中文字体设置指南:打造个性化的应用体验
android·javascript·flutter
帅得不敢出门14 小时前
安卓设备adb执行AT指令控制电话卡
android·adb·sim卡·at指令·电话卡
我又来搬代码了15 小时前
【Android】使用productFlavors构建多个变体
android
德育处主任17 小时前
Mac和安卓手机互传文件(ADB)
android·macos
芦半山17 小时前
Android“引用们”的底层原理
android·java