android实现截图并动画消失

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

整体思路

1、获取要截图的view
2、根据这个view创建Bitmap
3、保存图片,拿到图片路径
4、把图片路径传入自定义view(自定义view实现的功能:画圆角边框,动画缩小至消失)
主要用到的是ObjectAnimator属性动画的缩小和平移

核心代码

得到图片的路径

private String  getFilePath() {
        Bitmap bitmap = createViewBitmap(picImg);
        if (bitmap != null) {
            try {
                // 首先保存图片
                String storePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "HIS";
                File appDir = new File(storePath);
                if (!appDir.exists()) {
                    appDir.mkdir();
                }
                String fileName = System.currentTimeMillis() + ".jpg";
                File file = new File(appDir, fileName);

                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
                bitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos);
                bos.flush();
                bos.close();
                Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                Uri uri = Uri.fromFile(file);
                intent.setData(uri);
                sendBroadcast(intent);
                return file.getAbsolutePath();
            } catch (Exception e) {
                return null;
            }
        } else {
            return null;
        }

    }
public Bitmap createViewBitmap(View v) {
        Bitmap bitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        v.draw(canvas);
        return bitmap;
    }

把图片路径传入自定义view

 String filePath = getFilePath();
        mDisplayScreenshotSnv.setVisibility(View.GONE);
        mDisplayScreenshotSnv.setPath(filePath, picImg.getMeasuredWidth(), picImg.getMeasuredHeight(), true);
        mDisplayScreenshotSnv.setVisibility(View.VISIBLE);

截图实现圆角边框和动画消失

//实现截图动画(添加圆角边框)
                Glide.with(getContext())
                        .load(new File(path))
                        .transform(new CenterCrop(getContext()), new GlideRoundTransform(getContext(), radius))
                        .crossFade()
                        .listener(new RequestListener<File, GlideDrawable>() {
                            @Override
                            public boolean onException(Exception e, File model, Target<GlideDrawable> target, boolean isFirstResource) {
                                if (anim) {
                                    anim(thumb, true);
                                }
                                return false;
                            }

                            @Override
                            public boolean onResourceReady(GlideDrawable resource, File model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                                if (thumb.getDrawable() == null) {
                                    // 避免截图成功时出现短暂的全屏白色背景
                                    thumb.setImageDrawable(resource);
                                }
                                if (anim) {
                                    anim(thumb, true);
                                }
                                return false;
                            }
                        }).into(thumb);

                //启动延时关闭截图(显示5秒消失截图)
                startTick(true);

动画设置

