Android RatingBar 별표 색상 변경 [닫힘]


141

별의 색과 크기를 어떻게 바꿀 수 있습니까?


그렇게하려면 자신 만의 커스텀 레이팅 바를 만들어야한다고 생각합니다
Donal Rafferty

RatingBar 이미지를 변경하는 방법을 설명하는 블로그 게시물을 작성했습니다. kozyr.zydako.net/2010/05/23/pretty-ratingbar 또한 이미지 크기를 지정할 수있는 위치를 보여줍니다 ...
kozyr

나는이 질문이 웹 사이트에 표시된 것처럼 여러 가지 빛깔의 등급 표시 줄에 대한 것이기를 바랐다. 나를 위해 하나를 찾을 수 없었다. github.com/codebreaker/coloredratingbar-android 라는 간단한 구현을 만들었 습니다 . 이것이 누군가를 도울 수 있기를 바랍니다.
jaga

답변:


26

1 단계 :에서 기존 스타일 중 하나를 복제하여 (에서 $ANDROID_HOME/platforms/$SDK/data/res/values/styles.xml) 자신의 프로젝트 styles.xml에 배치하고 위젯을 레이아웃에 추가 할 때이를 참조 하여 자신 만의 스타일을 만듭니다 .

2 단계 :의 고유 한 LayerDrawableXML 리소스 RatingBar를 만들어 막대에 사용할 적절한 이미지를 가리 킵니다. 원래 스타일은 비교할 수있는 기존 리소스를 가리 킵니다. 그런 다음 LayerDrawable기본 제공 자원이 아닌 고유 한 자원 을 사용하도록 스타일을 조정하십시오 .


1
2 단계에 따라 Samsung 3 장치 나 다른 장치에서는 작동하지 않으므로 LayerDrawable 일 필요는 없습니다. 정보는 여기를 참조하십시오 : stackoverflow.com/questions/30266334/…
Kenny

6
android : progressTint = "@ color / yellow"를 사용하십시오. @superpuccio의 답변을 참조하십시오.
Vincent

2
progressTint는 21 API 레벨 이상 만 지원
Yogesh Rathi

이것이 최고의 솔루션입니다 : stackoverflow.com/a/36297738/1935135
André Luiz Reis

120

언급 된 블로그에서는 조금 복잡합니다. 비슷하지만 더 간단한 방법을 사용했습니다. 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"/>

그게 다야.


3
안녕하세요 Alex,이 솔루션을 시도했지만 등급을 1.1, 1.2 등으로 설정하려고하면 1.5로 표시됩니다. 나는 3 개의 별 이미지, 하나는 비어 있고, 하나는 꽉 찼고 하나는 꽉 찼습니다. 분수 구성 요소를 얻기 위해 둘 사이에 보간해야한다고 가정합니다. 다른 사람이 같은 문제가 있거나 눈에 띄게 잘못된 일이 있는지 궁금합니다.
Graham Baitson

당신은 우리가 날씨를 자사의 컬러 이미지와 이미지의 크기를 사용한다 이미지에 대해 전화를 나를 기쁘게 할 수는 ...이 문제를 해결 할 수없는 메신저
Prithviraj Shiroor에게

1
모두 2015 업데이트 답변을 아래에서 참조하십시오! 훨씬 쉽고 간단합니다!
katie

이 답변은 여전히 ​​별의 다른 상태보다 더 많은 유연성을 제공합니다.
Tom Brinkkemper

별 아래에 세로선이 나타나는 이유는 무엇입니까? 높이를 지정하여 사용자 정의 스타일을 정의하려고 시도했지만 AVD의 별 아래 여전히 세로선이 있습니다.
Aleksandar

93

색상 만 변경하려면 다음을 시도하십시오.

RatingBar ratingBar = (RatingBar) findViewById(R.id.ratingBar);
LayerDrawable stars = (LayerDrawable) ratingBar.getProgressDrawable();
stars.getDrawable(2).setColorFilter(Color.YELLOW, PorterDuff.Mode.SRC_ATOP);

