当前位置: 移动技术网 > IT编程>移动开发>Android > 基于Android实现个性彩色好看的二维码

基于Android实现个性彩色好看的二维码

2019年07月24日  | 移动技术网IT编程  | 我要评论

朱明国供出名单,瑜珈教程,北京消防检测

我编码的风格,先给大家展示下效果图,亲们感觉效果还不错,很满意的话,请继续往下阅读。

这里写图片描述
这里写图片描述

这里写图片描述

之前呢,也写过用安卓实现二维码生成彩色的二维码和带logo的二维码,也知道可以使用qrcode和zxing两种方式,然后这一篇呢也是写二维码使用barcodeformat.qr_code,主要也是看见很多的非常漂亮的二维码,这里呢主要模仿qq的二维码,并且也高仿实现了长按发送给朋友和保存到图库的功能,觉得不错呢就请多支持下,哪里不好呢也可以说出来。好了我们一步一步来。

第一步:简单二维码实现

先来个最简单的二维码:

这里写图片描述 

看下简单代码实现:

/**
* 根据指定内容生成自定义宽高的二维码图片
*
* @param content
* 需要生成二维码的内容
* @param width
* 二维码宽度
* @param height
* 二维码高度
* @throws writerexception
* 生成二维码异常
*/
public static bitmap makeqrimage(string content, int width, int height)
throws writerexception {
hashtable<encodehinttype, string> hints = new hashtable<encodehinttype, string>();
hints.put(encodehinttype.character_set, "utf-8");
// 图像数据转换,使用了矩阵转换
bitmatrix bitmatrix = new qrcodewriter().encode(content,
barcodeformat.qr_code, width, height, hints);
int[] pixels = new int[width * height];
// 按照二维码的算法,逐个生成二维码的图片,两个for循环是图片横列扫描的结果
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (bitmatrix.get(x, y))//范围内为黑色的
pixels[y * width + x] = 0xff000000;
else//其他的地方为白色
pixels[y * width + x] = 0xffffffff;
}
}
// 生成二维码图片的格式,使用argb_8888
bitmap bitmap = bitmap.createbitmap(width, height,
bitmap.config.argb_8888);
//设置像素矩阵的范围
bitmap.setpixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}

第二步:简单二维码加logo

接下来给二维码加logo:(看图)

这里写图片描述

/**
* 根据指定内容生成自定义宽高的二维码图片
*
* param logobm
* logo图标
* param content
* 需要生成二维码的内容
* param width
* 二维码宽度
* param height
* 二维码高度
* throws writerexception
* 生成二维码异常
*/
public static bitmap makeqrimage(bitmap logobmp, string content,
int qr_width, int qr_height) throws writerexception {
try {
// 图像数据转换,使用了矩阵转换
hashtable<encodehinttype, object> hints = new hashtable<encodehinttype, object>();
hints.put(encodehinttype.character_set, "utf-8");
hints.put(encodehinttype.error_correction, errorcorrectionlevel.h);// 容错率
hints.put(encodehinttype.margin, 2); // default is 4
hints.put(encodehinttype.max_size, 350);
hints.put(encodehinttype.min_size, 100);
bitmatrix bitmatrix = new qrcodewriter().encode(content,
barcodeformat.qr_code, qr_width, qr_height, hints);
int[] pixels = new int[qr_width * qr_height];
for (int y = 0; y < qr_height; y++) {
// 下面这里按照二维码的算法,逐个生成二维码的图片,//两个for循环是图片横列扫描的结果
for (int x = 0; x < qr_width; x++) {
if (bitmatrix.get(x, y))
pixels[y * qr_width + x] = 0xff000000;
else
pixels[y * qr_width + x] = 0xffffffff;
}
}
// ------------------添加图片部分------------------//
bitmap bitmap = bitmap.createbitmap(qr_width, qr_height,
bitmap.config.argb_8888);
// 设置像素点
bitmap.setpixels(pixels, 0, qr_width, 0, 0, qr_width, qr_height);
// 获取图片宽高
int logowidth = logobmp.getwidth();
int logoheight = logobmp.getheight();
if (qr_width == 0 || qr_height == 0) {
return null;
}
if (logowidth == 0 || logoheight == 0) {
return bitmap;
}
// 图片绘制在二维码中央,合成二维码图片
// logo大小为二维码整体大小的1/2
float scalefactor = qr_width * 1.0f / 2 / logowidth;
try {
canvas canvas = new canvas(bitmap);
canvas.drawbitmap(bitmap, 0, 0, null);
canvas.scale(scalefactor, scalefactor, qr_width / 2,
qr_height / 2);
canvas.drawbitmap(logobmp, (qr_width - logowidth) / 2,
(qr_height - logoheight) /2, null);
canvas.save(canvas.all_save_flag);
canvas.restore();
return bitmap;
} catch (exception e) {
bitmap = null;
e.getstacktrace();
}
} catch (writerexception e) {
e.printstacktrace();
}
return null;
}

