Android 仿各主流便签内容生成长图功能

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之间,基本还在可以接受的程度,当然 手机配置越高需要时间越短啦。。。。


阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013278940/article/details/52193022
文章标签: Android 生成长图
个人分类: Android学习
上一篇Android 点击水波纹扩散效果( Ripple Effect )
下一篇Android自绘字体大小paint.settextsize随分辨率大小变化
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