Android 사용자 정의 보기 그림 인증 코드 무 작위 생 성 그리 기

이 글 은 안 드 로 이 드 사용자 정의 View 의 랜 덤 으로 이미지 인증 코드 를 생 성 하 는 것 을 말한다.개발 과정 에서 우 리 는 랜 덤 으로 이미지 인증 코드 를 생 성 해 야 하지만 이것 은 그 다음 이다.주로 사용자 정의 View 의 개발 과정 과 주의해 야 할 부분 을 정리 하고 자 한다.
관례 에 따라 먼저 효과 도 를 보십시오.

1.사용자 정의 View 의 절 차 를 정리 합 니 다.
1.사용자 정의 View 의 속성
2.View 의 구조 방법 에서 사용자 정의 속성 을 얻 을 수 있 습 니 다.
3.onMesure 재 작성
4.다시 쓰기 onDraw
그 중에서 onMesure 방법 은 꼭 다시 쓰 지 는 않 지만 대부분 다시 써 야 합 니 다.
2.View 의 몇 가지 구조 함수
1、public CustomView(Context context)
->자바 코드 가 new 커 스 텀 뷰 인 스 턴 스 를 직접 사용 할 때 하나의 매개 변수 만 있 는 구조 함 수 를 호출 합 니 다.
2、public CustomView(Context context, AttributeSet attrs)
->기본 XML 레이아웃 파일 에서 만 들 때 두 개의 인자 가 있 는 구조 함 수 를 호출 합 니 다.AttributeSet 형식의 인 자 는 XML 레이아웃 파일 에서 사용자 정의 속성 을 AttributeSet 을 통 해 View 에 가 져 옵 니 다.
3、public CustomView(Context context, AttributeSet attrs, int defStyleAttr)
->구조 함수 에서 세 번 째 인 자 는 기본 Style 입 니 다.여기 서 기본 Style 은 현재 application 이나 Activity 에서 사용 하 는 Theme 의 기본 Style 을 말 하 며 명확 하 게 호출 될 때 만 호출 됩 니 다.
4、public CustomView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
―이 구조 함 수 는 API 21 에 추 가 된 것 이다
3.다음은 코드 를 살 펴 보 겠 습 니 다.
1.View 의 속성 을 사용자 정의 합 니 다.먼저 res/values/다음 에 attr.xml 를 만 들 고 우리 가 필요 로 하 는 속성 과 해당 속성 을 설명 하 는 수치 유형 을 정의 합 니 다.

<?xml version="1.0" encoding="utf-8"?>
<resources>

 <attr name="text" format="string" />
 <attr name="textColor" format="color" />
 <attr name="textSize" format="dimension" />
 <attr name="bgColor" format="color" />

 <declare-styleable name="CustomView">
 <attr name="text" />
 <attr name="textColor" />
 <attr name="textSize" />
 <attr name="bgColor" />
 </declare-styleable>

</resources>
글꼴,글꼴 색상,글꼴 크기 및 글꼴 의 배경 색상 4 개 속성 을 정의 합 니 다.format 는 이 속성의 값 을 추출 하 는 형식 입 니 다.format 의 값 을 추출 하 는 유형 은 모두 10 가지 입 니 다.string,color,demension,integer,enum,reference,float,boolean,fraction 과 flag 를 포함 합 니 다.
2.그리고 XML 레이아웃 에서 사용자 정의 View 를 설명 합 니 다.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:custom="http://schemas.android.com/apk/res-auto"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

 <com.per.customview01.view.CustomView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_centerInParent="true"
 android:padding="10dp"
 custom:bgColor="#FF27FF28"
 custom:text="J2RdWQG"
 custom:textColor="#ff0000"
 custom:textSize="36dp" />

</RelativeLayout>
반드시 xmlns:custom="을 도입 해 야 합 니 다.http://schemas.android.com/apk/res-auto"Android Studio 에서 res-atuo 네 임 스페이스 를 사용 할 수 있 습 니 다.사용자 정의 View 전체 이름 을 추가 하지 않 아 도 됩 니 다."
3.View 의 구조 방법 에서 사용자 정의 스타일 을 얻 을 수 있 습 니 다.

