별의 색과 크기를 어떻게 바꿀 수 있습니까?
별의 색과 크기를 어떻게 바꿀 수 있습니까?
답변:
1 단계 :에서 기존 스타일 중 하나를 복제하여 (에서 $ANDROID_HOME/platforms/$SDK/data/res/values/styles.xml
) 자신의 프로젝트 styles.xml
에 배치하고 위젯을 레이아웃에 추가 할 때이를 참조 하여 자신 만의 스타일을 만듭니다 .
2 단계 :의 고유 한 LayerDrawable
XML 리소스 RatingBar
를 만들어 막대에 사용할 적절한 이미지를 가리 킵니다. 원래 스타일은 비교할 수있는 기존 리소스를 가리 킵니다. 그런 다음 LayerDrawable
기본 제공 자원이 아닌 고유 한 자원 을 사용하도록 스타일을 조정하십시오 .
언급 된 블로그에서는 조금 복잡합니다. 비슷하지만 더 간단한 방법을 사용했습니다. 3 개의 별 이미지 (red_star_full.png, red_star_half.png 및 red_star_empty.png)와 하나의 XML이 필요합니다.
이 3 개의 이미지를 해상도 / 드로어 블에 놓습니다.
다음 ratingbar_red.xml을 넣으십시오.
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background" android:drawable="@drawable/red_star_empty" />
<item android:id="@android:id/secondaryProgress" android:drawable="@drawable/red_star_half" />
<item android:id="@android:id/progress" android:drawable="@drawable/red_star_full" />
</layer-list>
마지막으로, 평가 막대 정의에이를 사용하도록 지시하십시오. 즉
<RatingBar android:progressDrawable="@drawable/ratingbar_red"/>
그게 다야.
색상 만 변경하려면 다음을 시도하십시오.
RatingBar ratingBar = (RatingBar) findViewById(R.id.ratingBar);
LayerDrawable stars = (LayerDrawable) ratingBar.getProgressDrawable();
stars.getDrawable(2).setColorFilter(Color.YELLOW, PorterDuff.Mode.SRC_ATOP);
PorterDuff.Mode.SRC_ATOP
의미합니까?
Drawable stars = rb.getProgressDrawable(); stars.setTint( Color.YELLOW );
AppCompat Activity를 확장하는 경우 가장 효과적인 방법은 ...
build.gradle에서 최신 appcompat 라이브러리를 추가하십시오.
dependencies {
compile 'com.android.support:appcompat-v7:X.X.X' // where X.X.X version
}
활동을 android.support.v7.app.AppCompatActivity로 확장하십시오.
public class MainActivity extends AppCompatActivity {
...
}
styles.xml 파일에서 사용자 정의 스타일을 선언하십시오.
<style name="RatingBar" parent="Theme.AppCompat">
<item name="colorControlNormal">@color/indigo</item>
<item name="colorControlActivated">@color/pink</item>
</style>
android : theme 속성을 통해이 스타일을 RatingBar에 적용하십시오.
<RatingBar
android:theme="@style/RatingBar"
android:rating="3"
android:stepSize="0.5"
android:numStars="5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
style="?android:ratingBarStyleSmall"
함께 사용할 수 있습니다 .
<style name="RatingBarSmallTheme" parent="Theme.AppCompat"> <item name="colorControlNormal">@color/colorOrangeNormal</item> <item name="colorControlActivated">@color/colorOrangeActivated</item> <item name="ratingBarStyle">@style/Widget.AppCompat.RatingBar.Small</item> </style>
하고 ratingBar android:theme="@style/RatingBarSmallTheme"
2015 년 업데이트
이제 DrawableCompat 를 사용 하여 모든 종류의 드로어 블을 착색 할 수 있습니다 . 예를 들면 다음과 같습니다.
Drawable progress = ratingBar.getProgressDrawable();
DrawableCompat.setTint(progress, Color.WHITE);
이것은 API 4까지 하위 호환됩니다
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {}
는 API 22에서 기본적으로 작업하기 때문에
API 21부터이 세 줄의 코드로 별의 색상을 변경하는 것은 매우 쉽습니다.
android:progressTint="@android:color/holo_red_dark"
android:progressBackgroundTint="@android:color/holo_red_dark"
android:secondaryProgressTint="@android:color/holo_red_dark"
이렇게하면 다음과 같이 변경됩니다.
모든 별의 색상을 변경하려면 내 사용 상태를 나타냅니다.
LayerDrawable stars = (LayerDrawable) ratingBar.getProgressDrawable();
stars.getDrawable(2).setColorFilter(getResources().getColor(R.color.starFullySelected), PorterDuff.Mode.SRC_ATOP);
stars.getDrawable(1).setColorFilter(getResources().getColor(R.color.starPartiallySelected), PorterDuff.Mode.SRC_ATOP);
stars.getDrawable(0).setColorFilter(getResources().getColor(R.color.starNotSelected), PorterDuff.Mode.SRC_ATOP);
Alex와 CommonsWares가 게시 한 솔루션이 정확합니다. 안드로이드가 결코 이야기하지 않는 것은 밀도에 따라 적절한 픽셀 크기입니다. 다음은 후광을 기준으로 각 밀도에 필요한 치수입니다.
작은 별
mdpi: 16px
hdpi: 24px
xhdpi: 32px
xxhdpi: 48px
미디엄 스타
mdpi: 24px
hdpi: 36px
xhdpi: 48px
xxhdpi: 72px
큰 별
mdpi: 35px
hdpi: 52px
xhdpi: 69px
xxhdpi: 105px
그래서 나는 2 시간 동안이 문제로 어려움을 겪었고 절반 별 등급도 표시되는 모든 API 버전에 대한 작동 솔루션을 생각해 냈습니다.
private void setRatingStarColor(Drawable drawable, @ColorInt int color)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
DrawableCompat.setTint(drawable, color);
}
else
{
drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
}
}
다음과 같은 드로어 블 순서로 메소드를 호출하십시오.
LayerDrawable stars = (LayerDrawable) ratingBar.getProgressDrawable();
// Filled stars
setRatingStarColor(stars.getDrawable(2), ContextCompat.getColor(getContext(), R.color.foreground));
// Half filled stars
setRatingStarColor(stars.getDrawable(1), ContextCompat.getColor(getContext(), R.color.background));
// Empty stars
setRatingStarColor(stars.getDrawable(0), ContextCompat.getColor(getContext(), R.color.background));
참고 : 또한 XML에서 "max"및 "numStars"속성을 지정해야합니다. 그렇지 않으면 절반 별표가 표시되지 않습니다.
Mode.SRC_IN
또는 Mode.MULTIPLY
?
이제 AppCompat v22.1.0 이상의 DrawableCompat 를 사용 하여 모든 종류의 드로어 블을 동적으로 채색 할 수 있습니다 . 단일 드로어 블 세트로 여러 테마를 지원할 때 유용합니다. 예를 들면 다음과 같습니다.
LayerDrawable layerDrawable = (LayerDrawable) ratingBar.getProgressDrawable();
DrawableCompat.setTint(DrawableCompat.wrap(layerDrawable.getDrawable(0)), Color.RED); // Empty star
DrawableCompat.setTint(DrawableCompat.wrap(layerDrawable.getDrawable(1)), Color.GREEN); // Partial star
DrawableCompat.setTint(DrawableCompat.wrap(layerDrawable.getDrawable(2)), Color.BLUE); // Full star
이는 API 4와 하위 호환됩니다. 또한 Support Libraries v22.1.0 에 대한 Chris Banes의 블로그 게시물을 참조하십시오.
실제 크기와 모양을 위해서는 다른 사람들이 이미 위에서 대답했듯이 적절한 크기에 대한 새로운 스타일과 레이어 목록 드로어 블을 정의해야합니다.
android:theme
속성 사용 :
styles.xml
<style name="Theme.Rating" parent="Theme.AppCompat.Light">
<item name="colorAccent">@color/rating</item>
</style>
layout.xml
<android.support.v7.widget.AppCompatRatingBar
android:theme="@style/Theme.Rating"
android:numStars="5"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
색상을 변경하려면 android : progressTint 매개 변수를 설정해야합니다.
<RatingBar
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginTop="15dp"
android:numStars="5"
android:rating="1"
android:progressTint="@android:/color/black"
android:layout_gravity="center"
/>
크기는 스타일 속성입니다.
@lgvalle의 답변을 작성하십시오.
2015 년 업데이트
이제 DrawableCompat를 사용하여 모든 종류의 드로어 블을 착색 할 수 있습니다. 예를 들면 다음과 같습니다.
드로어 블 진행률 = ratingBar.getProgressDrawable (); DrawableCompat.setTint (progress, Color.WHITE); 이것은 API 4까지 하위 호환됩니다
LayerDrawable drawable = (LayerDrawable) getProgressDrawable();
Drawable progress = drawable.getDrawable(2);
DrawableCompat.setTint(progress, getResources().getColor(COLOR1));
progress = drawable.getDrawable(1);
DrawableCompat.setTintMode(progress, PorterDuff.Mode.DST_ATOP);
DrawableCompat.setTint(progress, getResources().getColor(COLOR1));
DrawableCompat.setTintMode(progress, PorterDuff.Mode.SRC_ATOP);
DrawableCompat.setTint(progress, getResources().getColor(COLOR2));
progress = drawable.getDrawable(0);
DrawableCompat.setTint(progress, getResources().getColor(COLOR2));
이것은 분수 단계 색상을 유지합니다.
새로운 스타일을 추가하지 않고 색조 색상을 사용할 수 있습니다. RatingBar
<RatingBar
android:id="@+id/ratingBar"
style="@android:style/Widget.Holo.RatingBar.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numStars="5"
android:rating="4.5"
android:stepSize="0.5"
android:progressTint="@color/colorPrimary"/>
몇 가지 연구를 한 후 배경 색조, 간격 색조 (예 : 반 별) 및 별 색조 색상을 설정하는이 방법을 생각해 냈습니다.
LayerDrawable layers = (LayerDrawable) ratingBar.getProgressDrawable();
DrawableCompat.setTint(layers.getDrawable(0), 0x33000000); // The background tint
DrawableCompat.setTint(layers.getDrawable(1), 0x00000000); // The gap tint (Transparent in this case so the gap doesnt seem darker than the background)
DrawableCompat.setTint(layers.getDrawable(2), 0xffFED80A); // The star tint
이 문제를 다음과 같이 해결합니다.
LayerDrawable layerDrawable = (LayerDrawable) ratingBar.getProgressDrawable();
DrawableCompat.setTint(DrawableCompat.wrap(layerDrawable.getDrawable(0)),
Color.WHITE); // Empty star
DrawableCompat.setTint(DrawableCompat.wrap(layerDrawable.getDrawable(1)),
Color.YELLOW); // Partial star
DrawableCompat.setTint(DrawableCompat.wrap(layerDrawable.getDrawable(2)),
Color.YELLOW);
테마에 따라 별의 색상을 변경하는 간단한 해결책을 찾았습니다.
이 사이트로 이동 : http://android-holo-colors.com/
테마 색상을 선택하고 스타 이미지를 만드십시오.
위의 답변을 사용하여 쉽게 재사용 할 수있는 빠른 정적 방법을 만들었습니다. 활성화 된 별의 진행 색상을 색조하는 것만 목표로합니다. 활성화되지 않은 별은 회색으로 유지됩니다.
public static RatingBar tintRatingBar (RatingBar ratingBar, int progressColor)if (ratingBar.getProgressDrawable() instanceof LayerDrawable) {
LayerDrawable progressDrawable = (LayerDrawable) ratingBar.getProgressDrawable();
Drawable drawable = progressDrawable.getDrawable(2);
Drawable compat = DrawableCompat.wrap(drawable);
DrawableCompat.setTint(compat, progressColor);
Drawable[] drawables = new Drawable[3];
drawables[2] = compat;
drawables[0] = progressDrawable.getDrawable(0);
drawables[1] = progressDrawable.getDrawable(1);
LayerDrawable layerDrawable = new LayerDrawable(drawables);
ratingBar.setProgressDrawable(layerDrawable);
return ratingBar;
}
else {
Drawable progressDrawable = ratingBar.getProgressDrawable();
Drawable compat = DrawableCompat.wrap(progressDrawable);
DrawableCompat.setTint(compat, progressColor);
ratingBar.setProgressDrawable(compat);
return ratingBar;
}
}
다음을 사용하여 등급 막대와 색상을 전달하십시오. getResources().getColor(R.color.my_rating_color)
보시다시피 DrawableCompat을 사용하므로 이전 버전과 호환됩니다.
편집 :이 방법은 API21에서 작동하지 않습니다 (이유를 이해하십시오). setProgressBar를 호출 할 때 NullPointerException이 발생합니다. API> = 21에서 전체 메소드를 비활성화했습니다.
API> = 21의 경우 SupperPuccio 솔루션을 사용합니다.
터치 바의 색상 변경을 위해 등급 표시 줄이 런타임에 자동으로 사용됩니다.
먼저 app \ src \ main \ res \ values \ styles.xml 파일에 스타일을 추가하십시오.
<style name="RatingBar" parent="Theme.AppCompat">
<item name="colorControlNormal">@android:color/darker_gray</item>
<item name="colorControlActivated">@color/com_facebook_blue</item>
</style>
그런 다음 등급 표시 줄에 다음과 같은 테마가 추가됩니다.
<RatingBar
android:id="@+id/rating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numStars="5"
android:stepSize="1"
android:theme="@style/RatingBar"/>
1)이 XML을 선언하십시오.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:layout_marginBottom="20dp"
android:background="#323232"
android:gravity="center_horizontal">
<com.example.android.custom_ratingbar.CustomRatingBar
android:id="@+id/coloredRatingBar5"
style="@style/coloredRatingBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="match_parent"
/>
</LinearLayout>
2) style.xml에서
<style name="coloredRatingBarStyleSmall">
<item name="indicator">false</item>
<item name="type">small</item>
</style>
삼)
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class CustomRatingBar extends View{
private static final String TAG="ColoredRatingBar";
private static final int NORMAL = 0;
private static final int SMALL = 1;
Bitmap[] drawables;
Bitmap progressBackground;
Context mContext;
private int mNumStars =9;
private float mRating =0;
private boolean mIndicator;
private float slidePosition;
private int mType;
/**
* A callback that notifies clients when the rating has been changed. This
* includes changes that were initiated by the user through a touch gesture
* or arrow key/trackball as well as changes that were initiated
* programmatically.
*/
public interface OnRatingBarChangeListener {
/**
* Notification that the rating has changed. Clients can use the
* fromUser parameter to distinguish user-initiated changes from those
* that occurred programmatically. This will not be called continuously
* while the user is dragging, only when the user finalizes a rating by
* lifting the touch.
*
* @param ratingBar The RatingBar whose rating has changed.
* @param rating The current rating. This will be in the range
* 0..numStars.
* @param fromUser True if the rating change was initiated by a user's
* touch gesture or arrow key/horizontal trackbell movement.
*/
void onRatingChanged(CustomRatingBar ratingBar, float rating, boolean fromUser);
}
private OnRatingBarChangeListener mOnRatingBarChangeListener;
public CustomRatingBar(Context context) {
this(context, null);
}
public CustomRatingBar(Context context, AttributeSet attrs) {
this(context, attrs,0);//R.attr.coloredRatingBarStyle
}
public CustomRatingBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomRatingBar,defStyle, 0);
final boolean indicator = a.getBoolean(R.styleable.CustomRatingBar_indicator, false);
final float rating = a.getFloat(R.styleable.CustomRatingBar_setrating, -1);
final int type = a.getInt(R.styleable.CustomRatingBar_type, 0);
a.recycle();
setIndicator(indicator);
setRating(rating);
setType(type);
init(context);
}
public int getType() {
return mType;
}
public void setType(int type) {
this.mType = type;
}
private void init(Context context) {
mContext = context;
Resources res = getResources();
if(mType==SMALL){
drawables = new Bitmap[]{BitmapFactory.decodeResource(res, R.drawable.rating_inactive),BitmapFactory.decodeResource(res, R.drawable.rating_active)};
progressBackground = BitmapFactory.decodeResource(res, R.drawable.rating_inactive);
}else{
drawables = new Bitmap[]{BitmapFactory.decodeResource(res, R.drawable.rating_inactive),BitmapFactory.decodeResource(res, R.drawable.rating_active)};
progressBackground = BitmapFactory.decodeResource(res, R.drawable.rating_inactive);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//draw empty stars bg
for(int i=0;i< mNumStars;i++){
drawStar(canvas,i);
}
}
private void drawStar(Canvas canvas, int position) {
float fraction = mRating -(position);
Bitmap ratedStar1 = getRatedStar();
Paint paint=getPaint(position);
int division=getSize();
Bitmap ratedStar=null;
Bitmap emptyStar=null;
if(!isInEditMode()){
ratedStar=Bitmap.createScaledBitmap(ratedStar1, division, division, false);
emptyStar=Bitmap.createScaledBitmap(progressBackground, division, division, false);
}
if((position)< mRating){
if(!isInEditMode()){
canvas.drawBitmap(ratedStar,(position* division),0,paint);
}
} else{
if(!isInEditMode()){
canvas.drawBitmap(emptyStar,(position*division),0,null);
}
}
}
private int getSize(){
return (getWidth()/mNumStars);
}
private Bitmap getRatedStar() {
if(mRating==0){
return drawables[0];
}
else{
return drawables[1];
}
}
private Paint getPaint(int position){
int value=(255*(position+1))/mNumStars;
String hexString=Integer.toHexString(value).equals("0")?"00":Integer.toHexString(value);
String hexvalue="#"+hexString+"000000";//FEE98E
//Log.e("TAG", position+"/"+value+"/"+hexvalue);
Paint paint=new Paint();
paint.setColor(Color.parseColor(hexvalue));
return paint;
}
public int getNumStars() {
return mNumStars;
}
public void setNumStars(int numStars) {
this.mNumStars = numStars;
}
public float getRating() {
return mRating;
}
public void setRating(float rating) {
setRating(rating,false);
}
void setRating(float rating,boolean fromUser) {
if(rating>mNumStars){
this.mRating = mNumStars;
}
this.mRating = rating;
invalidate();
dispatchRatingChange(fromUser);
}
public boolean isIndicator() {
return mIndicator;
}
public void setIndicator(boolean indicator) {
this.mIndicator = indicator;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (progressBackground != null) {
final int width = progressBackground.getWidth() * mNumStars;
final int height = progressBackground.getHeight();
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
Bitmap emptyStar=Bitmap.createScaledBitmap(progressBackground, widthSize/mNumStars, widthSize/mNumStars, false);
int heightSize = emptyStar.getHeight();
setMeasuredDimension(resolveSizeAndState(widthSize, widthMeasureSpec, 0),
resolveSizeAndState(heightSize, heightMeasureSpec, 0));
}
else{
int desiredWidth = 100;
int desiredHeight = 50;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
//Measure Width
if (widthMode == MeasureSpec.EXACTLY) {
//Must be this size
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
width = Math.min(desiredWidth, widthSize);
} else {
//Be whatever you want
width = desiredWidth;
}
//Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
//Must be this size
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
height = Math.min(desiredHeight, heightSize);
} else {
//Be whatever you want
height = desiredHeight;
}
//MUST CALL THIS
setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, 0),resolveSizeAndState(height, heightMeasureSpec, 0));
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if(mIndicator){
return false;
}
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
slidePosition = getRelativePosition(event.getX());
int newRating = (int)(slidePosition>0?slidePosition+1:0) ;
if(newRating>mNumStars){
newRating=mNumStars;
}
// Log.e("TAG", ""+newRating);
if (newRating != mRating) {
setRating(newRating,true);
}
break;
case MotionEvent.ACTION_CANCEL:
break;
default:
break;
}
return true;
}
private float getRelativePosition(float x) {
Bitmap emptyStar=Bitmap.createScaledBitmap(progressBackground, getWidth()/mNumStars, getWidth()/mNumStars, false);
int widthSize = emptyStar.getWidth();
// Log.e("TAG", widthSize+"/"+x);
float position = x / widthSize;
position = Math.max(position, 0);
return Math.min(position, mNumStars);
}
/**
* Sets the listener to be called when the rating changes.
*
* @param listener The listener.
*/
public void setOnRatingBarChangeListener(OnRatingBarChangeListener listener) {
mOnRatingBarChangeListener = listener;
}
/**
* @return The listener (may be null) that is listening for rating change
* events.
*/
public OnRatingBarChangeListener getOnRatingBarChangeListener() {
return mOnRatingBarChangeListener;
}
void dispatchRatingChange(boolean fromUser) {
if (mOnRatingBarChangeListener != null) {
mOnRatingBarChangeListener.onRatingChanged(this, getRating(),
fromUser);
}
}
}
5) then in calling activity---
CustomRatingBar coloredRatingBar5=(CustomRatingBar)findViewById(R.id.coloredRatingBar5);
coloredRatingBar5.setOnRatingBarChangeListener(new OnRatingBarChangeListener() {
@Override
public void onRatingChanged(CustomRatingBar ratingBar, float rating,boolean fromUser) {
// TODO Auto-generated method stub
Log.e("RATING", ""+rating);
}
});
6) 등급 활성-진한 색상으로 이미지를 촬영합니다. 등급이 다른 색상 투명도로 사용됩니다.
rating_inactive-- 배경이 밝은 위 이미지와 동일한 크기의 이미지를 촬영합니다. 등급이 선택되지 않은 경우에 사용됩니다.
별의 테두리 색상을 변경하는 가장 쉬운 방법은 xml 매개 변수를 사용하는 것입니다.
android:progressBackgroundTint=""
ratingBar보기에서. 값은 색상의 16 진수 코드 여야합니다.
적어도 API 9 까지이 작업을 수행 할 수있는 신뢰할 수있는 방법을 찾고있었습니다. "casting to LayerDrawble"솔루션은 나에게 위험한 솔루션처럼 보였으며 2.3에서 Android 전화에서 테스트했을 때 성공적으로 전송되었지만 DrawableCompat.setTint (...) 호출은 아무런 영향을 미치지 않았습니다.
드로어 블 자산을로드 할 필요도 나에게 좋은 해결책이 아닌 것 같습니다.
별표를 프로그래밍 방식으로 그리는 것을 담당하는 사용자 정의 Drawable을 사용하여 AppCompatRatingBar를 확장하는 클래스 인 내 솔루션을 코딩하기로 결정했습니다. 그것은 내 요구에 완벽하게 작동합니다. 누군가를 도울 수 있도록 게시 할 것입니다.
https://gist.github.com/androidseb/2b8044c90a07c7a52b4bbff3453c8460
전체 파일을 직접 얻을 수 있기 때문에 링크가 더 쉬우나 다음과 같은 경우에 전체 코드가 있습니다.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.AppCompatRatingBar;
import android.util.AttributeSet;
/**
* @author androidseb
* <p/>
* Extends AppCompatRatingBar with the ability to tint the drawn stars when selected, pressed and un-selected.
* Limitation: Only draws full stars.
*/
public class TintableRatingBar extends AppCompatRatingBar {
private TintableRatingBarProgressDrawable progressDrawable;
public TintableRatingBar(final Context context) {
super(context);
init();
}
public TintableRatingBar(final Context context, final AttributeSet attrs) {
super(context, attrs);
init();
}
public TintableRatingBar(final Context context, final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
progressDrawable = new TintableRatingBarProgressDrawable();
setProgressDrawable(progressDrawable);
}
public void setCustomTintColors(final int _uncheckedColor, final int _pressedColor, final int _checkedColor) {
progressDrawable.setRatingMaxLevelValue(getMax() * 1000);
progressDrawable.setUnCheckedColor(_uncheckedColor);
progressDrawable.setPressedColor(_pressedColor);
progressDrawable.setCheckedColor(_checkedColor);
invalidate();
}
public class TintableRatingBarProgressDrawable extends Drawable {
private static final int STAR_COUNT = 5;
private static final int STAR_BRANCHES_COUNT = 5;
/** Sets the max level value: if the level is at the max, then all stars are selected. */
private int ratingMaxLevelValue = 10000;
/** Color to be painted for unselected stars */
private int uncheckedColor = Color.GRAY;
/** Color to be painted for unselected stars when the ratingbar is pressed */
private int pressedColor = Color.CYAN;
/** Color to be painted for selected stars */
private int checkedColor = Color.BLUE;
@Override
public void setAlpha(final int _i) {
}
@Override
public void setColorFilter(final ColorFilter _colorFilter) {
}
@Override
public boolean isStateful() {
return true;
}
@Override
public boolean setState(final int[] stateSet) {
final boolean res = super.setState(stateSet);
invalidateSelf();
return res;
}
@Override
public int getOpacity() {
return 255;
}
public void setRatingMaxLevelValue(final int _ratingMaxLevelValue) {
ratingMaxLevelValue = _ratingMaxLevelValue;
}
public void setUnCheckedColor(final int _uncheckedColor) {
uncheckedColor = _uncheckedColor;
}
public void setPressedColor(final int _pressedColor) {
pressedColor = _pressedColor;
}
public void setCheckedColor(final int _checkedColor) {
checkedColor = _checkedColor;
}
@Override
public void draw(final Canvas _canvas) {
boolean pressed = false;
for (int i : getState()) {
if (i == android.R.attr.state_pressed) {
pressed = true;
}
}
final int level = (int) Math.ceil(getLevel() / (double) ratingMaxLevelValue * STAR_COUNT);
final int starRadius = Math.min(getBounds().bottom / 2, getBounds().right / STAR_COUNT / 2);
for (int i = 0; i < STAR_COUNT; i++) {
final int usedColor;
if (level >= i + 1) {
usedColor = checkedColor;
} else if (pressed) {
usedColor = pressedColor;
} else {
usedColor = uncheckedColor;
}
drawStar(_canvas, usedColor, (i * 2 + 1) * starRadius, getBounds().bottom / 2, starRadius,
STAR_BRANCHES_COUNT);
}
}
private void drawStar(final Canvas _canvas, final int _color, final float _centerX, final float _centerY,
final float _radius, final int _branchesCount) {
final double rotationAngle = Math.PI * 2 / _branchesCount;
final double rotationAngleComplement = Math.PI / 2 - rotationAngle;
//Calculating how much space is left between the bottom of the star and the bottom of the circle
//In order to be able to center the star visually relatively to the square when drawn
final float bottomOffset = (float) (_radius - _radius * Math.sin(rotationAngle / 2) / Math.tan(
rotationAngle / 2));
final float actualCenterY = _centerY + (bottomOffset / 2);
final Paint paint = new Paint();
paint.setColor(_color);
paint.setStyle(Style.FILL);
final Path path = new Path();
final float relativeY = (float) (_radius - _radius * (1 - Math.sin(rotationAngleComplement)));
final float relativeX = (float) (Math.tan(rotationAngle / 2) * relativeY);
final PointF a = new PointF(-relativeX, -relativeY);
final PointF b = new PointF(0, -_radius);
final PointF c = new PointF(relativeX, -relativeY);
path.moveTo(_centerX + a.x, actualCenterY + a.y);
_canvas.save();
for (int i = 0; i < _branchesCount; i++) {
path.lineTo(_centerX + b.x, actualCenterY + b.y);
path.lineTo(_centerX + c.x, actualCenterY + c.y);
rotationToCenter(b, rotationAngle);
rotationToCenter(c, rotationAngle);
}
_canvas.drawPath(path, paint);
_canvas.restore();
}
private void rotationToCenter(final PointF _point, final double _angleRadian) {
final float x = (float) (_point.x * Math.cos(_angleRadian) - _point.y * Math.sin(_angleRadian));
final float y = (float) (_point.x * Math.sin(_angleRadian) + _point.y * Math.cos(_angleRadian));
_point.x = x;
_point.y = y;
}
}
}
조금 늦게 대답하지만 일부 사람들에게 도움이되기를 바랍니다.
<RatingBar
android:id="@+id/rating"
style="@style/Base.Widget.AppCompat.RatingBar.Small"
android:theme="@style/WhiteRatingStar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/profil_name"
android:layout_centerHorizontal="true"
android:layout_marginLeft="@dimen/dimen_4"
android:rating="3" />
그리고 WhiteRatingStar의 모습은 다음과 같습니다.
<style name="WhiteRatingStar" parent="Base.Widget.AppCompat.RatingBar.Small">
<item name="colorAccent">@android:color/white</item>
</style>
이를 통해 별은 예를 들어 흰색으로 표시됩니다.