android實現截圖並動畫消失效果的思路詳解
阿新 • • 發佈:2020-06-25
整體思路
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,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",scaleToY); mTranslationXAnim = ObjectAnimator.ofFloat(ScreenshotNotifyView.this,"translationX",translateToX); mTranslationYAnim = ObjectAnimator.ofFloat(ScreenshotNotifyView.this,"translationY",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 = (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); params.setMargins(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()),true); } return false; } }).into(thumb); //啟動延時關閉截圖(顯示5秒消失截圖) startTick(true); } }); } /** * 動畫設定 * @param view * @param start */ private void anim(final ImageView view,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(),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,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,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,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(),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實現截圖並動畫消失內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!