1
정확히 무엇을 PorterDuff.Mode.SRC_ATOP의미합니까?
Zapnologica

5
API 5.0 이상에서는 작동하지 않습니다. 필요 :Drawable stars = rb.getProgressDrawable(); stars.setTint( Color.YELLOW );
zyamys

@zyamys 이건 정말 짜증나 = ( "더 높은 버전"에 대한 방법과 이전 버전에 대한 또 다른 방법이 필요합니까?
Daniela Morais

1
정밀도는 0.5입니다. 그렇지 않으면 (정확도 <0.5) 오버레이가 이상해지며 파란색은 여전히 ​​0.5의 정밀도를 유지하는 반면 노란색은 정확합니다.
Teo Inke

1
경고 : 사전 롤리팝 장치에서 충돌이 발생합니다. 허용 된 답변으로 이동하십시오.
blockwala

70

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"/>

3
@Vishal Kumar에게 감사합니다. Kitkat 4.4.4 (Samsung S3 neo)와 Marshmallow 6.0.1 (Samsung Galaxy On Nxt)에서 시도했지만 효과가있었습니다. 그러나 Lollipop 5.1 (Micromax)에서는 성공하지 못했습니다. Lollipop의 경우 RatingBar에서 "android : progressTint"속성을 사용했는데 작동합니다.
Prashant 2012

이것이 최선의 해결책입니다.
Arhat Baid

정답이 선택되어야합니다.
Hampel Előd

1
이것이 가장 좋은 해결책입니다. 별 크기를 변경하려면 style="?android:ratingBarStyleSmall"함께 사용할 수 있습니다 .
André Luiz Reis

AndréLuizReis @ <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"
Zakhar 라죠 노프

47

2015 년 업데이트

이제 DrawableCompat 를 사용 하여 모든 종류의 드로어 블을 착색 할 수 있습니다 . 예를 들면 다음과 같습니다.

Drawable progress = ratingBar.getProgressDrawable();
DrawableCompat.setTint(progress, Color.WHITE);

이것은 API 4까지 하위 호환됩니다


ratingBar에 드로어 블을 다시 설정하는 것을 잊지 마십시오.
squeeish

15
이렇게하면 전체 드로어 블이 한 가지 색으로 색조가 지정되어 빈 별을 구분하기가 매우 어려워집니다.
blueice

이것은 지원 라이브러리 <22가 아닌 안드로이드 지원 라이브러리> = 22에서만 작동합니다.
Raghav Sharma 2016

2
3.5가 아닌 5 개의 별을 그립니다.
CoolMind

1
난 그냥 둘러싸는 것 그와 if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {}는 API 22에서 기본적으로 작업하기 때문에
요안 Hercouet을

38

API 21부터이 세 줄의 코드로 별의 색상을 변경하는 것은 매우 쉽습니다.

android:progressTint="@android:color/holo_red_dark"
android:progressBackgroundTint="@android:color/holo_red_dark"
android:secondaryProgressTint="@android:color/holo_red_dark" 

이렇게하면 다음과 같이 변경됩니다.

  • 채워진 별 색상 (progressTint)
  • 채워지지 않은 별 색상 (progressBackgroundTint)
  • 별의 테두리 색상 (secondaryProgressTint)

3.5 대신 별 4 개를 그립니다.
CoolMind

@CoolMind는 android : stepSize : 1 대신 0.5 대신 설정
eLemEnt

4
빈 별의 색을 바꾸는 방법?
winklerrr

@winklerrr 당신은 빈 별의 색을 바꾸는 방법을 찾았습니다.
Tarun Kumar

해결책을 찾기 위해 추가 점검을하지 않았습니다
winklerrr

36

모든 별의 색상을 변경하려면 내 사용 상태를 나타냅니다.

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);

