Android常用实例——截取APP当前界面(可带图片、文字水印)

我们经常会看到很多APP会有一个截图的功能,虽然现在很多手机本身已经有截图的功能了,但是截图后不能加水印,这也是不小的麻烦,今天我们聊聊怎么截图APP当前界面自己想要的内容,并且加上水印后保存。

先看看我们的总体界面的效果。

Android常用实例——截取APP当前界面(可带图片、文字水印)_第1张图片

这个就是在我点击保存按钮后保存图片的效果截图。下方是加了一个文字水印,当然我们还可以实现图片水印。

这一次我们就采用循序渐进的方式来一步步探索这一个功能。先看怎么截图和保存。

我先谈谈思路,既然是一张截图,那首先就是一张图,任何一张图都有宽和高,这是基本属性,那么这个宽跟高是什么呢?就是我们所要的内容的高和宽,我们直接计算整个父级容器的高宽即可,然后这里要介绍一个系统的方法:

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;  
    }  

}

当然,我觉得小伙伴光粘贴复制,那肯定不过瘾,下面我再把源码贴上:源码

你可能感兴趣的:(Android)