android实现截图并动画消失效果的思路详解

时间:2021-05-20



整体思路

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

总结

到此这篇关于android实现截图并动画消失的文章就介绍到这了,更多相关android实现截图并动画消失内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章