데이터베이스에서 가져온 데이터를 기반으로 별색을 설정하는 방법이 있습니까? 하자 내가 5 별과 데이터베이스에서 반환 된 데이터는 4 그래서 그 대신 모든 5 변경, 내가 첫 번째 4 변경했다 가지고 말

1
getColor는 이제 더 이상 사용되지 않습니다.
Manohar Reddy

2
여기에서 답을 찾을 수 있습니다 stackoverflow.com/a/32202256/2513291 예를 들어이 방법의 ContextCompat.getColor (문맥, R.color.color_name)
YURIY 비노그라도프

잘 작동하지만 어떤 이유로 순서가 중요합니다 (2, 1, 0). 나는 그 반대를 시도했으며 처음 색상이 변경 될 때 UI 결함이 발생합니다.
사이먼 니논

25

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

나는 별 vectordrawble 사용할 수 있습니다
미나 Fawzy

24

그래서 나는 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"속성을 지정해야합니다. 그렇지 않으면 절반 별표가 표시되지 않습니다.


API19에 나를 위해 작품,하지만 난 XML 만 T_T에서이 작업을 수행하는 방법을 찾기 위해 포기하지 않은 유일한 방법
에 beeing JK

@BeeingJk RatingBar를 확장하는 커스텀 뷰를 생성하면 고유 한 xml 속성을 생성하여 색조 색상을 지정할 수 있습니다. 그런 다음 색조를 설정하는 단일 제어 지점이 있으며 색조를 xml로 지정할 수 있습니다. 희망이 도움이됩니다! 필요한 경우 더 설명 할 수 있습니다
포레스트 바이스

Mode.SRC_IN또는 Mode.MULTIPLY?
Dr.jacky

12

이제 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의 블로그 게시물을 참조하십시오.

실제 크기와 모양을 위해서는 다른 사람들이 이미 위에서 대답했듯이 적절한 크기에 대한 새로운 스타일과 레이어 목록 드로어 블을 정의해야합니다.


드로어 블은 배열이 아닙니다. 진행 상황에 어떻게 접근하고 있습니까 [0]?
blueice

@blueice 죄송합니다. Drawable은 이제 LayerDrawable이어야합니다. 고마워요.
Dan Dar3 2016 년

여전히 나를 위해 작동하지 않는 것, 나는 Yuriy Vinogradov 가이 질문에 다른 응답을 넣은 것으로 끝났고 그것은 효과가있는 것 같습니다.
blueice

Drawable 대신 색상을 바꾸는 방법?
Iman Marashi

@ImanMarashi 위의 Alex의 XML 기반 답변을 참조하십시오. LayerDrawable.setDrawable (index, drawable) 은 API23 이상에서만 사용할 수 있습니다.
Dan Dar3

10

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" />

9

xml에서 Rating bar의 색상을 변경하려면 다음을 수행하십시오.

android:progressTint="@color/your_color"
android:backgroundTint="@color/your_color"
android:secondaryProgressTint="@color/your_color"

별색

7

색상을 변경하려면 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"
       />

크기는 스타일 속성입니다.


감사 만 API (21)에 작동 이상
Junaid


4

@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));

이것은 분수 단계 색상을 유지합니다.


4
<!--For rating bar -->
    <style name="RatingBarfeed" parent="Theme.AppCompat">
        <item name="colorControlNormal">@color/colorPrimary</item>
        <item name="colorControlActivated">@color/colorPrimary</item>
    </style>

자신의 색을 사용하십시오


4

새로운 스타일을 추가하지 않고 색조 색상을 사용할 수 있습니다. 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"/>

3

버전 21 이하의 Android에서 작동

몇 가지 연구를 한 후 배경 색조, 간격 색조 (예 : 반 별) 및 별 색조 색상을 설정하는이 방법을 생각해 냈습니다.

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

3

간단한 해결책, AppCompatRatingBar 및 해당 setProgressTintList 메소드를 사용하여이를 달성하십시오.이 답변 을 참조하십시오.