/**
     * 动画设置
     * @param view
     * @param start
     */
    private void anim(final ImageView view, boolean start) {
        if (!start) {
            if (getChildCount() > 0) {
                // 快速点击截图时,上一次添加的子视图尚未移除,需重置视图
                resetView();
            }
            setScaleX(1f);
            setScaleY(1f);
            setTranslationX(0f);
            setTranslationY(0f);
            clearAnimation();
            if (mScaleXAnim != null) {
                mScaleXAnim.cancel();
                mScaleXAnim = null;
            }
            if (mScaleYAnim != null) {
                mScaleYAnim.cancel();
                mScaleYAnim = null;
            }
            if (mTranslationXAnim != null) {
                mTranslationXAnim.cancel();
                mTranslationXAnim = null;
            }
            if (mTranslationYAnim != null) {
                mTranslationYAnim.cancel();
                mTranslationYAnim = null;
            }
            return;
        }

        view.post(new Runnable() {
            @Override
            public void run() {
                if (!view.isAttachedToWindow()) {
                    // 子视图已被移除
                    return;
                }
                setCardBackgroundColor(Color.WHITE);

                //等待cross fade动画
                float margins = DisplayUtil.dip2px(getContext(), 10);
                float scaleToX = (float) mFinalW / getMeasuredWidth();
                float scaleToY = (float) mFinalH / getMeasuredHeight();
                float translateToX = -(getMeasuredWidth() / 2f - (mFinalW / 2 + margins));
                float translateToY = getMeasuredHeight() / 2f - (mFinalH / 2f + margins);

                //以当前view为中心,x轴右为正,左为负;y轴下为正,上为负

                mScaleXAnim = ObjectAnimator.ofFloat(ScreenshotNotifyView.this, "scaleX", 1.0f, scaleToX);
                mScaleYAnim = ObjectAnimator.ofFloat(ScreenshotNotifyView.this, "scaleY", 1.0f, scaleToY);

                mTranslationXAnim = ObjectAnimator.ofFloat(ScreenshotNotifyView.this, "translationX", 1.0f, translateToX);
                mTranslationYAnim = ObjectAnimator.ofFloat(ScreenshotNotifyView.this, "translationY", 1.0f, translateToY);

                //设置速度
                mScaleXAnim.setDuration(500);
                mScaleYAnim.setDuration(500);
                mTranslationXAnim.setDuration(500);
                mTranslationYAnim.setDuration(500);

                //缩放
                mScaleXAnim.start();
                mScaleYAnim.start();
                //平移
                mTranslationXAnim.start();
                mTranslationYAnim.start();
                setEnabled(false);
                mScaleXAnim.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationCancel(Animator animation) {
                        super.onAnimationCancel(animation);
                        setEnabled(true);
                    }

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        setEnabled(true);
                        setClickable(true);
                    }

                    @Override
                    public void onAnimationStart(Animator animation) {
                        super.onAnimationStart(animation);
                    }
                });

            }
        });
    }

完整代码

ScreenshotNotifyView.java

package com.lyw.myproject.widget;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Color;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.lyw.myproject.screenshot.GlideRoundTransform;
import com.lyw.myproject.utils.DisplayUtil;
import java.io.File;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.cardview.widget.CardView;

public class ScreenshotNotifyView extends CardView {
    private int mFinalW;
    private int mFinalH;

    private Handler mHandler;

    private ObjectAnimator mScaleXAnim = null;
    private ObjectAnimator mScaleYAnim = null;

    private ObjectAnimator mTranslationXAnim = null;
    private ObjectAnimator mTranslationYAnim = null;

    public ScreenshotNotifyView(@NonNull Context context) {
        super(context);
        init(context);
    }

