Android 사용자 정의 별 평가 컨트롤

다음은 컨트롤 의 실현 과정 입 니 다.
이 컨트롤 은 효율 적 입 니 다.ondraw 로 직접 그립 니 다.먼저 밝 게 비 춥 니 다.

안 드 로 이 드 자체 의 별 평가 컨트롤 스타일 은 바 꿀 수 있 지만 크기 조절 이 쉽 지 않 은 단점 이 있 습 니 다.small normal 같은 style 로 만 조정 할 수 있 고 사용자 정의 가 강하 지 않 기 때문에 제 가 별 컨트롤 을 사용자 정의 하려 는 욕망 을 격발 하 였 습 니 다.
별 평가 컨트롤 의 디자인 은 대체적으로 다음 과 같다.
그림 두 장,밝 은 별 하나,빈 별 하나 가 필요 합 니 다.(물론 그림 이 꼭 별 이 아니 라 다른 그림 도 괜 찮 습 니 다.지금 실험 은 별 을 사용 하면 됩 니 다.)별 수 는 간격 을 사용자 정의 할 수 있 습 니 다.별의 최소 걸음 은 0.1 입 니 다.사용자 가 사용 할 때 안 드 로 이 드 가 가지 고 있 는 방법 과 같 습 니 다.
별 컨트롤 은 크게 2 층,1 층 빈 별,2 층 밝 은 별,1 층 고정,2 층 동적 그리 기 로 나 뉘 어 평 점 을 받 을 수 있 습 니 다.
별 을 그 릴 때 xml 에서 돌아 온 대상 이 drawable 이기 때문에 bitmap 으로 전환 하지 않 아 도 되 기 때문에 drawable 을 직접 그 려 효율 을 높 일 수 있 습 니 다.
drawable 을 그 리 는 데 는 두 가지 방법 이 필요 합 니 다.
1.설정 을 그리 기:
setBounds(int left ,int top , int right ,int bottom);
2.그리 기:
draw(Canvas canvas);

하나의 for 순환 을 거 쳐 다섯 개의 빈 별 이 나 왔 습 니 다.하하

for (int i = 0;i < starCount;i++) {
   starEmptyDrawable.setBounds(starSize * i, 0, starSize * (i + 1), starSize);
   starEmptyDrawable.draw(canvas);
  }


for (int i = 0;i < starCount;i++) {
   starEmptyDrawable.setBounds(starSize * i, 0, starSize * (i + 1), starSize);
   starEmptyDrawable.draw(canvas);
  }
  for (int i = 0;i < starCount -1;i++) {
   starFillDrawable.setBounds(starSize * i, 0, starSize * (i + 1), starSize);
   starFillDrawable.draw(canvas);
  }

위의 몇 줄 의 코드 가 4 점 짜 리 로 강제로 설치 되 었 다
지금 은 몇 개의 별 이 스트레스 를 받 지 않 는 다 는 것 을 보 여 준다.그러나 우리 의 목 표 는 0.1 의 별 로 나 아 가 는 것 이다.
But
일련의 실험 을 통 해 Drawable 대상 이 그리 기 에 필요 한 부분 을 지정 하지 못 한 것 을 발견 했다.즉,별 반 개 를 그리 지 못 한 다 는 것 이다(어차피 찾 을 수 없 으 니 댓 글 을 찾 아 알려 줄 수 있다).그리고 절충 하 는 방법 으로 Drawable 대상 을 Bitmap 으로 바 꾸 면 된다.그리고 BitmapShader 를 이용 하여 그 리 려 는 만큼 많이 그립 니 다(즉,0.1 단계 진입 을 실현 하 는 것).다음은 1/3 개의 효과:

변환 방법:

private Bitmap drawableToBitmap(Drawable drawable)
 {
  if (drawable == null)return null;
  Bitmap bitmap = Bitmap.createBitmap(starSize, starSize, Bitmap.Config.ARGB_8888);
  Canvas canvas = new Canvas(bitmap);
  drawable.setBounds(0, 0, starSize, starSize);
  drawable.draw(canvas);
  return bitmap;
 }

Bitmap 를 붓 으로 변환 하여 그립 니 다:

paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(new BitmapShader(starFillBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));

ondraw()방법 으로 그리 기(3 분 의 1 개)
canvas.drawRect(0,0,starSize/3,starSize,paint);
원 리 는 이 렇 습 니 다.나머지 는 논리 적 인 문제 입 니 다.다음은 별 컨트롤 코드 입 니 다.

package com.dming.starbar;

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.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/**
 * Created by DMing on 2016/7/18.
 *
 */
public class StarBar extends View{
 private int starDistance = 0; //    
 private int starCount = 5; //    
 private int starSize;  //      ,       ,      
 private float starMark = 0.0F; //    
 private Bitmap starFillBitmap; //   
 private Drawable starEmptyDrawable; //   
 private OnStarChangeListener onStarChangeListener;//        
 private Paint paint;   //      
 private boolean integerMark = false;
 public StarBar(Context context, AttributeSet attrs) {
  super(context, attrs);
  init(context, attrs);
 }

 public StarBar(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  init(context, attrs);
 }

