Android通过代码生成长图并保存本地

hello大家好,我是斯普润,很久没有更新博客了。因为最近一直在赶项目,不停加班。难得有时间闲下来写写博客。最近也在抽时间学习flutter,作为一枚程序猿当然不能停止学习的脚步啦~

说远了,今天分享下用代码生成长图并保存到本地的功能。当点击分享按钮后,会在后台生成长图的Bitmap,点击保存会将Bitmap存到本地jpg文件。先来看看我实现的效果。

   

其实原理很简单,首先生成一个空白的画布,然后通过本地的xml布局文件获取layout,将layout转成Bitmap,通过Canvas绘制出来,唯一需要注意的就是计算高度。我这里将其拆分成了三块,头布局只有文字和头像,中布局全部是图片,尾布局高度指定,由于图片需要根据宽度去收缩放大,所以计算中布局稍微麻烦一点,将需要绘制的图片下载到本地,所以使用前需要先申请存储权限!将图片收缩或放大至指定宽度,计算出此时的图片高度,将所有图片高度与间距高度累加,就得到了中布局的总高度。

说了这么多,先来看我的代码吧~ 注释都有,就不过多解释了,有些工具类,你们替换一下就可以了,比如SharePreUtil、DimensionUtil、QRCodeUtil等等,不需要可以去掉

import android.Manifest;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.Nullable;

