本文详细介绍了Android编程实现支持拖动改变位置的图片中叠加文字功能的实例代码,有兴趣的同学可以将代码拿过去使用。
本文实例讲述了Android编程实现支持拖动改变位置的图片中叠加文字功能。分享给大家供大家参考,具体如下:
之所以做了这么一个Demo,是因为最近项目中有一个奇葩的需求:用户拍摄照片后,分享到微信的同时添加备注,想获取用户在微信的弹出框输入的内容,保存在自己的服务器上。而事实上,这个内容程序是无法获取的,因此采取了一个折衷方案,将文字直接写在图片上。
首先上Demo效果图:
功能:
1.用户自由输入内容,可手动换行,并且行满也会自动换行。
2.可拖动改变图片中文本位置(文字不会超出图片区域)。
3.点击“生成图片”按钮之后,生成一张带有文字的图片文件。
代码不多,直接全部贴上了:
Activity:
代码如下复制代码
/**
* 将文字写在图片中(截图方式),支持拖动文字。
* 说明:很明显,截图方式会降低图片的质量。如果需要保持图片质量可以使用canvas的方式,将文字直接绘制在图片之上(不过,使用此方式要实现文字拖动较为复杂)。
*/
publicclassMainActivityextendsAppCompatActivity {
//图片组件
privateImageView imageView;
//位于图片中的文本组件
privateTextView tvInImage;
//图片和文本的父组件
privateView containerView;
//父组件的尺寸
privatefloatimageWidth, imageHeight, imagePositionX, imagePositionY;
@Override
protectedvoidonCreate(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(newViewTreeObserver.OnGlobalLayoutListener() {
@Override
publicvoidonGlobalLayout() {
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(newTextWatcher() {
@Override
publicvoidbeforeTextChanged(CharSequence s,intstart,intcount,intafter) {
}
@Override
publicvoidonTextChanged(CharSequence s,intstart,intbefore,intcount) {
if(s.toString().equals("")) {
tvInImage.setVisibility(View.INVISIBLE);
}else{
tvInImage.setVisibility(View.VISIBLE);
tvInImage.setText(s);
}
}
@Override
publicvoidafterTextChanged(Editable s) {
}
});
finalGestureDetector gestureDetector =newGestureDetector(this,newSimpleGestureListenerImpl());
//移动
tvInImage.setOnTouchListener(newView.OnTouchListener() {
@Override
publicbooleanonTouch(View v, MotionEvent event) {
gestureDetector.onTouchEvent(event);
returntrue;
}
});
}
//确认,生成图片
publicvoidconfirm(View view) {
Bitmap bm = loadBitmapFromView(containerView);
String filePath = Environment.getExternalStorageDirectory() + File.separator +"image_with_text.jpg";
try{
bm.compress(Bitmap.CompressFormat.JPEG,100,newFileOutputStream(filePath));
Toast.makeText(this,"图片已保存至:SD卡根目录/image_with_text.jpg", Toast.LENGTH_LONG).show();
}catch(FileNotFoundException e) {
e.printStackTrace();
}
}
//以图片形式获取View显示的内容(类似于截图)
publicstaticBitmap loadBitmapFromView(View view) {
Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas =newCanvas(bitmap);
view.draw(canvas);
returnbitmap;
}
privateintcount =0;
//tvInImage的x方向和y方向移动量
privatefloatmDx, mDy;
//移动
privateclassSimpleGestureListenerImplextendsGestureDetector.SimpleOnGestureListener {
@Override
publicbooleanonScroll(MotionEvent e1, MotionEvent e2,floatdistanceX,floatdistanceY) {
//向右移动时,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);
}
returntrue;
}
}
//计算正确的显示位置(不能超出边界)
privatefloatcalPosition(floatmin,floatmax,floatcurrent) {
if(current < min) {
returnmin;
}
if(current > max) {
returnmax;
}
returncurrent;
}
//获取压缩后的bitmap
privateBitmap getScaledBitmap(intresId) {
BitmapFactory.Options opt =newBitmapFactory.Options();
opt.inJustDecodeBounds =true;
BitmapFactory.decodeResource(getResources(), resId, opt);
opt.inSampleSize = Utility.calculateInSampleSize(opt,600,800);
opt.inJustDecodeBounds =false;
returnBitmapFactory.decodeResource(getResources(), resId, opt);
}
}
一个工具类:
代码如下复制代码
publicclassUtility {
//计算 inSampleSize 值,压缩图片
publicstaticintcalculateInSampleSize(BitmapFactory.Options options,intreqWidth,intreqHeight) {
// Raw height and width of image
finalintheight = options.outHeight;
finalintwidth = options.outWidth;
intinSampleSize =1;
if(height > reqHeight || width > reqWidth) {
finalinthalfHeight = height /2;
finalinthalfWidth = 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;
}
}
returninSampleSize;
}
}
布局文件:
代码如下复制代码
<LinearLayoutxmlns: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"/>
<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="生成图片"/>
没有了
小编推荐的这篇文章介绍了Android基础之startActivityForResult()的用法详解,对初学android的同学来说非常有用,有需要的同学可以参考一下。
安卓开发中一个很基础的操作就是打开一个 Activity ,另一个很必要的操作就是,打开一个 Activity ,在打开的 Activity 中操作之后并获得返回结果。
两个 Activity