1、引言
你是否还在因为不懂UI设计而不得不去借用别人的图片,甚至使用各种网图作为界面布局的一部分,那么今天就教你使用Bitmap对象去绘制自定义图形,并保存为png格式的图片,须知图片编辑软件本就是程序员开发出来的,我们又何必舍近求远呢,用代码生成岂不是更爽?
2、实现步骤
2.1、Bitmap对象创建
使用下面的方法创建Bitmp对象,第一个参数代表创建的位图宽度,第二个是位图高度,宽度和高度的单位都是像素,第三个是设置为支持透明背景,这里要注意高度和宽度必须大于0,后面索引也是从零开始。
Bitmap customBitmap = Bitmap//通过控制每一个像素点生成bitmap对象,可以用这种方式生成图片
.createBitmap(501, 501, Bitmap.Config.ARGB_8888);//按像素设置
2.2、形状绘制
这里我以绘制透明背景圆形图片为例,并提供两种方法,第一种方法不适合绘制圆形,但可以用来绘制多边形。由于是绘制圆形,需要使用函数计算位置,我这里提供了用于计算圆的坐标的函数。
2.1.1、圆的标准方程函数
这个函数借助圆的标准方程计算圆的坐标。
/**
* 已知圆的半径,圆心坐标,x坐标,求圆的y坐标
* @param r 圆的半径
* @param rx 圆心x坐标
* @param ry 圆心y坐标
* @param x 圆的某个位置的x坐标或y坐标,默认是根据x坐标求y坐标,如果需要根据y坐标求x坐标,
* 那么互换rx和ry位置,传入y坐标,返回的结果就是x坐标
*/
public static double[] circle(double r,double rx,double ry,double x){
double[] result;
//因为是标准方程且一定有解,所以传入的第一个参数始终为1
double b=-2*ry;
double c=ry*ry+x*x-2*rx*x+rx*rx-r*r;
result=quadratic_equation_one(1,b,c);
return result;
}
2.1.2、一元二次方程函数
圆的计算过程中要用到一元二次方程,所以这里提供计算一元二次方程的方法。
/**
* 一元二次方程求解
* @param a 二次项系数
* @param b 一次项系数
* @param c 常数
* @return 计算结果返回数组
*/
public static double[] quadratic_equation_one(double a,double b,double c){
double[] result=null;//3、小于0:有两个复根,一般不考虑这种情况但为了完整都写好
//三种情况
double data=b*b-4*a*c;
if (data>0){//1、大于0:有两个实根
result=new double[2];
result[0]=(-b+Math.sqrt(data))/(2*a);
result[1]=(-b-Math.sqrt(data))/(2*a);
}else if (data==0){//2、等于0:有一个实根
result=new double[1];
result[0]=(-b)/(2*a);
}
return result;
}
3、绘制方法
3.1、方法一:直接绘制
//方法一:直接绘制圆,部分区域会被错过
int i,j;
for (i = 0; i < 500; i++) {
//判断在圆的范围内才绘制
for (j = 0; j < 250; j++) {
result=UiMath.circle(250-j,250,250,i-j);
if (result!=null){
if (result.length==1){//传入的x和y值必须大于0
customBitmap.setPixel(i-j, (int) result[0],Color.parseColor("#ff0000"));
customBitmap.setPixel((int) result[0],i-j,Color.parseColor("#ff0000"));
}else if (result.length==2){
customBitmap.setPixel(i-j, (int) result[0],Color.parseColor("#ff0000"));
customBitmap.setPixel(i-j, (int) result[1],Color.parseColor("#ff0000"));
customBitmap.setPixel((int) result[0],i-j,Color.parseColor("#ff0000"));
customBitmap.setPixel((int) result[1],i-j,Color.parseColor("#ff0000"));
}
}
}
}
3.2、方法二:反向绘制
先把需要绘制的区域全部填充颜色,然后的圆形以外的区域设置为透明色。
//方法二:反向绘制
//1、先绘制背景色
for (i = 0; i < 500; i++) {
//判断在圆的范围内才绘制
for (j = 0; j < 500; j++) {
customBitmap.setPixel(i,j,Color.parseColor("#ff0000"));
}
}
//2、去除多余区域
for (i = 0; i < 500; i++) {
result=UiMath.circle(250,250,250,i);
if (result!=null){
if (result.length==1){//传入的x和y值必须大于0
for (j = 0; j < 500; j++) {
if (j<result[0] || j>result[0]){
customBitmap.setPixel(i, j,Color.parseColor("#00000000"));
}
}
}else if (result.length==2){
for (j = 0; j < 500; j++) {
if (j<result[1] || j>result[0]){
customBitmap.setPixel(i, j,Color.parseColor("#00000000"));
}
}
}
}
}
4、保存图片
调用下面这个方法保存图片,如果保存为jpg格式是没有透明效果的。
/**
* 保存bitmap为图片
*/
private void saveBitmap(Bitmap bitmap) {
new Thread(){
@Override
public void run() {
File file=new File(getExternalFilesDir(null),"now.png");
try {
FileOutputStream fos=new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG,90,fos);
fos.flush();
fos.close();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(CreateBitmapActivity.this,"保存完成",
Toast.LENGTH_SHORT).show();
}
});
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}.start();
}