Android 사용자 정의 Drawable 이 Drawable 중부 에 투명 영역 을 지정 하 는 방법 예시

머리말
드 라 와 블 이 뭐 예요?
  • Canvas 에서 그 릴 수 있 는 추상 적 인 개념
  • 4.567917.색상,이미지 등 은 모두 하나의 Drawable 일 수 있 습 니 다.4.567918.
  • Drawable 은 XML 로 정의 하거나 코드 를 통 해 만 들 수 있 습 니 다
  • Android 에서 Drawable 은 추상 적 인 유형 으로 모든 구체 적 인 Drawable 은 그의 하위 유형 이다
  • Drawable 의 장점
  • 사용 이 간단 하고 사용자 정의 View 보다 원가 가 낮 습 니 다
  • 그림 류 가 아 닌 Drawable 이 차지 하 는 공간 이 작 아서 apk 크기 를 줄 일 수 있 습 니 다
  • 실제 개발 공정에 서 는 중간 이 비어 있 는 Drawable,즉 중간 이 투명 하고 다른 영역 이 정상적으로 표시 되 는 Drawable 이 있다 고 생각 하지 않 을 수 없다.
  • 주로 사용 하 는 기술 은 Porter Duff Xfermode 의 Porter Duff.Mode.XOR 모델 이다
  • 핵심 사상 은 먼저 전체 drawable 을 정상적으로 그린 다음 에 지 정 된 구역 을 투명 색 으로 혼합 하 는 것 이다
  • 메 인 코드 보 세 요.
    
    public void draw(@NonNull Canvas canvas) {
     //            ,             ,       ,                   
     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);
    }
    위의 코드 에서 어떤 사람들 은 하드웨어 를 닫 고 속 도 를 내야 한다 고 생각 할 수도 있다.즉,
    
    setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    그러나 실제 작업 에 서 는 canvas 를 잠 그 는 방식 으로 하드웨어 가속 동기 화로 인 한 비정상적인 디 스 플레이 를 효과적으로 피 할 수 있 으 며,잠 겨 있 는 canvas 는 캐 시 에서 정상 적 인 계산 을 할 수 있 으 며,잠 금 을 풀 고 렌 더 링 을 할 수 있 으 므 로 하드웨어 가속 기능 을 닫 지 마 십시오.
    효과 보이 기

    위의 레이아웃 파일 은?
    
    <FrameLayout
     android:layout_width="match_parent"
     android:layout_height="match_parent">
    
     <ImageView
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:background="@drawable/crop_image_bg" />
    
     <com.jian.cropimage.CoverView
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:background="@color/crop_image_cover_view_bg">
    
      <!--      View     ,          ,          -->
      <ImageView
       android:id="@+id/crop_image_cover_view_hole"
       android:layout_width="250dp"
       android:layout_height="250dp"
       android:layout_gravity="center" />
    
     </com.jian.cropimage.CoverView>
    </FrameLayout>
    전체 HoleDrawable 코드
    
    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.support.annotation.NonNull;
    import android.support.annotation.Nullable;
    
    /**
     *   :           drawable <br/>
     *   {@link #setSrcPath(Path)}          <br/>
     *   :  
     *   :2017/9/4.
     */
    
    public class HoleDrawable extends Drawable {
     private Paint srcPaint;
     private Path srcPath = new Path();
    
     private Drawable innerDrawable;
    
    
     public HoleDrawable(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();
     }
    }
    Hole Drawable 만 있 으 면 의미 가 없습니다.사용자 정의 View 를 써 서 방금 전의 그림 의 효 과 를 실현 합 니 다.
    
    import android.content.Context;
    import android.graphics.Path;
    import android.graphics.drawable.HoleDrawable;
    import android.support.annotation.NonNull;
    import android.support.annotation.Nullable;
    import android.util.AttributeSet;
    import android.view.View;
    import android.widget.FrameLayout;
    
    /**
     *        layout,    background          <br/>
     *    ,        ,                 ,          <br/>
     *    crop_image_cover_view_hole View   ,       <br/>
     *   :  
     *   :2017/9/4.
     */
    public class HoleBackgroundLayout extends FrameLayout {
    
     private HoleDrawable background;
    
     public HoleBackgroundLayout(@NonNull Context context) {
      super(context);
      initView(context, null, 0);
     }
    
     public HoleBackgroundLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
      super(context, attrs);
      initView(context, attrs, 0);
     }
    
     public HoleBackgroundLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
      super(context, attrs, defStyleAttr);
      initView(context, attrs, defStyleAttr);
     }
    
     private void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
      background = new HoleDrawable(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();
     }
    
     private void resetBackgroundHoleArea() {
      Path path = null;
      //  crop_image_cover_view_hole View              
      View v0 = findViewById(R.id.crop_image_cover_view_hole);
      if (v0 != null) {
       path = new Path();
       //       
       path.addRect(v0.getLeft(), v0.getTop(), v0.getRight(), v0.getBottom(), Path.Direction.CW);
      }
      if (path != null) {
       background.setSrcPath(path);
      }
     }
    }
    총결산
    이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

    좋은 웹페이지 즐겨찾기