재료 :이 com.google.android.material를 사용하여 API 28에서 나를 위해 일한 1.1.0-alpha02
마크 Lapasa

2

이 문제를 다음과 같이 해결합니다.

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);

고마워요. 그러나 분수 등급의 경우 별이 완전히 그려집니다.
CoolMind

2
RatingBar mRating=(RatingBar)findViewById(R.id.rating);
 LayerDrawable layerDrawable=(LayerDrawable)mRating.getProgressDrawable();
 layerDrawable.getDrawable(2).setColorFilter(Color.parseColor
 ("#32CD32"),    PorterDuff.Mode.SRC_ATOP);

나를 위해 작동합니다 ....



1

위의 답변을 사용하여 쉽게 재사용 할 수있는 빠른 정적 방법을 만들었습니다. 활성화 된 별의 진행 색상을 색조하는 것만 목표로합니다. 활성화되지 않은 별은 회색으로 유지됩니다.

    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 솔루션을 사용합니다.


java.lang.ClassCastException : android.support.v4.graphics.drawable.DrawableWrapperHoneycomb는 롤리팝 이전에 android.graphics.drawable.LayerDrawable로 캐스트 할 수 없습니다
Ishaan Garg

1
@IshaanGarg 당신이 맞아요. 같은 문제가 발생하여 메서드가 업데이트되었습니다. 사건을 처리하기 위해 코드를 업데이트했습니다. 나는 그것이 안드로이드 버전의 문제라고 생각하지 않습니다. style = "? android : attr / ratingBarStyleSmall"을 사용하여 더 작은 버전의 등급 막대를 사용하는 경우 반환되는 드로어 블은 여전히 ​​LayoutDrawable입니다.
JDenais

예, 구현 한 것만으로 AppCompatRatingBar를 사용해야합니다. XML / java에서 등급을 사전 설정할 때 별표를 얻을 수는 없지만. setRating (3.5) 쇼처럼 4 완전 별
Ishaan Garg를

1

터치 바의 색상 변경을 위해 등급 표시 줄이 런타임에 자동으로 사용됩니다.

먼저 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"/>

0

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-- 배경이 밝은 위 이미지와 동일한 크기의 이미지를 촬영합니다. 등급이 선택되지 않은 경우에 사용됩니다.


0

별의 테두리 색상을 변경하는 가장 쉬운 방법은 xml 매개 변수를 사용하는 것입니다.

android:progressBackgroundTint=""

ratingBar보기에서. 값은 색상의 16 진수 코드 여야합니다.


내가 왜 모르겠지만, 당신이 별의 경계에 영향을 미치는 유일한 방법 것 같다 (충전 색상은 기본 색상을 유지)
superpuccio

좋아, 일부 XML 매개 변수가 누락되었습니다. 아래에서 내 답변을 확인하십시오.
superpuccio

1
네가 옳아. 나는 왜 그가 별의 테두리 색을 바꾸는 데 문제가 있다고 생각했는지 모른다. 당신의 대답은 더 완전합니다.
포 알 랜디스 마르티네즈

0

적어도 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;
        }
    }
}

0

조금 늦게 대답하지만 일부 사람들에게 도움이되기를 바랍니다.

<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>

이를 통해 별은 예를 들어 흰색으로 표시됩니다.



-1

이전 답변에서 알 수 있듯이 등급 막대의 색상을 변경하는 것은 쉽지 않습니다. 별은 프로그래밍 방식으로 그려지지 않으며 고정 된 크기와 특정 색상 그라디언트가있는 이미지입니다. 색상을 변경하려면 다른 색상으로 별표 이미지를 생성 한 다음 고유 한 드로어 블 XML 리소스를 만들고 setProgressDrawable (Drawable d) 또는 XML 속성 android : progressDrawable을 사용하여 ratingsBar 클래스로 전달해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.