    public ScreenshotNotifyView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public ScreenshotNotifyView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    @Override
    public void setVisibility(int visibility) {
        super.setVisibility(visibility);
        if (visibility == GONE) {
            resetView();
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        anim(null, false);
        startTick(false);
    }

    private void init(Context context) {
        mHandler = new Handler(Looper.getMainLooper());
        setCardElevation(0);
    }

    public void setPath(final String path, int w, int h, final boolean anim) {
        setClickable(false);
        anim(null, false);
        final ImageView thumb = new ImageView(getContext());
        FrameLayout.LayoutParams thumbParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getLayoutParams();
        int padding = (int) DisplayUtil.dip2px(getContext(), 2);
        int margins = (int) DisplayUtil.dip2px(getContext(), 8);

        //设置截图之后的宽度,高度按照比例设置
        mFinalW = (int) DisplayUtil.dip2px(getContext(), 90);
        mFinalH = (int) ((float) mFinalW * h) / w;
        if (!anim) {
            //设置边框
            params.setMargins(margins, margins, margins, margins);
            margins = (int) DisplayUtil.dip2px(getContext(), 2);
            params.width = mFinalW + margins * 2;
            params.height = mFinalH + margins * 2;
            params.gravity = Gravity.START | Gravity.BOTTOM;

            thumbParams.width = mFinalW;
            thumbParams.height = mFinalH;
            thumbParams.gravity = Gravity.CENTER;
            setLayoutParams(params);
            requestLayout();
        } else {
            //设置边框
            thumbParams.setMargins(margins, margins, margins, margins);
            params.setMargins(0, 0, 0, 0);
            params.width = FrameLayout.LayoutParams.MATCH_PARENT;
            params.height = FrameLayout.LayoutParams.MATCH_PARENT;
            setLayoutParams(params);
            requestLayout();
        }
        thumb.setScaleType(ImageView.ScaleType.FIT_XY);
        thumb.setLayoutParams(thumbParams);
        addView(thumb);
        post(new Runnable() {
            @Override
            public void run() {
                float scale = (float) mFinalW / getMeasuredWidth();
                int radius = 5;
                if (anim) {
                    radius = (int) (5f / scale);
                }
                setRadius((int) DisplayUtil.dip2px(getContext(), radius));

                //显示截图(添加圆角)
                Glide.with(getContext())
                        .load(new File(path))
                        .transform(new CenterCrop(getContext()), new GlideRoundTransform(getContext(), radius))
                        .crossFade()
                        .listener(new RequestListener<File, GlideDrawable>() {
                            @Override
                            public boolean onException(Exception e, File model, Target<GlideDrawable> target, boolean isFirstResource) {
                                if (anim) {
                                    anim(thumb, true);
                                }
                                return false;
                            }

                            @Override
                            public boolean onResourceReady(GlideDrawable resource, File model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                                if (thumb.getDrawable() == null) {
                                    // 避免截图成功时出现短暂的全屏白色背景
                                    thumb.setImageDrawable(resource);
                                }
                                if (anim) {
                                    anim(thumb, true);
                                }
                                return false;
                            }
                        }).into(thumb);

                //启动延时关闭截图(显示5秒消失截图)
                startTick(true);
            }
        });
    }

    /**
     * 动画设置
     * @param view
     * @param start
     */
    private void anim(final ImageView view, boolean start) {
        if (!start) {
            if (getChildCount() > 0) {
                // 快速点击截图时,上一次添加的子视图尚未移除,需重置视图
                resetView();
            }
            setScaleX(1f);
            setScaleY(1f);
            setTranslationX(0f);
            setTranslationY(0f);
            clearAnimation();
            if (mScaleXAnim != null) {
                mScaleXAnim.cancel();
                mScaleXAnim = null;
            }
            if (mScaleYAnim != null) {
                mScaleYAnim.cancel();
                mScaleYAnim = null;
            }
            if (mTranslationXAnim != null) {
                mTranslationXAnim.cancel();
                mTranslationXAnim = null;
            }
            if (mTranslationYAnim != null) {
                mTranslationYAnim.cancel();
                mTranslationYAnim = null;
            }
            return;
        }

        view.post(new Runnable() {
            @Override
            public void run() {
                if (!view.isAttachedToWindow()) {
                    // 子视图已被移除
                    return;
                }
                setCardBackgroundColor(Color.WHITE);

                //等待cross fade动画
                float margins = DisplayUtil.dip2px(getContext(), 10);
                float scaleToX = (float) mFinalW / getMeasuredWidth();
                float scaleToY = (float) mFinalH / getMeasuredHeight();
                float translateToX = -(getMeasuredWidth() / 2f - (mFinalW / 2 + margins));
                float translateToY = getMeasuredHeight() / 2f - (mFinalH / 2f + margins);

                //以当前view为中心,x轴右为正,左为负;y轴下为正,上为负

                mScaleXAnim = ObjectAnimator.ofFloat(ScreenshotNotifyView.this, "scaleX", 1.0f, scaleToX);
                mScaleYAnim = ObjectAnimator.ofFloat(ScreenshotNotifyView.this, "scaleY", 1.0f, scaleToY);

                mTranslationXAnim = ObjectAnimator.ofFloat(ScreenshotNotifyView.this, "translationX", 1.0f, translateToX);
                mTranslationYAnim = ObjectAnimator.ofFloat(ScreenshotNotifyView.this, "translationY", 1.0f, translateToY);

                //设置速度
                mScaleXAnim.setDuration(500);
                mScaleYAnim.setDuration(500);
                mTranslationXAnim.setDuration(500);
                mTranslationYAnim.setDuration(500);

                //缩放
                mScaleXAnim.start();
                mScaleYAnim.start();
                //平移
                mTranslationXAnim.start();
                mTranslationYAnim.start();
                setEnabled(false);
                mScaleXAnim.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationCancel(Animator animation) {
                        super.onAnimationCancel(animation);
                        setEnabled(true);
                    }

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        setEnabled(true);
                        setClickable(true);
                    }

                    @Override
                    public void onAnimationStart(Animator animation) {
                        super.onAnimationStart(animation);
                    }
                });

            }
        });
    }

    private void resetView() {
        setCardBackgroundColor(Color.TRANSPARENT);
        removeAllViews();
        startTick(false);
    }

    private void startTick(boolean start) {
        if (!start) {
            mHandler.removeCallbacksAndMessages(null);
            return;
        }
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                setVisibility(GONE);
            }
        }, 5 * 1000);
    }
}