/**
 *   
 */
 private String mText;
 /**
 *      
 */
 private int mTextColor;
 /**
 *      
 */
 private int mTextSize;
 /**
 *        
 */
 private int mBgCplor;
 private Rect mBound;
 private Paint mPaint;

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

 public CustomView(Context context, AttributeSet attrs) {
 this(context, attrs, 0);
 }

 public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
 super(context, attrs, defStyleAttr);
 /**
  *                
  */
 TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomView, defStyleAttr, 0);
 for (int i = 0; i < a.getIndexCount(); i++) {
  int attr = a.getIndex(i);
  switch (attr) {
  case R.styleable.CustomView_text:
   mText = a.getString(attr);
   break;
  case R.styleable.CustomView_textColor:
   //            
   mTextColor = a.getColor(R.styleable.CustomView_textColor, Color.BLACK);
   break;
  case R.styleable.CustomView_bgColor:
   //              
   mBgCplor = a.getColor(R.styleable.CustomView_bgColor, Color.BLUE);
   break;
  case R.styleable.CustomView_textSize:
   //      16sp,TypeValue    sp   px
   mTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
   break;
  }
 }
 a.recycle();
 //           
 mPaint = new Paint();
 mPaint.setTextSize(mTextSize);

 mBound = new Rect();
 mPaint.getTextBounds(mText, 0, mText.length(), mBound);
 }
우 리 는 세 가지 구조 방법 을 다시 썼 다.위의 구조 방법 에서 기본 적 인 구조 파일 은 두 개의 매개 변수의 구조 방법 을 호출 하 는 것 이 라 고 말 했 기 때문에 모든 구조 방법 에 세 개의 매개 변수의 구조 방법 을 호출 한 다음 에 세 개의 매개 변수의 구조 방법 에서 자정 의 속성 을 얻 도록 하 는 것 을 기억 해 야 한다.
처음에 하나의 매개 변수의 구조 방법 과 두 개의 매개 변수의 구조 방법 은 다음 과 같다.

 public CustomView(Context context) {
 super(context);
 }

 public CustomView(Context context, AttributeSet attrs) {
 super(context, attrs);
 }
한 가지 주의해 야 할 것 은 슈퍼 가 this 로 바 꾼 다음 에 하나의 매개 변수의 구조 방법 으로 두 매개 변수의 구조 방법 을 인용 하 게 해 야 한 다 는 것 이다.두 매개 변수의 구조 방법 은 세 개의 매개 변수의 구조 방법 을 인용 하고 코드 는 다음 과 같다.

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

 public CustomView(Context context, AttributeSet attrs) {
 this(context, attrs, 0);
 }
 
4,다시 쓰기 onDraw,onMesure 방법

@Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 }

 @Override
 protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 mPaint.setColor(mBgCplor);
 canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);

 mPaint.setColor(mTextColor);
 canvas.drawText(mText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);
 }
View 의 그리 기 프로 세 스 는 ViewRoot 의 permTravarsals 방법 에서 시 작 된 것 으로 measure,layot 와 draw 세 가지 과정 을 거 쳐 야 최종 적 으로 하나의 View 를 그 릴 수 있 습 니 다.그 중에서:
 •측정―onMeasure():View 의 너비 와 높이 를 측정 하여 View 의 크기 를 결정 한다.
 •레이아웃-onLayout():View 가 부모 용기 View Group 에 있 는 위 치 를 확인 하 는 데 사용 합 니 다.
 •화면 에 View 를 그립 니 다.
이때 의 효과 도 를 살 펴 보 겠 습 니 다.

세심 한 친 구 는 위의 레이아웃 파일 에서 우 리 는 너비 와 높이 를 wrap 로 설정 한 것 을 발견 할 수 있 습 니 다.content 의,그러나 이 효과 도 는 아무리 봐 도 우리 가 원 하 는 것 이 아 닙 니 다.이것 은 시스템 이 우리 에 게 측정 해 준 높이 와 너비 가 기본적으로 MATCH 이기 때 문 입 니 다.PARNET,우리 가 명확 한 너비 와 높이 를 설정 할 때 시스템 이 측정 해 준 결 과 는 우리 가 설정 한 결과 입 니 다.이것 이 옳 습 니 다.그러나 명확 한 너비 와 높이 를 설정 하 는 것 외 에 우리 가 WRAP 로 설정 하 든CONTENT 아니면 MATCHPARENT,시스템 이 측정 해 준 결 과 는 MATCH 입 니 다.PARENT,그래서 우리 가 WRAP 를 설 치 했 을 때CONTENT 때,우 리 는 스스로 측정 을 해 야 한다.즉,우 리 는 onMesure 방법 을 다시 써 야 한다.
다음은 우리 가 onMeasure 코드 를 다시 쓰 는 것 이다.

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 int widthMode = MeasureSpec.getMode(widthMeasureSpec);
 int widthSize = MeasureSpec.getSize(widthMeasureSpec);
 int heighMode = MeasureSpec.getMode(heightMeasureSpec);
 int heighSize = MeasureSpec.getSize(heightMeasureSpec);
 setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthSize : getPaddingLeft() + getPaddingRight() + mBound.width(), heighMode == MeasureSpec.EXACTLY ? heighSize : getPaddingTop() + getPaddingBottom() + mBound.height());
 }