import com.liulishuo.filedownloader.BaseDownloadTask;
import com.liulishuo.filedownloader.FileDownloadListener;
import com.liulishuo.filedownloader.FileDownloader;
import com.tbruyelle.rxpermissions2.RxPermissions;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class LongPoster extends LinearLayout {

    private String TAG = this.getClass().getName();

    private Context context;
    private View rootView;
    private Listener listener;

    private LinearLayout topViewLl, contentLl;
    private FrameLayout bottomViewFl;
    private TextView appNameTv, nameTv, courseNameTv, courseDetailTv, codeContentTv;


    // 长图的宽度,默认为屏幕宽度
    private int longPictureWidth;
    // 长图两边的间距
    private int leftRightMargin;
    // 图片的url集合
    private List<String> imageUrlList;
    // 保存下载后的图片url和路径键值对的链表
    private LinkedHashMap<String, String> localImagePathMap;
    //每张图的高度
    private Map<Integer, Integer> imgHeightMap;

    private int topHeight = 0;
    private int contentHeight = 0;
    private int bottomHeight = 0;
    //是否包含头像
    private boolean isContainAvatar = false;
    private Bitmap qrcodeBit;
    private List<Bitmap> tempList;

    public static void createPoster(InitialActivity activity, LongPosterBean bean, Listener listener) {
        new RxPermissions(activity).request(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .subscribe(granted -> {
                    if (granted) {
                        activity.showInfoProgressDialog(activity, "海报生成中...");
                        LongPoster poster = new LongPoster(activity);
                        poster.setListener(listener);
                        poster.setCurData(bean);
                    } else {
                        ToastUtil.showShort(activity, "请获取存储权限");
                        listener.onFail();
                    }
                });
    }


    public LongPoster(Context context) {
        super(context);
        init(context);
    }

    public LongPoster(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public LongPoster(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    public void removeListener() {
        this.listener = null;
    }

    public void setListener(Listener listener) {
        this.listener = listener;
    }

    private void init(Context context) {
        this.context = context;

        tempList = new ArrayList<>();
        //这里去获取屏幕高度,我这里默认1080
        longPictureWidth = 1080;
        leftRightMargin = DimensionUtil.dp2pxInt(15);
        rootView = LayoutInflater.from(context).inflate(R.layout.layout_draw_canvas, this, false);
        initView();
    }

    private void initView() {
        topViewLl = rootView.findViewById(R.id.ll_top_view);
        contentLl = rootView.findViewById(R.id.ll_content);
        bottomViewFl = rootView.findViewById(R.id.fl_bottom_view);

        appNameTv = rootView.findViewById(R.id.app_name_tv);
        nameTv = rootView.findViewById(R.id.tv_name);
        courseNameTv = rootView.findViewById(R.id.tv_course_name);
        courseDetailTv = rootView.findViewById(R.id.tv_course_detail_name);
        codeContentTv = rootView.findViewById(R.id.qr_code_content_tv);

        imageUrlList = new ArrayList<>();
        localImagePathMap = new LinkedHashMap<>();
        imgHeightMap = new HashMap<>();
    }

    public void setCurData(LongPosterBean bean) {
        imageUrlList.clear();
        localImagePathMap.clear();

        String icon = SharedPreUtil.getString("userIcon", "");
        if (!TextUtils.isEmpty(icon)) {
            imageUrlList.add(StringUtil.handleImageUrl(icon));
            isContainAvatar = true;
        }

        if (bean.getPhotoList() != null) {
            for (String str : bean.getPhotoList()) {
                imageUrlList.add(StringUtil.handleImageUrl(str));
            }
        }

        appNameTv.setText(R.string.app_name);
        nameTv.setText(SharedPreUtil.getString("userNickName", ""));
        String courseNameStr = "我在" + getResources().getString(R.string.app_name) + "学" + bean.getCourseName();
        SpannableString ss = new SpannableString(courseNameStr);

        ss.setSpan(new ForegroundColorSpan(Color.parseColor("#333333")),
                courseNameStr.length() - bean.getCourseName().length(), courseNameStr.length(),
                SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);

        courseNameTv.setText(ss);
        courseDetailTv.setText(bean.getDetailName());
        codeContentTv.setText("扫描二维码\n查看" + bean.getCourseName());

        if (!TextUtils.isEmpty(bean.getQrCodeUrl())) {
            int width = (int) DimensionUtil.dp2px(120);
            qrcodeBit = QRCodeUtil.createQRCodeBitmap(bean.getQrCodeUrl(), width, width);
            tempList.add(qrcodeBit);
        }
        downloadAllPic();
    }

    private void downloadAllPic() {
        //下载方法,这里替换你选用的三方库,或者你可以选用我使用的这个三方库
        //implementation 'com.liulishuo.filedownloader:library:1.7.4'
        if (imageUrlList.isEmpty()) return;

        FileDownloader.setup(context);
        FileDownloadListener queueTarget = new FileDownloadListener() {
            @Override
            protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) {
            }

            @Override
            protected void connected(BaseDownloadTask task, String etag, boolean isContinue, int soFarBytes, int totalBytes) {
            }

            @Override
            protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) {
            }

            @Override
            protected void blockComplete(BaseDownloadTask task) {
            }

            @Override
            protected void retry(final BaseDownloadTask task, final Throwable ex, final int retryingTimes, final int soFarBytes) {
            }

            @Override
            protected void completed(BaseDownloadTask task) {
                localImagePathMap.put(task.getUrl(), task.getTargetFilePath());
                if (localImagePathMap.size() == imageUrlList.size()) {
                    //全部图片下载完成开始绘制
                    measureHeight();
                    drawPoster();
                }
            }

            @Override
            protected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) {
            }

            @Override
            protected void error(BaseDownloadTask task, Throwable e) {
                listener.onFail();
                e.printStackTrace();
            }

            @Override
            protected void warn(BaseDownloadTask task) {
            }
        };

        for (String url : imageUrlList) {
            String storePath = BitmapUtil.getImgFilePath();
            FileDownloader.getImpl().create(url)
                    .setCallbackProgressTimes(0)
                    .setListener(queueTarget)
                    .setPath(storePath)
                    .asInQueueTask()
                    .enqueue();
        }

        FileDownloader.getImpl().start(queueTarget, true);
    }

    private void measureHeight() {
        layoutView(topViewLl);
        layoutView(contentLl);
        layoutView(bottomViewFl);

        topHeight = topViewLl.getMeasuredHeight();
        //原始高度加上图片总高度
        contentHeight = contentLl.getMeasuredHeight() + getAllImageHeight();
        bottomHeight = bottomViewFl.getMeasuredHeight();
//        LogUtil.d(TAG, "drawLongPicture layout top view = " + topHeight + " × " + longPictureWidth);
//        LogUtil.d(TAG, "drawLongPicture layout llContent view = " + contentHeight);
//        LogUtil.d(TAG, "drawLongPicture layout bottom view = " + bottomHeight);
    }

    /**
     * 绘制方法
     */
    private void drawPoster() {
        // 计算出最终生成的长图的高度 = 上、中、图片总高度、下等个个部分加起来
        int allBitmapHeight = topHeight + contentHeight + bottomHeight;

        // 创建空白画布
        Bitmap.Config config = Bitmap.Config.RGB_565;
        Bitmap bitmapAll = Bitmap.createBitmap(longPictureWidth, allBitmapHeight, config);

        Canvas canvas = new Canvas(bitmapAll);
        canvas.drawColor(Color.WHITE);
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setDither(true);
        paint.setFilterBitmap(true);

        // 绘制top view
        Bitmap topBit = BitmapUtil.getLayoutBitmap(topViewLl, longPictureWidth, topHeight);
        canvas.drawBitmap(topBit, 0, 0, paint);

        //绘制头像
        Bitmap avatarBit;
        if (isContainAvatar) {
            int aWidth = (int) DimensionUtil.dp2px(77);
            avatarBit = BitmapUtil.resizeImage(BitmapFactory.decodeFile(localImagePathMap.get(imageUrlList.get(0))), aWidth, aWidth);
        } else {
            avatarBit = BitmapUtil.drawableToBitmap(context.getDrawable(R.drawable.placeholder));
        }
        if (avatarBit != null) {
            avatarBit = BitmapUtil.getOvalBitmap(avatarBit, (int) DimensionUtil.dp2px(38));
            canvas.drawBitmap(avatarBit, DimensionUtil.dp2px(20), DimensionUtil.dp2px(70), paint);
        }

        //绘制中间图片列表
        if (isContainAvatar && imageUrlList.size() > 1) {
            Bitmap bitmapTemp;
            int top = (int) (topHeight + DimensionUtil.dp2px(20));
            for (int i = 1; i < imageUrlList.size(); i++) {
                String filePath = localImagePathMap.get(imageUrlList.get(i));
                bitmapTemp = BitmapUtil.fitBitmap(BitmapFactory.decodeFile(filePath),
                        longPictureWidth - leftRightMargin * 2);
                if (i > 1)
                    top += imgHeightMap.get(i - 1) + DimensionUtil.dp2px(10);
                canvas.drawBitmap(bitmapTemp, leftRightMargin, top, paint);
                tempList.add(bitmapTemp);
            }
        } else if (!isContainAvatar && !imageUrlList.isEmpty()) {
            Bitmap bitmapTemp;
            int top = (int) (topHeight + DimensionUtil.dp2px(20));
            for (int i = 0; i < imageUrlList.size(); i++) {
                String filePath = localImagePathMap.get(imageUrlList.get(i));
                bitmapTemp = BitmapUtil.fitBitmap(BitmapFactory.decodeFile(filePath),
                        longPictureWidth - leftRightMargin * 2);
                if (i > 0)
                    top += imgHeightMap.get(i - 1) + DimensionUtil.dp2px(10);
                canvas.drawBitmap(bitmapTemp, leftRightMargin, top, paint);
                tempList.add(bitmapTemp);
            }
        }

        // 绘制bottom view
        Bitmap bottomBit = BitmapUtil.getLayoutBitmap(bottomViewFl, longPictureWidth, bottomHeight);
        canvas.drawBitmap(bottomBit, 0, topHeight + contentHeight, paint);

        // 绘制QrCode
        //if (qrcodeBit != null)
            //canvas.drawBitmap(qrcodeBit, longPictureWidth - DimensionUtil.dp2px(150),
                    //topHeight + contentHeight + DimensionUtil.dp2px(15), paint);

        //保存最终的图片
        String time = String.valueOf(System.currentTimeMillis());
        boolean state = BitmapUtil.saveImage(bitmapAll, context.getExternalCacheDir() +
                    File.separator, time, Bitmap.CompressFormat.JPEG, 80);

        //绘制回调
        if (listener != null) {
            if (state) {
                listener.onSuccess(context.getExternalCacheDir() + File.separator + time);
            } else {
                listener.onFail();
            }
        }

        //清空所有Bitmap
        tempList.add(topBit);
        tempList.add(avatarBit);
        tempList.add(bottomBit);
        tempList.add(bitmapAll);
        for (Bitmap bit : tempList) {
            if (bit != null && !bit.isRecycled()) {
                bit.recycle();
            }
        }
        tempList.clear();

        //绘制完成,删除所有保存的图片
        for (int i = 0; i < imageUrlList.size(); i++) {
            String path = localImagePathMap.get(imageUrlList.get(i));
            File file = new File(path);
            if (file.exists()) {
                file.delete();
            }
        }
    }

    /**
     * 获取当前下载所有图片的高度,忽略头像
     */
    private int getAllImageHeight() {
        imgHeightMap.clear();
        int height = 0;
        int startIndex = 0;
        int cutNum = 1;
        if (isContainAvatar) {
            cutNum = 2;
            startIndex = 1;
        }

        for (int i = startIndex; i < imageUrlList.size(); i++) {
            Bitmap tamp = BitmapUtil.fitBitmap(BitmapFactory.decodeFile(localImagePathMap.get(imageUrlList.get(i))),
                    longPictureWidth - leftRightMargin * 2);
            height += tamp.getHeight();
            imgHeightMap.put(i, tamp.getHeight());
            tempList.add(tamp);
        }

        height = (int) (height + DimensionUtil.dp2px(10) * (imageUrlList.size() - cutNum));
        return height;
    }


    /**
     * 手动测量view宽高
     */
    private void layoutView(View v) {
        v.layout(0, 0, DoukouApplication.screenWidth, DoukouApplication.screenHeight);
        int measuredWidth = View.MeasureSpec.makeMeasureSpec(DoukouApplication.screenWidth, View.MeasureSpec.EXACTLY);
        int measuredHeight = View.MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        v.measure(measuredWidth, measuredHeight);
        v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
    }

    public interface Listener {

        /**
         * 生成长图成功的回调
         *
         * @param path 长图路径
         */
        void onSuccess(String path);

        /**
         * 生成长图失败的回调
         */
        void onFail();
    }
}