GlideRoundTransform.java

package com.lyw.myproject.screenshot;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;

import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;

/**
 * Created on 2018/12/26.
 *
 * @author lyw
 **/
public class GlideRoundTransform extends BitmapTransformation {

    private static float radius = 0f;

    /**
     * 构造函数 默认圆角半径 4dp
     *
     * @param context Context
     */
    public GlideRoundTransform(Context context) {
        this(context, 4);
    }

    /**
     * 构造函数
     *
     * @param context Context
     * @param dp 圆角半径
     */
    public GlideRoundTransform(Context context, int dp) {
        super(context);
        radius = Resources.getSystem().getDisplayMetrics().density * dp;
    }

    @Override
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        return roundCrop(pool, toTransform);
    }

    private static Bitmap roundCrop(BitmapPool pool, Bitmap source) {
        if (source == null)  {
            return null;
        }

        Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
        if (result == null) {
            result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
        }

        Canvas canvas = new Canvas(result);
        Paint paint = new Paint();
        paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
        paint.setAntiAlias(true);
        RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight());
        canvas.drawRoundRect(rectF, radius, radius, paint);
        return result;
    }

    @Override
    public String getId() {
        return getClass().getName() + Math.round(radius);
    }
}

activity_screen_shot1.xml

<?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">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <ImageView
            android:id="@+id/pic_iv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scaleType="fitXY"
            android:src="@mipmap/picture" />

        <com.lyw.myproject.widget.ScreenshotNotifyView
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:id="@+id/display_screenshot_snv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="gone"
            app:cardBackgroundColor="@color/src_trans" />

    </FrameLayout>

    <Button
        android:id="@+id/screen_btn"
        android:text="截图"
        android:layout_gravity="center"
        android:layout_marginTop="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>

ScreenShotActivity1.java

package com.lyw.myproject.screenshot;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import com.lyw.myproject.BaseActivity;
import com.lyw.myproject.R;
import com.lyw.myproject.utils.LoadingLayout;
import com.lyw.myproject.utils.MemoryUtils;
import com.lyw.myproject.utils.PermissionUtil;
import com.lyw.myproject.widget.ScreenshotNotifyView;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;

import androidx.annotation.Nullable;

/**
 * 功能描述:截图
 */