MeasureSpec 은 부모 레이아웃 이 하위 레이아웃 에 전달 하 는 레이아웃 요 구 를 봉 인 했 습 니 다.MeasureSpec 의 specMode 는 모두 세 가지 모델 이 있 습 니 다.
(1)EXACTLY(완전):보통 명확 한 값 이나 MATCH 를 설정 합 니 다.PARENT,부모 요 소 는 하위 요소 의 크기 를 결정 합 니 다.하위 요 소 는 주어진 범위 에 한정 되 어 그 자체 의 크기 를 무시 합 니 다.
(2)AT_MOST(많 을 때 까지):하위 요소 가 주어진 최대 치 에 달 하 는 것 을 나타 내 는데 보통 WARP 입 니 다.CONTENT;
효과 도 를 다시 봅 시다.

이제 이것 은 우리 가 원 하 는 결과 입 니 다.주제 로 돌아 갑 니 다.오늘 은 사용자 정의 View 의 무 작위 로 이미지 인증 코드 를 만 드 는 것 을 말 합 니 다.이 제 는 사용자 정의 View 부분 을 완 성 했 습 니 다.저 는 완전한 코드 를 붙 였 습 니 다.

package com.per.customview01.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;

import com.per.customview01.R;

import java.util.Random;

/**
 * @author: adan
 * @description:
 * @projectName: CustomView01
 * @date: 2016-06-12
 * @time: 10:26
 */
public class CustomView extends View {
 private static final char[] CHARS = {'0', '1', '2', '3', '4', '5', '6',
  '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
  'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
  'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
  'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
  'X', 'Y', 'Z'};
 /**
 *           
 */
 private Random mRandom = new Random();
 /**
 *         
 */
 private StringBuffer sb = new StringBuffer();
 /**
 *   
 */
 private String mText;
 /**
 *      
 */
 private int mTextColor;
 /**
 *      
 */
 private int mTextSize;
 /**
 *        
 */
 private int mBgCplor;
 private Rect mBound;
 private Paint mPaint;

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

 public CustomView(Context context, AttributeSet attrs) {
 this(context, attrs, 0);
 }

 public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
 super(context, attrs, defStyleAttr);
 /**
  *                
  */
 TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomView, defStyleAttr, 0);
 for (int i = 0; i < a.getIndexCount(); i++) {
  int attr = a.getIndex(i);
  switch (attr) {
  case R.styleable.CustomView_text:
   mText = a.getString(attr);
   break;
  case R.styleable.CustomView_textColor:
   //            
   mTextColor = a.getColor(R.styleable.CustomView_textColor, Color.BLACK);
   break;
  case R.styleable.CustomView_bgColor:
   //              
   mBgCplor = a.getColor(R.styleable.CustomView_bgColor, Color.BLUE);
   break;
  case R.styleable.CustomView_textSize:
   //      16sp,TypeValue    sp   px
   mTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
   break;
  }
 }
 a.recycle();
 //           
 mPaint = new Paint();
 mPaint.setTextSize(mTextSize);

 mBound = new Rect();
 mPaint.getTextBounds(mText, 0, mText.length(), mBound);

 this.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
  mText = createCode();
  mTextColor = randomColor();
  mBgCplor = randomColor();
  //View      draw  ,          
  postInvalidate();
  }
 });
 }

 /**
 *      
 */
 public String createCode() {
 sb.delete(0, sb.length()); //           
 for (int i = 0; i < 6; i++) {
  sb.append(CHARS[mRandom.nextInt(CHARS.length)]);
 }
 Log.e("     ", sb.toString());
 return sb.toString();
 }

 /**
 *     
 */
 private int randomColor() {
 sb.delete(0, sb.length()); //           
 String haxString;
 for (int i = 0; i < 3; i++) {
  haxString = Integer.toHexString(mRandom.nextInt(0xFF));
  if (haxString.length() == 1) {
  haxString = "0" + haxString;
  }
  sb.append(haxString);
 }
 Log.e("    ", "#" + sb.toString());
 return Color.parseColor("#" + sb.toString());
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 int widthMode = MeasureSpec.getMode(widthMeasureSpec);
 int widthSize = MeasureSpec.getSize(widthMeasureSpec);
 int heighMode = MeasureSpec.getMode(heightMeasureSpec);
 int heighSize = MeasureSpec.getSize(heightMeasureSpec);
 setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthSize : getPaddingLeft() + getPaddingRight() + mBound.width(), heighMode == MeasureSpec.EXACTLY ? heighSize : getPaddingTop() + getPaddingBottom() + mBound.height());
 }

 @Override
 protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 mPaint.setColor(mBgCplor);
 canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);

 mPaint.setColor(mTextColor);
 canvas.drawText(mText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);
 }
}
클릭 이벤트 가 추가 되 었 습 니 다.View 를 클릭 할 때마다 인증 코드 와 글꼴 색상,글꼴 배경 색 을 인쇄 하 라 고 했 습 니 다.다음 과 같 습 니 다.

이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기