Android编程实现支持拖动改变位置的图片中叠加文字功能示例
程序员文章站
2024-02-20 13:43:10
本文实例讲述了android编程实现支持拖动改变位置的图片中叠加文字功能。分享给大家供大家参考,具体如下:
之所以做了这么一个demo,是因为最近项目中有一个奇葩的需求:...
本文实例讲述了android编程实现支持拖动改变位置的图片中叠加文字功能。分享给大家供大家参考,具体如下:
之所以做了这么一个demo,是因为最近项目中有一个奇葩的需求:用户拍摄照片后,分享到微信的同时添加备注,想获取用户在微信的弹出框输入的内容,保存在自己的服务器上。而事实上,这个内容程序是无法获取的,因此采取了一个折衷方案,将文字直接写在图片上。
首先上demo效果图:
功能:
1.用户*输入内容,可手动换行,并且行满也会自动换行。
2.可拖动改变图片中文本位置(文字不会超出图片区域)。
3.点击“生成图片”按钮之后,生成一张带有文字的图片文件。
代码不多,直接全部贴上了:
activity:
/** * 将文字写在图片中(截图方式),支持拖动文字。<br/> * 说明:很明显,截图方式会降低图片的质量。如果需要保持图片质量可以使用canvas的方式,将文字直接绘制在图片之上(不过,使用此方式要实现文字拖动较为复杂)。 */ public class mainactivity extends appcompatactivity { //图片组件 private imageview imageview; //位于图片中的文本组件 private textview tvinimage; //图片和文本的父组件 private view containerview; //父组件的尺寸 private float imagewidth, imageheight, imagepositionx, imagepositiony; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.image_with_text); imageview = (imageview) findviewbyid(r.id.writetext_img); edittext edittext = (edittext) findviewbyid(r.id.writetext_et); tvinimage = (textview) findviewbyid(r.id.writetext_image_tv); containerview = findviewbyid(r.id.writetext_img_rl); imageview.getviewtreeobserver().addongloballayoutlistener(new viewtreeobserver.ongloballayoutlistener() { @override public void ongloballayout() { imageview.getviewtreeobserver().removeongloballayoutlistener(this); imagepositionx = imageview.getx(); imagepositiony = imageview.gety(); imagewidth = imageview.getwidth(); imageheight = imageview.getheight(); //设置文本大小 tvinimage.setmaxwidth((int) imagewidth); } }); imageview.setimagebitmap(getscaledbitmap(r.mipmap.test_img)); //输入框 edittext.addtextchangedlistener(new textwatcher() { @override public void beforetextchanged(charsequence s, int start, int count, int after) { } @override public void ontextchanged(charsequence s, int start, int before, int count) { if (s.tostring().equals("")) { tvinimage.setvisibility(view.invisible); } else { tvinimage.setvisibility(view.visible); tvinimage.settext(s); } } @override public void aftertextchanged(editable s) { } }); final gesturedetector gesturedetector = new gesturedetector(this, new simplegesturelistenerimpl()); //移动 tvinimage.setontouchlistener(new view.ontouchlistener() { @override public boolean ontouch(view v, motionevent event) { gesturedetector.ontouchevent(event); return true; } }); } //确认,生成图片 public void confirm(view view) { bitmap bm = loadbitmapfromview(containerview); string filepath = environment.getexternalstoragedirectory() + file.separator + "image_with_text.jpg"; try { bm.compress(bitmap.compressformat.jpeg, 100, new fileoutputstream(filepath)); toast.maketext(this, "图片已保存至:sd卡根目录/image_with_text.jpg", toast.length_long).show(); } catch (filenotfoundexception e) { e.printstacktrace(); } } //以图片形式获取view显示的内容(类似于截图) public static bitmap loadbitmapfromview(view view) { bitmap bitmap = bitmap.createbitmap(view.getwidth(), view.getheight(), bitmap.config.argb_8888); canvas canvas = new canvas(bitmap); view.draw(canvas); return bitmap; } private int count = 0; //tvinimage的x方向和y方向移动量 private float mdx, mdy; //移动 private class simplegesturelistenerimpl extends gesturedetector.simpleongesturelistener { @override public boolean onscroll(motionevent e1, motionevent e2, float distancex, float distancey) { //向右移动时,distancex为负;向左移动时,distancex为正 //向下移动时,distancey为负;向上移动时,distancey为正 count++; mdx -= distancex; mdy -= distancey; //边界检查 mdx = calposition(imagepositionx - tvinimage.getx(), imagepositionx + imagewidth - (tvinimage.getx() + tvinimage.getwidth()), mdx); mdy = calposition(imagepositiony - tvinimage.gety(), imagepositiony + imageheight - (tvinimage.gety() + tvinimage.getheight()), mdy); //控制刷新频率 if (count % 5 == 0) { tvinimage.setx(tvinimage.getx() + mdx); tvinimage.sety(tvinimage.gety() + mdy); } return true; } } //计算正确的显示位置(不能超出边界) private float calposition(float min, float max, float current) { if (current < min) { return min; } if (current > max) { return max; } return current; } //获取压缩后的bitmap private bitmap getscaledbitmap(int resid) { bitmapfactory.options opt = new bitmapfactory.options(); opt.injustdecodebounds = true; bitmapfactory.decoderesource(getresources(), resid, opt); opt.insamplesize = utility.calculateinsamplesize(opt, 600, 800); opt.injustdecodebounds = false; return bitmapfactory.decoderesource(getresources(), resid, opt); } }
一个工具类:
public class utility { //计算 insamplesize 值,压缩图片 public static int calculateinsamplesize(bitmapfactory.options options, int reqwidth, int reqheight) { // raw height and width of image final int height = options.outheight; final int width = options.outwidth; int insamplesize = 1; if (height > reqheight || width > reqwidth) { final int halfheight = height / 2; final int halfwidth = width / 2; // calculate the largest insamplesize value that is a power of 2 and keeps both // height and width larger than the requested height and width. while ((halfheight / insamplesize) > reqheight && (halfwidth / insamplesize) > reqwidth) { insamplesize *= 2; } } return insamplesize; } }
布局文件:
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="10dp"> <relativelayout android:id="@+id/writetext_img_rl" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal"> <imageview android:id="@+id/writetext_img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:maxheight="360dp" android:adjustviewbounds="true" android:contentdescription="@null"/> <textview android:id="@+id/writetext_image_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:visibility="invisible" android:layout_centerinparent="true" android:background="#79652a" android:clickable="true" android:padding="4dp" android:textcolor="@android:color/white" android:textsize="15sp" /> </relativelayout> <edittext android:id="@+id/writetext_et" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margintop="8dp" android:hint="添加备注" /> <button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onclick="confirm" android:text="生成图片" /> </linearlayout>
更多关于android相关内容感兴趣的读者可查看本站专题:《android图形与图像处理技巧总结》、《android开发入门与进阶教程》、《android调试技巧与常见问题解决方法汇总》、《android基本组件用法总结》、《android视图view技巧总结》、《android布局layout技巧总结》及《android控件用法总结》
希望本文所述对大家android程序设计有所帮助。