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이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.