接下来是界面布局,由于图片先下载再绘制的,所以不需要图片控件,只需要预留出图片的位置就可以了~

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        android:orientation="vertical">

        <LinearLayout
            android:id="@+id/ll_top_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingLeft="15dp"
            android:paddingRight="15dp">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:layout_marginTop="25dp"
                android:gravity="center_vertical"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/app_name_tv"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="#fffb4e90"
                    android:textSize="18sp" />

                <View
                    android:layout_width="1dp"
                    android:layout_height="14dp"
                    android:layout_marginHorizontal="10dp"
                    android:background="@color/colorPrimary" />

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="#fffb4e90"
                    android:textSize="18sp" />

            </LinearLayout>

            <FrameLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="20dp">

                <TextView
                    android:id="@+id/tv_name"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="87dp"
                    android:layout_marginTop="8dp"
                    android:textColor="@color/c33"
                    android:textSize="18sp" />

                <TextView
                    android:id="@+id/tv_course_name"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="87dp"
                    android:layout_marginTop="43dp"
                    android:textColor="@color/c66"
                    android:textSize="18sp" />

            </FrameLayout>

            <TextView
                android:id="@+id/tv_course_detail_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:layout_marginTop="28dp"
                android:background="@drawable/shape_black_radius2"
                android:paddingHorizontal="22dp"
                android:paddingVertical="10dp"
                android:textColor="#ffffffff"
                android:textSize="15sp" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/ll_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingLeft="15dp"
            android:paddingTop="20dp"
            android:paddingRight="15dp"
            android:paddingBottom="10dp" />

        <FrameLayout
            android:id="@+id/fl_bottom_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            android:paddingLeft="15dp"
            android:paddingRight="15dp"
            android:paddingBottom="20dp">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="150dp"
                android:scaleType="fitXY"
                android:src="@drawable/bg_qr_code" />

            <TextView
                android:id="@+id/qr_code_content_tv"
                android:layout_width="175dp"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:layout_marginLeft="15dp"
                android:ellipsize="end"
                android:maxLines="3"
                android:textColor="@color/white"
                android:textSize="15sp" />

        </FrameLayout>

    </LinearLayout>