 /**
  *    UI  
  *
  * @param context
  * @param attrs
  */
 private void init(Context context, AttributeSet attrs){
  setClickable(true);
  TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.RatingBar);
  this.starDistance = (int) mTypedArray.getDimension(R.styleable.RatingBar_starDistance, 0);
  this.starSize = (int) mTypedArray.getDimension(R.styleable.RatingBar_starSize, 20);
  this.starCount = mTypedArray.getInteger(R.styleable.RatingBar_starCount, 5);
  this.starEmptyDrawable = mTypedArray.getDrawable(R.styleable.RatingBar_starEmpty);
  this.starFillBitmap = drawableToBitmap(mTypedArray.getDrawable(R.styleable.RatingBar_starFill));
  mTypedArray.recycle();

  paint = new Paint();
  paint.setAntiAlias(true);
  paint.setShader(new BitmapShader(starFillBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
 }

 /**
  *           
  * @param integerMark
  */
 public void setIntegerMark(boolean integerMark){
  this.integerMark = integerMark;
 }

 /**
  *           
  *
  * @param mark
  */
 public void setStarMark(float mark){
  if (integerMark) {
   starMark = (int)Math.ceil(mark);
  }else {
   starMark = Math.round(mark * 10) * 1.0f / 10;
  }
  if (this.onStarChangeListener != null) {
   this.onStarChangeListener.onStarChange(starMark); //      
  }
  invalidate();
 }

 /**
  *          
  *
  * @return starMark
  */
 public float getStarMark(){
  return starMark;
 }


 /**
  *            
  */
 public interface OnStarChangeListener {
  void onStarChange(float mark);
 }

 /**
  *     
  * @param onStarChangeListener
  */
 public void setOnStarChangeListener(OnStarChangeListener onStarChangeListener){
  this.onStarChangeListener = onStarChangeListener;
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  setMeasuredDimension(starSize * starCount + starDistance * (starCount - 1), starSize);
 }

 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  if (starFillBitmap == null || starEmptyDrawable == null) {
   return;
  }
  for (int i = 0;i < starCount;i++) {
   starEmptyDrawable.setBounds((starDistance + starSize) * i, 0, (starDistance + starSize) * i + starSize, starSize);
   starEmptyDrawable.draw(canvas);
  }
  if (starMark > 1) {
   canvas.drawRect(0, 0, starSize, starSize, paint);
   if(starMark-(int)(starMark) == 0) {
    for (int i = 1; i < starMark; i++) {
     canvas.translate(starDistance + starSize, 0);
     canvas.drawRect(0, 0, starSize, starSize, paint);
    }
   }else {
    for (int i = 1; i < starMark - 1; i++) {
     canvas.translate(starDistance + starSize, 0);
     canvas.drawRect(0, 0, starSize, starSize, paint);
    }
    canvas.translate(starDistance + starSize, 0);
    canvas.drawRect(0, 0, starSize * (Math.round((starMark - (int) (starMark))*10)*1.0f/10), starSize, paint);
   }
  }else {
   canvas.drawRect(0, 0, starSize * starMark, starSize, paint);
  }
 }


 @Override
 public boolean onTouchEvent(MotionEvent event) {
  int x = (int) event.getX();
  if (x < 0) x = 0;
  if (x > getMeasuredWidth()) x = getMeasuredWidth();
  switch(event.getAction()){
   case MotionEvent.ACTION_DOWN: {
    setStarMark(x*1.0f / (getMeasuredWidth()*1.0f/starCount));
    break;
   }
   case MotionEvent.ACTION_MOVE: {
    setStarMark(x*1.0f / (getMeasuredWidth()*1.0f/starCount));
    break;
   }
   case MotionEvent.ACTION_UP: {
    break;
   }
  }
  invalidate();
  return super.onTouchEvent(event);
 }

 /**
  * drawable bitmap
  *
  * @param drawable
  * @return
  */
 private Bitmap drawableToBitmap(Drawable drawable)
 {
  if (drawable == null)return null;
  Bitmap bitmap = Bitmap.createBitmap(starSize, starSize, Bitmap.Config.ARGB_8888);
  Canvas canvas = new Canvas(bitmap);
  drawable.setBounds(0, 0, starSize, starSize);
  drawable.draw(canvas);
  return bitmap;
 }
}
attrs 파일:

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <declare-styleable name="RatingBar">
  <!--    -->
  <attr format="dimension" name="starDistance"/>
  <!--    -->
  <attr format="dimension" name="starSize"/>
  <!--    -->
  <attr format="integer" name="starCount"/>
  <!--    -->
  <attr format="reference" name="starEmpty"/>
  <!--    -->
  <attr format="reference" name="starFill"/>
 </declare-styleable>

</resources>

XML 사용 방법:

 <com.dming.starbar.StarBar
  android:id="@+id/starBar"
  android:layout_below="@+id/display"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  ratingbar:starEmpty="@drawable/star_empty"
  ratingbar:starFill="@drawable/star_full"
  ratingbar:starDistance="5dp"
  ratingbar:starCount="8"
  ratingbar:starSize="30dp"/>
<중점>공정 소스 코드:http://xiazai.jb51.net/201701/yuanma/AndroidStarBar(jb51.net).rar
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기