Android 에서 BitmapShader 를 이용 하여 테 두 리 를 가 진 동 그 란 두상 을 만 듭 니 다.

효 과 는 다음 과 같 습 니 다:

BitmapShader 의 간단 한 소개Shader이 무엇 인지,Shader의 종류 가 몇 가지 가 있 는 지,그리고 어떻게 사용 하 는 지 에 대해 본 고의 범주 에 속 하지 않 는 지 에 대해 잘 모 르 는 학생 들 은 먼저Shader 의 기본 적 인 사용 을 배 워 보 는 것 을 권장 합 니 다.BitmapShader주요 한 역할 은 Paint 대상 을 통 해 캔버스 를 지정 한Bitmap채 워 일련의 효 과 를 실현 하 는 것 이다.다음 과 같은 세 가지 모델 로 선택 할 수 있다.
      1.CLAMP -스 트 레 칭,여기 스 트 레 칭 은 그림 의 마지막 요소 로 끊임없이 반복 된다.이 효 과 는 그림 이 비교적 작고 그 릴 면적 이 비교적 클 때 뚜렷 하 다.
      2.REPEAT -반복,가로 세로 로 계속 반복 되 며 이전 모델 과 다 릅 니 다.이런 모델 은 그림 이 비교적 작 아서 요 구 를 만족 시 키 지 못 합 니 다.가로 세로 로 계속 반복 해서 도형 을 그립 니 다.
      3.MIRROR -뒤 집기,이런 모델 은REPEAT 과 유사 하 다.다만 이곳 의 중복 은 뒤 집기 반복 이 고 종이 접 기와 효과 가 많 지 않다.
그리고 우리 가 사용 하고 자 하 는 것 은CLAMP 모델 이다.왜냐하면 우리 가 도형 의 크기 를 제어 하면 이미지 의 스 트 레 칭 을 피 할 수 있 기 때문이다.
구체 적 실현 소개
그림,테두리 너비,색상 을 정의 하기 위해 서,먼저 res/values 디 렉 터 리 에 attrs.xml 파일 을 새로 만 듭 니 다.그 안에 쓸 내용 은 다음 과 같 습 니 다.

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <declare-styleable name="MyCustomView">
  <attr name="mborder_color" format="color"></attr>
  <attr name="mborder_width" format="dimension"></attr>
  <attr name="msrc" format="reference"></attr>
 </declare-styleable>
</resources>
물론 여기에 다른 특성 도 추가 할 수 있다.우리 가 사용 하고 자 하 는 특성 을 정의 한 이상 사용자 정의View에서 이러한 속성 을 분석 하고 이용 해 야 합 니 다.분석 과정 은 다음 과 같 습 니 다.

 TypedArray type = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView);
 mBorderColor = type.getColor(R.styleable.MyCustomView_mborder_color,0);
 mDrawable = type.getDrawable(R.styleable.MyCustomView_msrc);

 //     Drawable     Bitmap
 BitmapDrawable bitmapDrawable = (BitmapDrawable) mDrawable;
 mBitmap = bitmapDrawable.getBitmap();

 mBorderWidth = type.getDimensionPixelSize(R.styleable.MyCustomView_mborder_width, 2);
주의해 야 할 것 은mSrc 속성의 해석 이다.Drawable 대상 을 얻 었 기 때문에 우 리 는 이 를Bitmap 대상 으로 전환 해 야 한다.
다음은 우리 가 얻 은Bitmap 대상 을 이용 하여 원형 두상 을 그립 니 다.BitmapShader Paint 의 초기 화 는 다음 과 같 습 니 다.

  mSrcBitmap = Bitmap.createScaledBitmap(mBitmap, mWidth, mHeight, false);
  mShader = new BitmapShader(mSrcBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
  mPaint = new Paint();
  mPaint.setShader(mShader);
  mRadius = (mWidth - mBorderWidth * 2 - 4) / 2;
  mCircleX = (mWidth) / 2;
  mCircleY = (mHeight) / 2;
mSrcBitmap 는 얻 은 이미 지 를 적당 하 게 축소 하거나 확대 하여 우리 가 도형 에 대한 요구 에 적응 하 는 것 입 니 다.여기mWidth mHeight 는 무엇 입 니까?실제 적 으로 우 리 는 보기 가 layout_width layout_height에서 전 달 된 값 을 정의 했다.그러나 여기 서 나 는 그들 에 게 처 리 를 했다.즉,최소 값 조작 을 선택 하면 너비 가 높 거나 높이 가 넓 어서 이미지 가 지정 한 구역 을 채 우지 못 하 는 현상 을 피 할 수 있다.주의해 야 할 것 은 사용자 정의 보 기 는wrap_content 를 특수 처리 해 야 하 며,그렇지 않 으 면 시스템 이 이 속성의 보 기 를 표시 하지 않 습 니 다.어떻게 처리 하 는 지 에 대해 서 는 본 사례 의 소스 코드 를 볼 수 있 고 간단 하 며 많은 사람들 이 한눈 에 알 거나 이미 알 고 있 을 것 이 라 고 믿 습 니 다.
또 강조해 야 할 것 은 여기mRadius ,즉 그 릴 원 의 반지름 인 데 왜 테두리 의 너비 곱 하기 2 를 빼 야 합 니까?우리 의 원 은 보기 가 지정 한 너비 나 높이 에 따라 그 려 진 것 임 을 알 아야 합 니 다.만약 우리 가 그린 원 이 지정 한 보기 의 내 접 원 이 라면 테 두 리 는 어디 에 두 어야 합 니까?그것 은 분명히 보기 의 바깥쪽 에 그 려 져 있 을 것 이다.그러면 우 리 는 완전한 테 두 리 를 볼 수 없 을 것 이다.그래서 이렇게 빼 는 의 미 는 테 두 리 를 위해 공간 을 비 우 는 것 이다.
이상 의 조작 을 통 해 우 리 는 이미 원형 두상 을 그 렸 다.아래 에 테 두 리 를 그 렸 다.사실은 매우 간단 하 다.나 는 단지 또 하나의 정 의 를 내 렸 을 뿐이다.  Paint 대상 을 이용 하여 원 을 그 렸 을 뿐 이 고 붓 의 초기 화 작업 은 다음 과 같다.

  mBorderPaint = new Paint();
  mBorderPaint.setStyle(Paint.Style.STROKE);
  mBorderPaint.setStrokeWidth(mBorderWidth);
  mBorderPaint.setColor(mBorderColor);
  mBorderPaint.setStrokeCap(Paint.Cap.ROUND);
자,다음은onDraw()함수 에서 그 릴 수 있 습 니 다.다음 과 같 습 니 다.

 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  canvas.drawCircle(mCircleX, mCircleY, mRadius, mPaint);
  canvas.drawCircle(mCircleX, mCircleY, mRadius, mBorderPaint);
 }
