在开发的时候可能会遇到需要根据后台返回来的Url生成二维码来让用户扫。
// zxing依赖
implementation "cn.yipianfengye.android:zxing-library:2.2"
/**
* 二维码生成工具类
*/
public class QRCodeUtil {
/**
* 生成二维码Bitmap
*
* @param content 内容
* @param widthPix 图片宽度
* @param heightPix 图片高度
* @param logoBm 二维码中心的Logo图标(可以为null)
* @param filePath 用于存储二维码图片的文件路径
* @return 生成二维码及保存文件是否成功
*/
public static boolean createQRImage(String content, int widthPix, int heightPix, Bitmap logoBm, String filePath) {
try {
if (content == null || "".equals(content)) {
return false;
}
//配置参数
Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
//容错级别
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
//设置空白边距的宽度
// hints.put(EncodeHintType.MARGIN, 2); //default is 4
// 图像数据转换,使用了矩阵转换
BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, widthPix, heightPix, hints);
int[] pixels = new int[widthPix * heightPix];
// 下面这里按照二维码的算法,逐个生成二维码的图片,
// 两个for循环是图片横列扫描的结果
for (int y = 0; y < heightPix; y++) {
for (int x = 0; x < widthPix; x++) {
if (bitMatrix.get(x, y)) {
pixels[y * widthPix + x] = 0xff000000;
} else {
pixels[y * widthPix + x] = 0xffffffff;
}
}
}
// 生成二维码图片的格式,使用ARGB_565
Bitmap bitmap = Bitmap.createBitmap(widthPix, heightPix, Bitmap.Config.RGB_565);
bitmap.setPixels(pixels, 0, widthPix, 0, 0, widthPix, heightPix);
if (logoBm != null) {
bitmap = addLogo(bitmap, logoBm);
}
//必须使用compress方法将bitmap保存到文件中再进行读取。直接返回的bitmap是没有任何压缩的,内存消耗巨大!
return bitmap != null && bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(filePath));
} catch (WriterException | IOException e) {
e.printStackTrace();
}
return false;
}
/**
* 在二维码中间添加Logo图案
*/
private static Bitmap addLogo(Bitmap src, Bitmap logo) {
if (src == null) {
return null;
}
if (logo == null) {
return src;
}
//获取图片的宽高
int srcWidth = src.getWidth();
int srcHeight = src.getHeight();
int logoWidth = logo.getWidth();
int logoHeight = logo.getHeight();
if (srcWidth == 0 || srcHeight == 0) {
return null;
}
if (logoWidth == 0 || logoHeight == 0) {
return src;
}
//logo大小为二维码整体大小的1/5
float scaleFactor = srcWidth * 1.0f / 5 / logoWidth;
Bitmap bitmap = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888);
try {
Canvas canvas = new Canvas(bitmap);
canvas.drawBitmap(src, 0, 0, null);
canvas.scale(scaleFactor, scaleFactor, srcWidth / 2, srcHeight / 2);
canvas.drawBitmap(logo, (srcWidth - logoWidth) / 2, (srcHeight - logoHeight) / 2, null);
canvas.save();
canvas.restore();
} catch (Exception e) {
bitmap = null;
e.getStackTrace();
}
return bitmap;
}
/**
* 生成二维码
*
* @param url:二维码链接
* @param drawableId:中间图片的资源Id
*/
public static void createQRImage(String url, int drawableId, ImageView img, int CENTER_IMG_HALF_WIDTH, int QR_WIDTH) {
LogUtils.logd("url--->>" + url);
Bitmap mBitmap = null;
Bitmap bitmap = null;
mBitmap = ((BitmapDrawable) img.getResources().getDrawable(drawableId)).getBitmap();
// 缩放图片
Matrix matrix = new Matrix();
float sx = (float) 2 * CENTER_IMG_HALF_WIDTH / mBitmap.getWidth();
float sy = (float) 2 * CENTER_IMG_HALF_WIDTH / mBitmap.getHeight();
matrix.setScale(sx, sy);
mBitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), matrix
, false);
try {
// 判断URL合法性
if (url == null || "".equals(url) || url.length() < 1) {
return;
}
Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
// 图像数据转换,使用了矩阵转换
BitMatrix bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, QR_WIDTH,
QR_WIDTH, hints);
// 下面这里按照二维码的算法,逐个生成二维码的图片,
// 两个for循环是图片横列扫描的结果
int height = bitMatrix.getHeight();
int width = bitMatrix.getWidth();
int halfW = width / 2;
int halfH = height / 2;
int[] pixels = new int[width * height];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (x > (halfW - CENTER_IMG_HALF_WIDTH) && x < (halfW + CENTER_IMG_HALF_WIDTH)
&& y > (halfH - CENTER_IMG_HALF_WIDTH)
&& y < CENTER_IMG_HALF_WIDTH + halfH) {
pixels[y * width + x] = mBitmap.getPixel(x - halfW +
CENTER_IMG_HALF_WIDTH, y - halfH + CENTER_IMG_HALF_WIDTH);
} else {
pixels[y * width + x] = bitMatrix.get(x, y) ? 0xff000000 : 0xffffffff;
}
}
}
// 生成二维码图片的格式,使用ARGB_565
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
// 显示到一个ImageView上面
if (img != null) {
img.setImageBitmap(bitmap);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
mBitmap = null;
bitmap = null;
}
}
}
/**
* 屏幕相关的辅助类
*/
public class DisplayUtil {
private DisplayUtil() {
/* cannot be instantiated */
throw new UnsupportedOperationException("cannot be instantiated");
}
/**
* 将px值转换为dip或dp值,保证尺寸大小不变
*
* @param pxValue
* (DisplayMetrics类中属性density)
* @return
*/
public static int px2dip(float pxValue) {
final float scale = BaseApplication.getAppContext().getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
/**
* 将dip或dp值转换为px值,保证尺寸大小不变
*
* @param dipValue
* (DisplayMetrics类中属性density)
* @return
*/
public static int dip2px( float dipValue) {
final float scale = BaseApplication.getAppContext().getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
/**
* 将px值转换为sp值,保证文字大小不变
*
* @param pxValue
* (DisplayMetrics类中属性scaledDensity)
* @return
*/
public static int px2sp(float pxValue) {
final float fontScale = BaseApplication.getAppContext().getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
}
/**
* 将sp值转换为px值,保证文字大小不变
*
* @param spValue
* (DisplayMetrics类中属性scaledDensity)
* @return
*/
public static int sp2px(float spValue) {
final float fontScale = BaseApplication.getAppContext().getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
/**
* 直接获取控件的宽、高
* @param view
* @return int[]
*/
public static int[] getWidgetWH(final View view){
ViewTreeObserver vto2 = view.getViewTreeObserver();
vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
return new int[]{view.getWidth(),view.getHeight()};
}
/**
* 直接获取控件的宽、高
* @param view
* @return int[]
*/
public static int getViewHeight(final View view){
ViewTreeObserver vto2 = view.getViewTreeObserver();
vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
return view.getHeight();
}
/**
* 直接获取控件的宽、高
* @param view
* @return int[]
*/
public static int getViewWidth(final View view){
ViewTreeObserver vto2 = view.getViewTreeObserver();
vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
return view.getWidth();
}
/**
* 获得屏幕宽度
*
* @param context
* @return
*/
public static int getScreenWidth(Context context) {
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.widthPixels;
}
/**
* 获得屏幕高度
*
* @param context
* @return
*/
public static int getScreenHeight(Context context) {
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.heightPixels;
}
/**
* 获得状态栏的高度
* 注意:该方法只能在Activity类中使用,在测试模式下失败
* @param context
* @return
*/
public static int getStatusBarHeight(Context context) {
int statusBarHeight = -1;
try {
Class<?> clazz = Class.forName("com.android.internal.R$dimen");
Object object = clazz.newInstance();
int height = Integer.parseInt(clazz.getField("status_bar_height")
.get(object).toString());
statusBarHeight = context.getResources().getDimensionPixelSize(height);
} catch (Exception e) {
e.printStackTrace();
}
return statusBarHeight;
}
/**
* 获取控件的宽
* @param view
* @return
*/
public static int getWidgetWidth(View view){
int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(w, h);//先度量
int width = view.getMeasuredWidth();
return width;
}
/**
* 获取控件的高
* @param view
* @return
*/
public static int getWidgetHeight(View view){
int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(w, h);//先度量
int height = view.getMeasuredHeight();
return height;
}
/**
* 设置控件宽
* @param view
* @param width
*/
public static void setWidgetWidth(View view, int width){
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
params.width = width;
view.setLayoutParams(params);
}
/**
* 设置控件高
* @param view
* @param height
*/
public static void setWidgetHeight(View view, int height){
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
params.height = height;
view.setLayoutParams(params);
}
//----------------------------------------------
/**
* 获取当前屏幕截图,包含状态栏(这个方法没测试通过)
*
* @param activity
* @return Bitmap
*/
public static Bitmap snapShotWithStatusBar(Activity activity) {
View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bmp = view.getDrawingCache();
int width = getScreenWidth(activity);
int height = getScreenHeight(activity);
Bitmap bp = null;
bp = Bitmap.createBitmap(bmp, 0, 0, width, height);
view.destroyDrawingCache();
return bp;
}
/**
* 获取当前屏幕截图,不包含状态栏(这个方法没测试通过)
*
* @param activity
* @return Bitmap
*/
public static Bitmap snapShotWithoutStatusBar(Activity activity) {
View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap bmp = view.getDrawingCache();
Rect frame = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
int width = getScreenWidth(activity);
int height = getScreenHeight(activity);
Bitmap bp = null;
bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height
- statusBarHeight);
view.destroyDrawingCache();
return bp;
}
}
//具体使用
//QRCodeUtil.createQRImage("二维码Url", "二维码中心小icon", "放二维码的imageView", "中心icon的宽高","二维码的宽高");
QRCodeUtil.createQRImage(qrUrl,
R.drawable.icon_qr_center,
mBinding.ivArriveHomeQrCode,
DisplayUtil.dip2px(20),
DisplayUtil.dip2px(300));