</ScrollView>

BitmapUtil工具类~

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.RequiresApi;
import androidx.fragment.app.FragmentActivity;

import com.tbruyelle.rxpermissions2.RxPermissions;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.UUID;


public class BitmapUtil {

    private static final String TAG = "BitmapUtil";

 
    /**
     * 将Bitmap转成图片保存本地
     */
    public static boolean saveImage(Bitmap bitmap, String filePath, String filename, Bitmap.CompressFormat format, int quality) {
        if (quality > 100) {
            Log.d("saveImage", "quality cannot be greater that 100");
            return false;
        }
        File file;
        FileOutputStream out = null;
        try {
            switch (format) {
                case PNG:
                    file = new File(filePath, filename);
                    out = new FileOutputStream(file);
                    return bitmap.compress(Bitmap.CompressFormat.PNG, quality, out);
                case JPEG:
                    file = new File(filePath, filename);
                    out = new FileOutputStream(file);
                    return bitmap.compress(Bitmap.CompressFormat.JPEG, quality, out);
                default:
                    file = new File(filePath, filename + ".png");
                    out = new FileOutputStream(file);
                    return bitmap.compress(Bitmap.CompressFormat.PNG, quality, out);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    /**
     * drawable 转 bitmap
     */
    public static Bitmap drawableToBitmap(Drawable drawable) {
        // 取 drawable 的长宽
        int w = drawable.getIntrinsicWidth();
        int h = drawable.getIntrinsicHeight();

        // 取 drawable 的颜色格式
        Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
        // 建立对应 bitmap
        Bitmap bitmap = Bitmap.createBitmap(w, h, config);
        // 建立对应 bitmap 的画布
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, w, h);
        // 把 drawable 内容画到画布中
        drawable.draw(canvas);
        return bitmap;
    }

    public static void saveImage(FragmentActivity context, Bitmap bmp, boolean recycle) {
        new RxPermissions(context).request(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .subscribe(granted -> {
                    if (granted) {
                        if (BitmapUtil.saveImageToGallery(context, bmp)) {
                            ToastUtil.showShort(context, "保存成功");
                        } else {
                            ToastUtil.showShort(context, "保存失败");
                        }
                    } else {
                        ToastUtil.showShort(context, "请获取存储权限");
                    }
                    if (recycle) bmp.recycle();
                });
    }

    //保存图片到指定路径
    private static boolean saveImageToGallery(FragmentActivity context, Bitmap bmp) {
        // 首先保存图片
        String storePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator +
                Environment.DIRECTORY_PICTURES + File.separator + "test";
        File appDir = new File(storePath);
        if (!appDir.exists()) {
            appDir.mkdir();
        }
        String fileName = System.currentTimeMillis() + ".jpg";
        File file = new File(appDir, fileName);
        try {
            FileOutputStream fos = new FileOutputStream(file);
            //通过io流的方式来压缩保存图片
            boolean isSuccess = bmp.compress(Bitmap.CompressFormat.JPEG, 60, fos);
            fos.flush();
            fos.close();

            //把文件插入到系统图库
//            MediaStore.Images.Media.insertImage(context.getContentResolver(), bmp, fileName, null);

            //保存图片后发送广播通知更新数据库
            Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
            Uri uri = Uri.fromFile(new File(file.getAbsolutePath()));
            LogUtil.e("路径============", file.getAbsolutePath());
            intent.setData(uri);
            context.sendBroadcast(intent);

            return isSuccess;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    public static String getImgFilePath() {
        String storePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator +
                Environment.DIRECTORY_PICTURES + File.separator + "test" + File.separator;
        File appDir = new File(storePath);
        if (!appDir.exists()) {
            appDir.mkdir();
        }
        return storePath + UUID.randomUUID().toString().replace("-", "") + ".jpg";
    }


    /***
     * 得到指定半径的圆形Bitmap
     * @param bitmap 图片
     * @param radius 半径
     * @return bitmap
     */
    public static Bitmap getOvalBitmap(Bitmap bitmap, int radius) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap
                .getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        int width = bitmap.getWidth();
        int height = bitmap.getHeight();

        float scaleWidth = ((float) 2 * radius) / width;

        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleWidth);

        bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);

        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());

        final RectF rectF = new RectF(rect);

        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);

        canvas.drawOval(rectF, paint);

        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);
        return output;
    }

    /**
     * layout布局转Bitmap
     *
     * @param layout 布局
     * @param w      宽
     * @param h      高
     * @return bitmap
     */
    public static Bitmap getLayoutBitmap(ViewGroup layout, int w, int h) {
        Bitmap originBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(originBitmap);
        layout.draw(canvas);
        return resizeImage(originBitmap, w, h);
    }

    public static Bitmap resizeImage(Bitmap origin, int newWidth, int newHeight) {
        if (origin == null) {
            return null;
        }
        int height = origin.getHeight();
        int width = origin.getWidth();
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        Bitmap newBM = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
        if (!origin.isRecycled()) {
            origin.recycle();
        }
        return newBM;
    }


    /**
     * fuction: 设置固定的宽度,高度随之变化,使图片不会变形
     *
     * @param target   需要转化bitmap参数
     * @param newWidth 设置新的宽度
     * @return
     */
    public static Bitmap fitBitmap(Bitmap target, int newWidth) {
        int width = target.getWidth();
        int height = target.getHeight();
        Matrix matrix = new Matrix();
        float scaleWidth = ((float) newWidth) / width;
        // float scaleHeight = ((float)newHeight) / height;
        int newHeight = (int) (scaleWidth * height);
        matrix.postScale(scaleWidth, scaleWidth);
        // Bitmap result = Bitmap.createBitmap(target,0,0,width,height,
        // matrix,true);
        Bitmap bmp = Bitmap.createBitmap(target, 0, 0, width, height, matrix,
                true);
        if (target != null && !target.equals(bmp) && !target.isRecycled()) {
            target.recycle();
            target = null;
        }
        return bmp;// Bitmap.createBitmap(target, 0, 0, width, height, matrix,
        // true);
    }
}

嗯,好了,大致代码就是以上这些,不过有些方法需要替换成你们自己的哦~

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯普润丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值