上段代码可以看出要给二维码图片中间加logo,但是图片不能占据整个二维码图片的很大一部分。然后还必须设置容错率:容错率有m,l,q,h几个等级,容错率越高,二维码的有效像素点就越多。这里使用小写的utf-8编码,大写会出现]q2\000026开头内容,为了好看点还设置了边距和大小。

第三步:实现带logo的彩色二维码

接下来我们把黑白矩阵变为彩色矩阵:
就把

if (bitmatrix.get(x, y))
pixels[y * width + x] = 0xff000000;
else
pixels[y * width + x] = 0xffffffff;

替换为:(这里的颜色随便设置,效果随便改)

if (x < qr_width / 2 && y < qr_height / 2) {
pixels[y * qr_width + x] = 0xff0094ff;// 蓝色
integer.tohexstring(new random().nextint());
} else if (x < qr_width / 2 && y > qr_height / 2) {
pixels[y * qr_width + x] = 0xfffed545;// 黄色
} else if (x > qr_width / 2 && y > qr_height / 2) {
pixels[y * qr_width + x] = 0xff5acf00;// 绿色
} else {
pixels[y * qr_width + x] = 0xff000000;// 黑色
}
} else {
pixels[y * qr_width + x] = 0xffffffff;// 白色
}

改后的效果:

这里写图片描述

第四步:给二维码加背景

接下来我们来给二维码图片加背景:

/**
* 给二维码图片加背景
*
*/
public static bitmap addbackground(bitmap foreground,bitmap background){
int bgwidth = background.getwidth();
int bgheight = background.getheight();
int fgwidth = foreground.getwidth();
int fgheight = foreground.getheight();
bitmap newmap = bitmap
.createbitmap(bgwidth, bgheight, bitmap.config.argb_8888);
canvas canvas = new canvas(newmap);
canvas.drawbitmap(background, 0, 0, null);
canvas.drawbitmap(foreground, (bgwidth - fgwidth) / 2,
(bgheight - fgheight) *3 / 5+70, null);
canvas.save(canvas.all_save_flag);
canvas.restore();
return newmap;
}

这样效果就变为:

这里写图片描述

第五步:给二维码加水印

然后二维码的个性化制作就最后一步了:加水印,位置随便放

/**
* 在图片右下角添加水印
*
* @param srcbmp
* 原图
* @param markbmp
* 水印图片
* @return 合成水印后的图片
*/
public static bitmap composewatermark(bitmap srcbmp, bitmap markbmp) {
if (srcbmp == null) {
return null;
}
// 创建一个新的和src长度宽度一样的位图
bitmap newb = bitmap.createbitmap(srcbmp.getwidth(),
srcbmp.getheight(), bitmap.config.argb_8888);
canvas cv = new canvas(newb);
// 在 0,0坐标开始画入原图
cv.drawbitmap(srcbmp, 0, 0, null);
// 在原图的右下角画入水印
cv.drawbitmap(markbmp, srcbmp.getwidth() - markbmp.getwidth()*4/5,
srcbmp.getheight()*2/7 , null);
// 保存
cv.save(canvas.all_save_flag);
// 存储
cv.restore();
return newb;
}

这里写图片描述 

这里贴下实现二维码个性化的完整代码类:

package com.ry.personalizedcode.uitls;
import android.content.context;
import android.graphics.bitmap;
import android.graphics.bitmapfactory;
import android.graphics.canvas;
import com.google.zxing.barcodeformat;
import com.google.zxing.encodehinttype;
import com.google.zxing.writerexception;
import com.google.zxing.common.bitmatrix;
import com.google.zxing.qrcode.qrcodewriter;
import com.google.zxing.qrcode.decoder.errorcorrectionlevel;
import java.util.hashtable;
import java.util.random;
/**
* created on 2016/2/24.
* 生成二维码的工具类
*/
public class makeqrcodeutil {
/**
* 根据指定内容生成自定义宽高的二维码图片
*
* param logobm
* logo图标
* param content
* 需要生成二维码的内容
* param width
* 二维码宽度
* param height
* 二维码高度
* throws writerexception
* 生成二维码异常
*/
public static bitmap makeqrimage(bitmap logobmp, string content,
int qr_width, int qr_height) throws writerexception {
try {
// 图像数据转换,使用了矩阵转换
hashtable<encodehinttype, object> hints = new hashtable<encodehinttype, object>();
hints.put(encodehinttype.character_set, "utf-8");
hints.put(encodehinttype.error_correction, errorcorrectionlevel.h);// 容错率
hints.put(encodehinttype.margin, 2); // default is 4
hints.put(encodehinttype.max_size, 350);
hints.put(encodehinttype.min_size, 100);
bitmatrix bitmatrix = new qrcodewriter().encode(content,
barcodeformat.qr_code, qr_width, qr_height, hints);
int[] pixels = new int[qr_width * qr_height];
for (int y = 0; y < qr_height; y++) {
// 下面这里按照二维码的算法,逐个生成二维码的图片,//两个for循环是图片横列扫描的结果
for (int x = 0; x < qr_width; x++) {
if (bitmatrix.get(x, y)) {
if (x < qr_width / 2 && y < qr_height / 2) {
pixels[y * qr_width + x] = 0xff0094ff;// 蓝色
integer.tohexstring(new random().nextint());
} else if (x < qr_width / 2 && y > qr_height / 2) {
pixels[y * qr_width + x] = 0xfffed545;// 黄色
} else if (x > qr_width / 2 && y > qr_height / 2) {
pixels[y * qr_width + x] = 0xff5acf00;// 绿色
} else {
pixels[y * qr_width + x] = 0xff000000;// 黑色
}
} else {
pixels[y * qr_width + x] = 0xffffffff;// 白色
}
}
}
// ------------------添加图片部分------------------//
bitmap bitmap = bitmap.createbitmap(qr_width, qr_height,
bitmap.config.argb_8888);
// 设置像素点
bitmap.setpixels(pixels, 0, qr_width, 0, 0, qr_width, qr_height);
// 获取图片宽高
int logowidth = logobmp.getwidth();
int logoheight = logobmp.getheight();
if (qr_width == 0 || qr_height == 0) {
return null;
}
if (logowidth == 0 || logoheight == 0) {
return bitmap;
}
// 图片绘制在二维码中央,合成二维码图片
// logo大小为二维码整体大小的1/2
float scalefactor = qr_width * 1.0f / 2 / logowidth;
try {
canvas canvas = new canvas(bitmap);
canvas.drawbitmap(bitmap, 0, 0, null);
canvas.scale(scalefactor, scalefactor, qr_width / 2,
qr_height / 2);
canvas.drawbitmap(logobmp, (qr_width - logowidth) / 2,
(qr_height - logoheight) /2, null);
canvas.save(canvas.all_save_flag);
canvas.restore();
return bitmap;
} catch (exception e) {
bitmap = null;
e.getstacktrace();
}
} catch (writerexception e) {
e.printstacktrace();
}
return null;
}
/**
* 获取十六进制的颜色代码.例如 "#6e36b4" , for html ,
* @return string
*/
public static string getrandcolorcode(){
string r,g,b;
random random = new random();
r = integer.tohexstring(random.nextint(256)).touppercase();
g = integer.tohexstring(random.nextint(256)).touppercase();
b = integer.tohexstring(random.nextint(256)).touppercase();
r = r.length()==1 ? "0" + r : r ;
g = g.length()==1 ? "0" + g : g ;
b = b.length()==1 ? "0" + b : b ;
return r+g+b;
}
/**
* 根据指定内容生成自定义宽高的二维码图片
*
* @param content
* 需要生成二维码的内容
* @param width
* 二维码宽度
* @param height
* 二维码高度
* @throws writerexception
* 生成二维码异常
*/
public static bitmap makeqrimage(string content, int width, int height)
throws writerexception {
hashtable<encodehinttype, string> hints = new hashtable<encodehinttype, string>();
hints.put(encodehinttype.character_set, "utf-8");
// 图像数据转换,使用了矩阵转换
bitmatrix bitmatrix = new qrcodewriter().encode(content,
barcodeformat.qr_code, width, height, hints);
int[] pixels = new int[width * height];
// 按照二维码的算法,逐个生成二维码的图片,两个for循环是图片横列扫描的结果
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (bitmatrix.get(x, y))
pixels[y * width + x] = 0xff000000;
else
pixels[y * width + x] = 0xffffffff;
}
}
// 生成二维码图片的格式,使用argb_8888
bitmap bitmap = bitmap.createbitmap(width, height,
bitmap.config.argb_8888);
bitmap.setpixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
/**
* 从资源文件中获取图片
*
* @param context
* 上下文
* @param drawableid
* 资源文件id
* @return
*/
public static bitmap gainbitmap(context context, int drawableid) {
bitmap bmp = bitmapfactory.decoderesource(context.getresources(),
drawableid);
return bmp;
}
/**
* 在图片右下角添加水印
*
* @param srcbmp
* 原图
* @param markbmp
* 水印图片
* @return 合成水印后的图片
*/
public static bitmap composewatermark(bitmap srcbmp, bitmap markbmp) {
if (srcbmp == null) {
return null;
}
// 创建一个新的和src长度宽度一样的位图
bitmap newb = bitmap.createbitmap(srcbmp.getwidth(),
srcbmp.getheight(), bitmap.config.argb_8888);
canvas cv = new canvas(newb);
// 在 0,0坐标开始画入原图
cv.drawbitmap(srcbmp, 0, 0, null);
// 在原图的右下角画入水印
cv.drawbitmap(markbmp, srcbmp.getwidth() - markbmp.getwidth()*4/5,
srcbmp.getheight()*2/7 , null);
// 保存
cv.save(canvas.all_save_flag);
// 存储
cv.restore();
return newb;
}
/**
* 给二维码图片加背景
*
*/
public static bitmap addbackground(bitmap foreground,bitmap background){
int bgwidth = background.getwidth();
int bgheight = background.getheight();
int fgwidth = foreground.getwidth();
int fgheight = foreground.getheight();
bitmap newmap = bitmap
.createbitmap(bgwidth, bgheight, bitmap.config.argb_8888);
canvas canvas = new canvas(newmap);
canvas.drawbitmap(background, 0, 0, null);
canvas.drawbitmap(foreground, (bgwidth - fgwidth) / 2,
(bgheight - fgheight) *3 / 5+70, null);
canvas.save(canvas.all_save_flag);
canvas.restore();
return newmap;
}
}

