我们经常会看到很多APP会有一个截图的功能,虽然现在很多手机本身已经有截图的功能了,但是截图后不能加水印,这也是不小的麻烦,今天我们聊聊怎么截图APP当前界面自己想要的内容,并且加上水印后保存。
先看看我们的总体界面的效果。
这个就是在我点击保存按钮后保存图片的效果截图。下方是加了一个文字水印,当然我们还可以实现图片水印。
这一次我们就采用循序渐进的方式来一步步探索这一个功能。先看怎么截图和保存。
我先谈谈思路,既然是一张截图,那首先就是一张图,任何一张图都有宽和高,这是基本属性,那么这个宽跟高是什么呢?就是我们所要的内容的高和宽,我们直接计算整个父级容器的高宽即可,然后这里要介绍一个系统的方法:
Bitmap.createBitmap(width, height, config)
看名字就很清楚了,原来这个是创建一个Bitmap,那就好办了,这里需要传入高、宽、还有一个bitmap的配置,这里我们直接传入Bitmap.Config.ARGB_8888。
然后调用父级容器的draw方法绘制就行了。完整的代码是:
/**
* 把布局转换成bitmap
* @param scrollView
* @return bitmap
*/
public Bitmap getBitmapByView(ScrollView scrollView) {
Bitmap bitmap = null;
// 创建对应大小的bitmap
bitmap = Bitmap.createBitmap(scrollView.getWidth(), scrollView.getHeight(),
Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bitmap);
scrollView.draw(canvas);
// 测试输出
FileOutputStream out = null;
try {
out = new FileOutputStream("/sdcard/screen_test.png");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
if (null != out) {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
我们这里的父级容器是ScrollView ,所以使用的是ScrollView 的宽、高。另外我这里模拟了一下保存,看不懂也没关系,实际并没用上。
下面看看我们是怎么执行保存操作的。
/**
* 保存图片至/sdcard/myFolder文件夹下
* @param bmp
*/
public void saveCroppedImage(Bitmap bmp) {
File file = new File("/sdcard/myFolder");
if (!file.exists())
file.mkdir();
long time= System.currentTimeMillis();
file = new File("/sdcard/"+time+".jpg".trim());
String fileName = file.getName();
String mName = fileName.substring(0, fileName.lastIndexOf("."));
String sName = fileName.substring(fileName.lastIndexOf("."));
newFilePath = "/sdcard/myFolder" + "/" + mName + sName;
file = new File(newFilePath);
try {
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
bmp.compress(CompressFormat.JPEG, 50, fos);
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
这里是一个保存的操作了,把刚刚生成的bitmap传入这个方法就可以了,不是很难,我们学文件操作的时候都接触过,我这里是把文件保存在了/sdcard/myFolder目录下,这个目录可以自定义,另外我这里的文件名是采用当前的系统时间加上后缀名。
文件截图跟文件保存都有了,下面可以看看怎么生成水印了,先看看生成生成照片的水印。看看代码:
/**
* 有水印的保存
* @param photo 当前截图的bitmap
* @param mark 水印的图片
* @param image 控件
* @return
*/
public Bitmap addTagUtil(Bitmap photo){
Bitmap photoMark = Bitmap.createBitmap(photo.getWidth(), photo.getHeight(), Config.ARGB_8888);
Bitmap mark= BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_launcher);
Canvas canvas = new Canvas(photoMark);
canvas.drawBitmap(photo, 0, 0, null);
Bitmap bitmapMark =mark.copy(Bitmap.Config.ARGB_8888, true);
canvas.drawBitmap(bitmapMark, photo.getWidth() - bitmapMark.getWidth()-10, photo.getHeight() - bitmapMark.getHeight(), null);
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.restore();
return photoMark;
}
这里实际上也是在创建一个bitmap,只是我们用canvas去绘制的时候有重叠的部分。一般的,水印都是在图片的右下角,所以我们也是按照套路来。这个方法返回的bitmap就是一个已经有图片水印的bitmap了,同样可以调用saveCroppedImage(bitmap)来保存。
接下来再看看绘制有文字水印的截图:
/**
* 添加文字到图片,类似水印文字。
* @param gContext
* @param gResId
* @param gText
* @return
*/
public Bitmap drawTextToBitmap(Bitmap bitmap, String gText) {
Resources resources = mContext.getResources();
float scale = resources.getDisplayMetrics().density;
android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();
if (bitmapConfig == null) {
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.parseColor("#458EFD"));
paint.setTextSize((int) (3 * scale*5));
paint.setShadowLayer(1f, 0f, 1f, Color.WHITE);
Rect bounds = new Rect();
paint.getTextBounds(gText, 0, gText.length(), bounds);
int x = (bitmap.getWidth() - bounds.width())/10*9 ;
int y = (bitmap.getHeight() + bounds.height())/10*9;
canvas.drawText(gText, x , y, paint);
return bitmap;
}
可以看到这实际上也是一个套路,我们把文字传进去,在前面我们讲自定义View的时候接触过很多绘制文字的操作,所以我觉得也不需要再去解释怎么绘制文字了。同样的这里返回一个bitmap,那么这个bitmap就是带有文字的水印了。
当然,为了让截图效果更逼真,我们还可以加上一个属性动画:
/**
* 定义动画
* @param mBg 父级容器
* @param mImage 将要显示的图片控件
* @param bitmap 图片
*/
public void startAnim(final LinearLayout mBg,final ImageView mImage,final Bitmap bitmap){
//设置为半透明
mBg.setBackgroundColor(Color.parseColor("#e0000000"));
PropertyValuesHolder values1=PropertyValuesHolder.ofFloat("alpha", 0f,1f,0.5f);
PropertyValuesHolder values2=PropertyValuesHolder.ofFloat("scaleX", 1,3/4f);
PropertyValuesHolder values3=PropertyValuesHolder.ofFloat("scaleY", 1,3/4f);
ObjectAnimator animator=ObjectAnimator.ofPropertyValuesHolder(mImage, values1,values2,values3);
animator.setDuration(1000);
animator.setInterpolator(new DecelerateInterpolator());
animator.start();
animator.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator arg0) {
}
@Override
public void onAnimationRepeat(Animator arg0) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationEnd(Animator arg0) {
mImage.setVisibility(View.INVISIBLE);
//重置背景
mBg.setBackgroundColor(Color.parseColor("#00000000"));
}
@Override
public void onAnimationCancel(Animator arg0) {
// TODO Auto-generated method stub
}
});
}
这样就可以实现截图的功能了。下面我贴上全部代码:
布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.ssssss.MainActivity" >
<TextView
android:id="@+id/save"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#458EFD"
android:gravity="center"
android:padding="10dip"
android:text="保存"
android:textColor="#ffffff"
android:textSize="20sp" />
<ScrollView
android:id="@+id/mScrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#eeeeee" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dip"
android:text="花淡淡,水悠悠,叶田田。那又是谁斑驳了这绝世的花颜,携一帘幽梦,
盈一袖轻云,掬一滴清泉,揽一缕清风,娴静优雅,柔情缱绻,尾随而来?莲花初开,微风徐来,沁心的荷香,
诗意了岁月,徜徉了人间,嗅着这若有若无的淡淡荷花香,一股通灵的感觉如游丝般慢慢的浸润了心扉,
躁动的心儿也仿佛跟着悄然安静了下来。
“陌上欣欣青绿邈,岁岁年年,轮转无终了。”那又是谁蹙一弯峨眉,流转于潋滟碧波;嬉一袭水袖,惊鸿在风尘阙歌?逸动的涟漪,惑起的水滴,风动荷香,花开莲池。那又是谁羞答答的捧起那一宛粉,一宛白,以珠水空灵的韵味勾勒出那娓娓垂涎流香?风过,心头一抹芬芳,指尖一缕余香。是莲花开了吗?是莲花她处处开了吗? 那我为何只见花开,不见你来?
少时,小雨随风而至。倾时,云水之巅,清风细雨,烟雾迷弥,翠玉轻翻,红粉留痕,氤氲的莲池瞬时漾起一行行醉人的音符。“蕊中千滴泪,心里万条丝。”滴滴细雨,悠悠情思,那淡淡风痕处,款款崖暖时,你可晓莲花她已处处开?氤氲烟雨中,毓秀淡雅刻,那你又可懂迷离了谁的清波凝眸?馨香的花瓣,百年的凝望,千年的等待,“荷花频频,杨柳依依”,
“三生两会,两世相逢”。既然,山和水可以彼此相忘,星和月可以流光相皎。风华只是一指流沙,苍老只是一段年华。那么,心儿在您的世界,您的天空可真的有我?" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dip"
android:text="“陌上欣欣青绿邈,岁岁年年,轮转无终了。" />
LinearLayout>
<LinearLayout
android:id="@+id/image_bg"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="@+id/jietu_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" />
LinearLayout>
RelativeLayout>
ScrollView>
LinearLayout>
主界面:
public class MainActivity extends Activity {
private TextView button;
private ScrollView mScrollView;
private ImageView mImage;
private LinearLayout mBg;
private Utils utils;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
utils=new Utils(MainActivity.this);
initView();
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Bitmap bitmap = utils.getBitmapByView(mScrollView);//这里返回的是没有水印的图片
mImage.setVisibility(View.VISIBLE);
utils.startAnim(mBg,mImage,bitmap);
// bitmap= utils.addTagUtil(bitmap);//返回有图片水印
bitmap=utils.drawTextToBitmap(bitmap, "http://blog.csdn.net/qq_25193681");//返回有文字的水印
utils.saveCroppedImage(bitmap);
mImage.setImageBitmap(bitmap);
mImage.setVisibility(View.VISIBLE);
}
});
}
private void initView() {
mScrollView=(ScrollView) findViewById(R.id.mScrollview);
button=(TextView) findViewById(R.id.save);
mBg=(LinearLayout) findViewById(R.id.image_bg);
mImage=(ImageView) findViewById(R.id.jietu_image);
}
}
工具类;
public class Utils {
private Context mContext;
public Utils(Context mContext) {
this.mContext = mContext;
}
private static String newFilePath = "";
/**
* 定义动画
* @param mBg 父级容器
* @param mImage 将要显示的图片控件
* @param bitmap 图片
*/
public void startAnim(final LinearLayout mBg,final ImageView mImage,final Bitmap bitmap){
//设置为半透明
mBg.setBackgroundColor(Color.parseColor("#e0000000"));
PropertyValuesHolder values1=PropertyValuesHolder.ofFloat("alpha", 0f,1f,0.5f);
PropertyValuesHolder values2=PropertyValuesHolder.ofFloat("scaleX", 1,3/4f);
PropertyValuesHolder values3=PropertyValuesHolder.ofFloat("scaleY", 1,3/4f);
ObjectAnimator animator=ObjectAnimator.ofPropertyValuesHolder(mImage, values1,values2,values3);
animator.setDuration(1000);
animator.setInterpolator(new DecelerateInterpolator());
animator.start();
animator.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator arg0) {
}
@Override
public void onAnimationRepeat(Animator arg0) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationEnd(Animator arg0) {
mImage.setVisibility(View.INVISIBLE);
//重置背景
mBg.setBackgroundColor(Color.parseColor("#00000000"));
}
@Override
public void onAnimationCancel(Animator arg0) {
// TODO Auto-generated method stub
}
});
}
/**
* 把布局转换成bitmap
* @param scrollView
* @return bitmap
*/
public Bitmap getBitmapByView(ScrollView scrollView) {
Bitmap bitmap = null;
// 创建对应大小的bitmap
bitmap = Bitmap.createBitmap(scrollView.getWidth(), scrollView.getHeight(),
Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bitmap);
scrollView.draw(canvas);
// 测试输出
FileOutputStream out = null;
try {
out = new FileOutputStream("/sdcard/screen_test.png");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
if (null != out) {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
/**
* 保存图片至/sdcard/myFolder文件夹下
* @param bmp
*/
public void saveCroppedImage(Bitmap bmp) {
File file = new File("/sdcard/myFolder");
if (!file.exists())
file.mkdir();
long time= System.currentTimeMillis();
file = new File("/sdcard/"+time+".jpg".trim());
String fileName = file.getName();
String mName = fileName.substring(0, fileName.lastIndexOf("."));
String sName = fileName.substring(fileName.lastIndexOf("."));
newFilePath = "/sdcard/myFolder" + "/" + mName + sName;
file = new File(newFilePath);
try {
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
bmp.compress(CompressFormat.JPEG, 50, fos);
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 有水印的保存
* @param photo 当前截图的bitmap
* @param mark 水印的图片
* @param image 控件
* @return
*/
public Bitmap addTagUtil(Bitmap photo){
Bitmap photoMark = Bitmap.createBitmap(photo.getWidth(), photo.getHeight(), Config.ARGB_8888);
Bitmap mark= BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_launcher);
Canvas canvas = new Canvas(photoMark);
canvas.drawBitmap(photo, 0, 0, null);
Bitmap bitmapMark =mark.copy(Bitmap.Config.ARGB_8888, true);
canvas.drawBitmap(bitmapMark, photo.getWidth() - bitmapMark.getWidth()-10, photo.getHeight() - bitmapMark.getHeight(), null);
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.restore();
return photoMark;
}
/**
* 添加文字到图片,类似水印文字。
* @param gContext
* @param gResId
* @param gText
* @return
*/
public Bitmap drawTextToBitmap(Bitmap bitmap, String gText) {
Resources resources = mContext.getResources();
float scale = resources.getDisplayMetrics().density;
android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();
if (bitmapConfig == null) {
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.parseColor("#458EFD"));
paint.setTextSize((int) (3 * scale*5));
paint.setShadowLayer(1f, 0f, 1f, Color.WHITE);
Rect bounds = new Rect();
paint.getTextBounds(gText, 0, gText.length(), bounds);
int x = (bitmap.getWidth() - bounds.width())/10*9 ;
int y = (bitmap.getHeight() + bounds.height())/10*9;
canvas.drawText(gText, x , y, paint);
return bitmap;
}
}
当然,我觉得小伙伴光粘贴复制,那肯定不过瘾,下面我再把源码贴上:源码