android中拖动文字实现功能,Android:图片中叠加文字,支持拖动改变位置

之所以做了这么一个Demo,是因为最近项目中有一个奇葩的需求:用户拍摄照片后,分享到微信的同时添加备注,想获取用户在微信的弹出框输入的内容,保存在自己的服务器上。而事实上,这个内容程序是无法获取的,因此采取了一个折衷方案,将文字直接写在图片上。

首先上Demo效果图:

21053093T_0.png

功能:

1.用户自由输入内容,可手动换行,并且行满也会自动换行。

2.可拖动改变图片中文本位置(文字不会超出图片区域)。

3.点击“生成图片”按钮之后,生成一张带有文字的图片文件。

代码不多,直接全部贴上了:

Activity:

/**

* 将文字写在图片中(截图方式),支持拖动文字。

* 说明:很明显,截图方式会降低图片的质量。如果需要保持图片质量可以使用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;

}

}

相关报道:

在进行数据查询的时候我们有真分页和假分页两种,所谓真分页就是按照根据pageIndex(当前页码)和pageSize(每页的记录条数)去数据库中查找响应的记录,而假分 更多

一.基本规则1.函数定义 在python中函数用关键字def声明,参数用逗号隔开,另外需要注意的是函数没有返回类型.Python函数不指定特定的返回类型,甚至不需要指定是否返回一个.但实际上,每一个python函数都会返回一 个.如果执行了return语句,那么它会返回 更多

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/419986.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

bzoj 3196/tyvj p1730 二逼平衡树

原题链接&#xff1a;http://www.tyvj.cn/p/1730 树套树。。。 如下&#xff1a; 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<algorithm> 5 #define lc root<<1 6 #define rc root<<1|1 7 #define INF…

联想android刷机教程,超详细的联想刷机教程~带你嘻刷刷

一、刷机是什么说到“刷机”&#xff0c;很多人可能会和“升级”混淆起来&#xff0c;其实升级和刷机并不是同一概念。通俗地讲&#xff0c;升级就是对手机内的软件或系统进行升级&#xff0c;比如很多厂商手机都支持的OTA空中在线升级。而刷机&#xff0c;则相当于就是重装系统…

多看 android6,多看阅读本地版

为您推荐&#xff1a;多看阅读《多看阅读本地版》是一款由多看科技倾情研发打造的海量优质完本小说免费在线阅读app软件&#xff0c;这款软件的功能非常的全面&#xff0c;操作性简单&#xff0c;上手起来非常的容易&#xff0c;在这款软件里&#xff0c;各位用户们将能够于此体…

UIProgressView-初识IOS

好几天没更新了&#xff0c;学的时候太紧&#xff0c;没时间复习了都。今天刚好有时间&#xff0c;多更几个。 今天复习的是UIProgressView,我们常见使用在修改某些属性的时候经常用到&#xff0c;比如透明度&#xff0c;今天我们介绍一个简单的使用例子 定义什么的&#xff0c…

浅谈0/1切换

前言:   做过GUI开发的同学, 都知晓双缓存机制. 其过程为先把所有的场景和实体对象画到一个备份canvas, 然后再把备份canvas的内容整个填充真正的画板canvas中. 如果不采用双缓存机制, 你的画面有可能会出现闪烁和抖动.   究其原因是整个绘制过程, 包含清屏, 绘制场景和各…

Action和Func区别

Action<>和Func<>其实都是委托的【代理】简写形式。 简单的委托写法&#xff1a; 1 //普通的委托2 public delegate void myDelegate(string str);3 4 //Delegate委托调。5 myDelegate dDelegate new myDelegate(SayHellow);6 dDelegate("Mr wang");7 8…

最好的android one手机,最高配置的Android One手机登场 LG推出G7 One与G7 F

原标题&#xff1a;最高配置的Android One手机登场 LG推出G7 One与G7 F集微网消息&#xff0c;Android One原本是谷歌与中国台湾的联发科共同开发的一个项目&#xff0c;旨在让手机制造商打造低成本的智能手机&#xff0c;这些手机主要是销售给新兴市场上的近10亿潜在用户。随着…

vs代码模板制作

VS2008代码模板制作 一&#xff0c;类模板制作&#xff1a; 路径&#xff1a;C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\ItemTemplatesCache\CSharp\Code\2052\Class.zip 操作&#xff1a;打开Class.cs文件&#xff0c;编辑内容如下&#xff1a; // <…

pads导出坐标文件html,【教程】PADS如何导出SMT贴片机用的坐标文件

找到一个好办法&#xff0c;用wps的Excel软件的话&#xff0c;将脚本进行如下修改即可。修改前&#xff1a;Sub ExportToExcel (txt As String)FillClipboardDim xl As ObjectOn Error Resume NextSet xl GetObject(,"Excel.Application")On Error GoTo ExcelError …

avalon框架,简单的MVVM

今天我又要挑战一次一个高大上的公司了 但是看着jd有点忧伤了要求如下 基本要求&#xff1a;1、熟悉 HTML / CSS / JS 并有良好的代码风格&#xff1b;2、理解 Web 标准&#xff0c;语义化&#xff0c;可以解决主流浏览器及不同版本的兼容性问题&#xff1b;3、熟悉常见框架&am…

html锚点反向联动,小程序菜单左右联动

最近做小程序的时候&#xff0c;产品提了一个需求&#xff1a;1.左侧的菜单栏和右侧的菜单可分别滚动&#xff0c;滚动左侧不影响右侧&#xff0c;滚动右侧左侧随之联动高亮显示所在的菜单分类。2.点击下方左侧导航菜单栏&#xff0c;高亮显示被点击的菜单分类&#xff0c;右侧…

第6/24周 聚集索引

上个星期我向你介绍了堆表&#xff08;heap tables&#xff09;。我们说过&#xff0c;在SQL Server表可以是堆表&#xff08;Heap Table&#xff09;或者聚集表&#xff08;Clustered Table&#xff09;——一个在它上面有聚集索引&#xff08;Clustered Index&#xff09;定义…

广西2021普通高考成绩查询,2021广西高考成绩什么时候出

2021广西高考成绩什么时候出2021-04-22 10:39:21文/叶丹2021广西高考成绩公布时间&#xff1a;预计6月23日。预计6月23日对考生开放高考成绩查询通道&#xff0c;并公布录取最低控制分数线。届时考生可查询高考成绩&#xff0c;请考生密切关注广西招生考试院官网、官方微博、官…

vmware安装中标麒麟高级服务器操作系统 V7.0

vmware安装中标麒麟高级服务器操作系统 V7.0 1、下载中标麒麟高级服务器操作系统 V7.0镜像2、安装中标麒麟高级服务器操作系统 V7.02.1、新建虚拟机2.2、安装虚拟机 3、配置中标麒麟高级服务器操作系统 V7.03.1、登录系统3.2、配置静态IP地址 和 dns3.3、查看磁盘分区3.4、查看…

2021年衢州高考的成绩查询,2021年衢州高考状元是谁分数多少分,历年衢州高考状元名单...

2020年衢州一年一度的高考考试已经结束&#xff0c;今年衢州高考状元是谁呢&#xff0c;衢州高考状元出自哪个高中学校&#xff0c;文理科分数是多少分&#xff0c;一起来了解。一、2020年衢州高考状元名单资料2020年衢州高考状元名单和学校相关信息&#xff0c;截至目前发文时…

计算机主机机箱面板指示灯,电脑主机指示灯不亮了是什么原因

公告&#xff1a; 为响应国家净网行动&#xff0c;部分内容已经删除&#xff0c;感谢读者理解。话题&#xff1a;电脑主机指示灯不亮了是什么原因&#xff1f;回答&#xff1a;是指示灯坏了。或者是主机主板出了问题。参考回答&#xff1a;绿灯不亮是电源问题红灯不亮是硬盘或者…