第六步:给二维码实现长按功能

最后为了模拟下qq的查看二维码名片功能,还加了一个长按弹出actionsheet的功能。
看效果:

这里写图片描述 

具体的 安卓版actionsheet的实现,前面博客有介绍需要的请移步。

这里我们先来实现发送给好友功能:(这里就不做第三方的发送)

private void sendtofriends() {
intent intent=new intent(intent.action_send);
uri imageuri= uri.parse(environment.getexternalstoragedirectory()+"/code/qrcode.jpg");
intent.settype("image/*");
intent.putextra(intent.extra_stream, imageuri);
intent.setflags(intent.flag_activity_new_task);
startactivity(intent.createchooser(intent, gettitle()));
}

发送给朋友效果图:

这里写图片描述 

然后就是要实现保存到本地图库的功能:

/**
* 先保存到本地再广播到图库
* */
public static void saveimagetogallery(context context, bitmap bmp) {
// 首先保存图片
file appdir = new file(environment.getexternalstoragedirectory(),
"code");
if (!appdir.exists()) {
appdir.mkdir();
}
string filename = "qrcode.jpg";
file = new file(appdir, filename);
try {
fileoutputstream fos = new fileoutputstream(file);
bmp.compress(compressformat.jpeg, 100, fos);
fos.flush();
fos.close();
} catch (filenotfoundexception e) {
e.printstacktrace();
} catch (ioexception e) {
e.printstacktrace();
}
// 其次把文件插入到系统图库
try {
mediastore.images.media.insertimage(context.getcontentresolver(), file.getabsolutepath(), filename, null);
// 最后通知图库更新
context.sendbroadcast(new intent( intent.action_media_scanner_scan_file, uri.parse("file://"
+ file)));
} catch (filenotfoundexception e) {
e.printstacktrace();
}
}

总结:

这篇说白了就是使用了大量的canvas和bitmap的处理,然后篇幅也是有点长,看起来也是有点累。要看完整的代码请自己下载personalizedcode.rar。下一篇我准备写webview中的二维码图片长按识别二维码功能。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网