1.前言
目前各大主流手机均有各自的便签记事本之类的工具,并且功能逐渐完善,其中有一项功能——生成图片分享比较吸引眼球,尤其是有些社交app在发动态是有字数限制,如果将要发的内容生成图片就会解决这个困扰。对比了几家手机的自带便签,三星不具备生成图片,锤子,魅族,华为具备,但生成时有稍微卡顿,小米同样具备,生成图片时未出现明显卡顿。目标,自己做出不太明显卡顿即可。
2.思路
生成图片并保存,必须实现一个画布绘制。故思路:
a 获取便签内容,包含文本 图片 icon等,根据便签内容计算所需画布长度(即长图的高度)
b 获取便签背景,并将背景提前绘制到画布上
c 分析内容文本直接调用canvas.drawText绘制,图片 icon 用canvas.drwaBitmap()绘制.
d 绘制完成,图片保存到指定路径。
3.实现
private void doCreateBitmap() {//开始生成长图
Toast.makeText(getApplicationContext(),getResources().
getString(R.string.shareimagecreaate), Toast.LENGTH_LONG).show();
String text = mText.getText().toString();//获取便签内容
/*新起一个线程执行计算长度绘图等操作,因为绘图是个耗时较长的操作,
在UI线程中之行容易给用户一种app卡死的感觉。*/
Thread t=new Thread(new shareRunnable(text));
t.start();
} public class shareRunnable implements Runnable{
String Rtext;
shareRunnable(String text){
Rtext=text;
}
@Override
public void run() {
<span style="color:#ff0000;">drawBitmap(Rtext);//绘制长图</span>
/*下面代码是分享到各大社交app的实现*/
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
String path = Environment.getExternalStorageDirectory() + "/gnotes/share.png";
Uri uri=Uri.parse("file:///"+path);
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
shareIntent.setType("image/*");
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.share)));
}
} private void drawBitmap(String text) {
int xStart=40;//距离左边界宽度
int stringlength=20;//每行包含字符串数
int lineHeight=75;//每行高度
int bitmapHeight=300;//图片规定高度
int lineNumber=0;//笔记中包含文字行数
int bitmapNumber=0;//笔记中包含图片张数
int bitmapTotalHeight=0;//文本中包含图片总高度
int heightCount=80;//绘制长度,初始值为80
String s1="/storage/";
String s2="";
Resources res = getResources();
Bitmap skin_head = BitmapFactory.decodeResource(res, HeadId[skinIndex]);
Bitmap skin_list = BitmapFactory.decodeResource(res, BackgroundRepeatId[skinIndex]);
Bitmap skin_tail = BitmapFactory.decodeResource(res, TailId[skinIndex]);
int skin_headHeight=skin_head.getHeight();
int skin_listHeight=skin_list.getHeight();
int skin_listWidth =skin_list.getWidth();
int skin_tailHeight=skin_tail.getHeight();
//计算一共有多少段文字(包含图片路径)
String[] texts=text.split("\n");
for(int j=0;j<texts.length;j++){
if(texts[j].contains(s1)){
String[] spath=texts[j].split("/");
String path=null;
if(spath[0].equals("")||spath[0]==null){
path = texts[j];
}else{
path=texts[j].substring(spath[0].length(), texts[j].length());
}
bitmapNumber=bitmapNumber+1;
Bitmap bm = BitmapFactory.decodeFile(path);
bitmapTotalHeight=bitmapTotalHeight+lineHeight+bm.getHeight();
}else{
lineNumber=lineNumber+texts[j].length()/stringlength+1;
}
}
int heightBitmap=(lineNumber+bitmapNumber+2)*lineHeight+bitmapTotalHeight;
WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
//int widthBitmap = wm.getDefaultDisplay().getWidth();
int widthBitmap=skin_head.getWidth();
int duanshu=text.length()/stringlength+1;
Bitmap bitmap = Bitmap.createBitmap(widthBitmap, heightBitmap, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(2);
paint.setTextSize(35);
paint.setTypeface(Typeface.DEFAULT_BOLD);
int skinHeight=0;
canvas.drawBitmap(skin_head, 0, 0, paint);
skinHeight=skinHeight+skin_headHeight;
while(skinHeight<heightBitmap){
canvas.drawBitmap(skin_list, 0, skinHeight, paint);
for(int i=skin_listWidth;i<widthBitmap;i=i+skin_listWidth){
canvas.drawBitmap(skin_list, i, skinHeight, paint);
}
skinHeight=skinHeight+skin_listHeight;
}
canvas.drawBitmap(skin_tail, 0, heightBitmap-skin_tailHeight, paint);
//开始绘制文本和图片
Bitmap bitmapCircleNormal=BitmapFactory.decodeResource(res, R.drawable.circle_normal);
Bitmap bitmapCircleSelected=BitmapFactory.decodeResource(res, R.drawable.circle_selected);
int circleWidth=bitmapCircleNormal.getWidth()+10;
for(int j=0;j<texts.length;j++){
if(texts[j].contains(s1)){
//插入图片操作
String path = null;
String[] spath=texts[j].split("/");
if(spath[0].equals("")||spath[0]==null){
path = texts[j];
}else{
canvas.drawText(spath[0], xStart+circleWidth, heightCount, paint);
path=texts[j].substring(spath[0].length(), texts[j].length());
}
Bitmap bm = BitmapFactory.decodeFile(path);
bm=resizetoshare(bm,widthBitmap);
int height=bm.getHeight();
heightCount=heightCount+lineHeight;
canvas.drawBitmap(bm, xStart, heightCount, paint);
heightCount=heightCount+height;
}else{
//画选择框
boolean hasCircle=false;
if(texts[j].contains("circle_normal")){
canvas.drawBitmap(bitmapCircleNormal, xStart, heightCount+lineHeight-circleWidth/2, paint);
texts[j]=texts[j].substring(13, texts[j].length());
hasCircle=true;
}else if(texts[j].contains("circle_select")){
canvas.drawBitmap(bitmapCircleSelected, xStart, heightCount+lineHeight-circleWidth/2, paint);
texts[j]=texts[j].substring(13, texts[j].length());
hasCircle=true;
}
//画文本
int mline=texts[j].length()/stringlength+1;
for(int i=0;i<mline;i++){
heightCount=heightCount+lineHeight;
int XIncludeBitmapStart=xStart+circleWidth;
if(i==mline-1){
String drawtext=texts[j].substring(stringlength*i, texts[j].length());
if(hasCircle){
canvas.drawText(drawtext, xStart+circleWidth, heightCount, paint);
hasCircle=false;
}else{
canvas.drawText(drawtext, xStart, heightCount, paint);
}
}else{
String drawtext=texts[j].substring(stringlength*i, stringlength*(i+1)-1);
if(hasCircle){
canvas.drawText(drawtext, xStart+circleWidth, heightCount, paint);
hasCircle=false;
}else{
canvas.drawText(drawtext, xStart, heightCount, paint);
}
}
}
}
}
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.restore();
String path = Environment.getExternalStorageDirectory() + "/gnotes";//图片保存路径
File mfile=new File(path);
if(!mfile.exists()){
mfile.mkdir();
}
try {
FileOutputStream fos = new FileOutputStream(mfile+"/share.png");
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);//以png格式保存
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}将图片重新编辑用来匹配屏幕宽度:
@SuppressWarnings("UnnecessaryLocalVariable")
private Bitmap resizetoshare(Bitmap bitmap, int widthBitmap) {
// DisplayMetrics dm = new DisplayMetrics();
// getWindowManager().getDefaultDisplay().getMetrics(dm);
int screenwidth = widthBitmap;
int padding = getResources().getDimensionPixelSize(R.dimen.g_note_padding_left);
int border = getResources().getDimensionPixelSize(R.dimen.g_note_image_border);
int shadow = getResources().getDimensionPixelSize(R.dimen.g_note_image_shadow);
int contentwidth = screenwidth - 2*padding - 2*border -2*shadow;
int imgWidth = bitmap.getWidth();
int imgHeight = bitmap.getHeight();
if (contentwidth >= imgWidth) {
return bitmap;
} else {
float scale = (float) (contentwidth*1.0/imgWidth);
Matrix mx = new Matrix();
mx.postScale(scale, scale);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, imgWidth, imgHeight, mx, true);
return bitmap;
}
}4.总结
此功能实现难在如何计算长图每行绘制多少内容,需要多高的画布方面,实现起来真正涉及到的高深算法倒是没有,在于计算时根据设计的要求细心调试以达到最优的呈现效果,目前生成图片纯文本需要时间<1s,内容中包含一张图片时间1S-3S之间,两张图3S-5S之间,基本还在可以接受的程度,当然 手机配置越高需要时间越短啦。。。。
本文介绍了一种实现便签内容生成图片分享的方法。通过分析便签内容,包括文本和图片,计算所需画布尺寸并绘制内容。该方案考虑了不同设备间的适配性,实现了较为流畅的生成体验。
6181

被折叠的 条评论
为什么被折叠?



