Android 는 지 정 된 영역 투명 영역 을 그립 니 다.

개술
스 캔 기능 을 실현 할 때,우 리 는 중간 이 투명 한 스 캔 상 자 를 그 려 야 하고,나머지 부분 은 반투명 이다.일반적인 상황 에서 예 를 들 어 위 챗 이나 알 리 페 이의 스 캔 상 자 는 모두 사각형 입 니 다.만약 에 중간 에 스 캔 상자 가 사각형 이 라면 구 조 는 매우 간단 합 니 다.그러나 스 캔 상자 가 원 각 사각형 이나 원형 등 상황 이 라면 어떻게 합 니까?이 글 은 주로 중간 투명 띠 원 각 의 사각형 을 그 리 는 것 을 기록 하고 있다.
관례 에 따라 우 리 는 먼저 효과 도 를 살 펴 보 자.

2.절차 에 따라 코드 를 살 펴 보 겠 습 니 다.
1.Custom Drawable,중간 에 투명 영역 이 나타 나 는 drawable 지원

package per.juan.scandome;

import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

/**
 *            drawable
 *   {@link #setSrcPath(Path)}         
 * Created by juan on 2018/07/20.
 */
public class CustomDrawable extends Drawable {
 private Paint srcPaint;
 private Path srcPath = new Path();

 private Drawable innerDrawable;


 public CustomDrawable(Drawable innerDrawable) {
  this.innerDrawable = innerDrawable;
  srcPath.addRect(100, 100, 200, 200, Path.Direction.CW);
  srcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  srcPaint.setColor(0xffffffff);
 }

 /**
  *          
  *
  * @param srcPath
  */
 public void setSrcPath(Path srcPath) {
  this.srcPath = srcPath;
 }

 @Override
 public void draw(@NonNull Canvas canvas) {
  innerDrawable.setBounds(getBounds());
  if (srcPath == null || srcPath.isEmpty()) {
   innerDrawable.draw(canvas);
  } else {
   //            ,             ,       ,                   
   int saveCount = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), srcPaint, Canvas.ALL_SAVE_FLAG);

   //dst      
   innerDrawable.draw(canvas);

   //      
   srcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
   //src     
   canvas.drawPath(srcPath, srcPaint);
   //      
   srcPaint.setXfermode(null);
   //    
   canvas.restoreToCount(saveCount);
  }
 }

 @Override
 public void setAlpha(int alpha) {
  innerDrawable.setAlpha(alpha);
 }

 @Override
 public void setColorFilter(@Nullable ColorFilter colorFilter) {
  innerDrawable.setColorFilter(colorFilter);
 }

 @Override
 public int getOpacity() {
  return innerDrawable.getOpacity();
 }
}
(1)주로 사용 하 는 기술 은 Porter Duff Xfermode 의PorterDuff.Mode.XOR모델 이다.
(2)핵심 사상 은 먼저 drawable 전 체 를 정상적으로 그 려 낸 다음 에 지정 한 구역 을 투명 색 으로 혼합 하 는 것 이다.
2、CustomLayout

package per.juan.scandome;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Path;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;

/**
 *   layout  View   ,        
 * Created by juan on 2018/07/20.
 */
public class CustomLayout extends FrameLayout {

 private Context mContext;
 private CustomDrawable background;

 public CustomLayout(@NonNull Context context) {
  super(context);
  initView(context, null, 0);
 }

 public CustomLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
  super(context, attrs);
  this.mContext=context;
  initView(context, attrs, 0);
 }

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

 @SuppressLint("NewApi")
 private void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
  background = new CustomDrawable(getBackground());
  setBackground(background);
 }

 @Override
 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
  super.onLayout(changed, left, top, right, bottom);
  resetBackgroundHoleArea();
 }

 @SuppressLint("NewApi")
 private void resetBackgroundHoleArea() {
  Path path = null;
  //   View              
  View view = findViewById(R.id.iv_scan);
  if (view != null) {
   path = new Path();
   //       
   path.addRoundRect(view.getLeft(), view.getTop(), view.getRight(), view.getBottom(), dp2Px(mContext,10), dp2Px(mContext,10),Path.Direction.CW);
  }
  if (path != null) {
   background.setSrcPath(path);
  }
 }

 public int dp2Px(Context context, float dp) {
  final float scale = context.getResources().getDisplayMetrics().density;
  return (int) (dp * scale + 0.5f);
 }
}
3.그리고 XML 레이아웃 에서 사용자 정의 View 를 설명 합 니 다.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:id="@+id/frame_layout"
 android:layout_height="match_parent">

 <ImageView
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="@mipmap/bg_image" />

 <per.juan.scandome.CustomLayout
  android:layout_width="match_parent"
  android:id="@+id/layout"
  android:background="#8c565658"
  android:layout_height="match_parent">

  <!--      View     ,           -->
  <FrameLayout
   android:id="@+id/iv_scan"
   android:layout_width="200dp"
   android     center" />

 </per.juan.scandome.CustomLayout>
</FrameLayout>
자,이 글 은 이렇게 되 었 습 니 다.부족 한 점 이 있 으 면 지 도 를 바 랍 니 다.감사합니다^ ^
부록:
사용자 정의 Drawable:Drawable 중부 에 투명 영역 지정
총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

좋은 웹페이지 즐겨찾기