public class ScreenShotActivity1 extends BaseActivity {
    private ImageView picImg;
    private Button screenBtn;
    private ScreenshotNotifyView mDisplayScreenshotSnv;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_screen_shot1);
        initView();
        initEvent();
    }
    private void initView() {
        picImg = (ImageView) findViewById(R.id.pic_iv);
        mDisplayScreenshotSnv = (ScreenshotNotifyView) findViewById(R.id.display_screenshot_snv);
        screenBtn = (Button) findViewById(R.id.screen_btn);
    }

    private void initEvent() {
        screenBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                handleScreenShot();
            }
        });
    }

    /**
     * 处理截屏的业务
     */
    private void handleScreenShot() {
        if (!PermissionUtil.isHasSDCardWritePermission(this)) {
            Toast.makeText(ScreenShotActivity1.this, "没有权限", Toast.LENGTH_SHORT).show();
            PermissionUtil.requestSDCardWrite(this);
            return;
        }
        if (!MemoryUtils.hasEnoughMemory(MemoryUtils.MIN_MEMORY)) {
            Toast.makeText(ScreenShotActivity1.this, "内存不足,截图失败", Toast.LENGTH_SHORT).show();
            return;
        }
        String filePath = getFilePath();
        mDisplayScreenshotSnv.setVisibility(View.GONE);
        mDisplayScreenshotSnv.setPath(filePath, picImg.getMeasuredWidth(), picImg.getMeasuredHeight(), true);
        mDisplayScreenshotSnv.setVisibility(View.VISIBLE);
    }

    private String  getFilePath() {
        Bitmap bitmap = createViewBitmap(picImg);
        if (bitmap != null) {
            try {
                // 首先保存图片
                String storePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "HIS";
                File appDir = new File(storePath);
                if (!appDir.exists()) {
                    appDir.mkdir();
                }
                String fileName = System.currentTimeMillis() + ".jpg";
                File file = new File(appDir, fileName);

                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
                bitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos);
                bos.flush();
                bos.close();

                Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                Uri uri = Uri.fromFile(file);
                intent.setData(uri);
                sendBroadcast(intent);
                return file.getAbsolutePath();
            } catch (Exception e) {
                return null;
            }
        } else {
            return null;
        }
    }

    public Bitmap createViewBitmap(View v) {
        Bitmap bitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        v.draw(canvas);
        return bitmap;
    }
}

PermissionUtil.java

package com.lyw.myproject.utils;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import androidx.core.app.ActivityCompat;

public class PermissionUtil {
    /**
     * 请求地理位置
     *
     * @param context
     */
    public static void requestLocationPermission(Context context) {
        if (Build.VERSION.SDK_INT >= 23) {
            if (!isHasLocationPermission(context)) {
                ActivityCompat.requestPermissions((Activity) context, PermissionManager.PERMISSION_LOCATION, PermissionManager.REQUEST_LOCATION);
            }
        }
    }

    /**
     * 判断是否有地理位置
     *
     * @param context
     * @return
     */
    public static boolean isHasLocationPermission(Context context) {
        return ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
    }

    /**
     * 判断是否有文件读写的权限
     *
     * @param context
     * @return
     */
    public static boolean isHasSDCardWritePermission(Context context) {
        return ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
    }

    /**
     * 文件权限读写
     *
     * @param context
     */

    public static void requestSDCardWrite(Context context) {
        if (Build.VERSION.SDK_INT >= 23) {
            if (!isHasSDCardWritePermission(context)) {
                ActivityCompat.requestPermissions((Activity) context, PermissionManager.PERMISSION_SD_WRITE, PermissionManager.REQUEST_SD_WRITE);
            }
        }
    }
}

MemoryUtils.java

package com.lyw.myproject.utils;
import android.util.Log;
public class MemoryUtils {
    public static final int MIN_MEMORY = 50 * 1024 * 1024;
    /**
     * 判断有没足够内存截图
     *
     * @param size
     * @return
     */
    public static boolean hasEnoughMemory(int size) {
        //最大内存
        long maxMemory = Runtime.getRuntime().maxMemory();
        //分配的可用内存
        long freeMemory = Runtime.getRuntime().freeMemory();
        //已用内存
        long usedMemory = Runtime.getRuntime().totalMemory() - freeMemory;
        //剩下可使用的内存
        long canUseMemory = maxMemory - usedMemory;
        Log.d("Memory", "hasEnoughMemory: " +
            "maxMemory = " + maxMemory +
            ", freeMemory = " + freeMemory +
            ", usedMemory = " + usedMemory +
            ", canUseMemory = " + canUseMemory);
        if (canUseMemory >= size) {
            return true;
        }
        return false;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_28002747/article/details/106906837