이렇게 하면 전체 효 과 는 이 루어 진 셈 이다.다음은 어떻게 사용 하 는 지 보 겠 습 니 다.

 <com.example.hwaphon.patheffecttest.MyView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_marginBottom="16dp"
   android:layout_marginRight="8dp"
   app:mborder_color="@android:color/holo_green_light"
   app:mborder_width="4dp"
   app:msrc="@drawable/myview_test"/>
주의 하 세 요.반드시 용기 에 이 한 마디 를 더 해 야 합 니 다.

xmlns:app=http://schemas.android.com/apk/res-auto
구체 적 으로 실 현 된 핵심 코드

package com.example.hwaphon.patheffecttest;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by Hwaphon on 2016/5/12.
 */
public class MyView extends View {

 private Bitmap mBitmap;
 private Drawable mDrawable;
 private Bitmap mSrcBitmap;

 private BitmapShader mShader;
 private Paint mPaint;

 private int mWidth, mHeight;

 private int mRadius;
 private int mCircleX, mCircleY;

 private int mBorderColor;
 private Paint mBorderPaint;
 private int mBorderWidth;

 public MyView(Context context) {
  this(context, null);
 }

 public MyView(Context context, AttributeSet attrs) {
  super(context, attrs);
  TypedArray type = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView);
  mBorderColor = type.getColor(R.styleable.MyCustomView_mborder_color,0);
  mDrawable = type.getDrawable(R.styleable.MyCustomView_msrc);

  //     Drawable     Bitmap
  BitmapDrawable bitmapDrawable = (BitmapDrawable) mDrawable;
  mBitmap = bitmapDrawable.getBitmap();

  mBorderWidth = type.getDimensionPixelSize(R.styleable.MyCustomView_mborder_width, 2);
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  mWidth = measureWidth(widthMeasureSpec);
  mHeight = measureHeight(heightMeasureSpec);
  int temp = mWidth > mHeight ? mHeight : mWidth;
  mWidth = mHeight = temp;
  initView();
  setMeasuredDimension(mWidth, mHeight);
 }

 private int measureHeight(int heightMeasureSpec) {
  int size = MeasureSpec.getSize(heightMeasureSpec);
  int sizeMode = MeasureSpec.getMode(heightMeasureSpec);
  int result = 0;
  if (sizeMode == MeasureSpec.EXACTLY) {
   result = size;
  } else {
   result = 200;
   if (sizeMode == MeasureSpec.AT_MOST) {
    result = Math.min(result, size);
   }
  }
  return result;
 }

 private int measureWidth(int widthMeasureSpec) {
  int size = MeasureSpec.getSize(widthMeasureSpec);
  int sizeMode = MeasureSpec.getMode(widthMeasureSpec);
  int result = 0;
  if (sizeMode == MeasureSpec.EXACTLY) {
   result = size;
  } else {
   result = 200;
   if (sizeMode == MeasureSpec.AT_MOST) {
    result = Math.min(result, size);
   }
  }
  return result;
 }

 private void initView() {

  mSrcBitmap = Bitmap.createScaledBitmap(mBitmap, mWidth, mHeight, false);
  mShader = new BitmapShader(mSrcBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
  mPaint = new Paint();
  mPaint.setShader(mShader);
  mRadius = (mWidth - mBorderWidth * 2) / 2;
  mCircleX = (mWidth) / 2;
  mCircleY = (mHeight) / 2;

  mBorderPaint = new Paint();
  mBorderPaint.setStyle(Paint.Style.STROKE);
  mBorderPaint.setStrokeWidth(mBorderWidth);
  mBorderPaint.setColor(mBorderColor);
  mBorderPaint.setStrokeJoin(Paint.Join.ROUND);
  mBorderPaint.setStrokeCap(Paint.Cap.ROUND);
 }

 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  canvas.drawCircle(mCircleX, mCircleY, mRadius, mPaint);
  canvas.drawCircle(mCircleX, mCircleY, mRadius, mBorderPaint);
 }
}
총결산
이상 은 안 드 로 이 드 가 비트 맵 셰 이 더 를 이용 해 자체 테두리 원형 얼굴 을 만 드 는 모든 콘 텐 츠 입 니 다.이 글 이 안 드 로 이 드 를 개발 할 때 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 면 댓 글로 주 고 받 으 세 요.

좋은 웹페이지 즐겨찾기