안 드 로 이 드 캡 처 및 애니메이션 사라 짐 효과 에 대한 자세 한 설명

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
전체적인 사고 방식.
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;
 }
}
총결산
안 드 로 이 드 가 캡 처 를 실현 하고 애니메이션 이 사라 진 것 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 안 드 로 이 드 가 캡 처 를 실현 하고 애니메이션 이 사라 진 내용 은 예전 의 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 저 희 를 많이 사랑 해 주세요!

좋은 웹페이지 즐겨찾기