Android RatingBar thay đổi màu sao [đóng]


141

Làm cách nào để thay đổi màu sắc và kích thước của các ngôi sao?


Tôi nghĩ bạn phải tạo thanh xếp hạng tùy chỉnh của riêng mình nếu bạn muốn làm điều đó
Donal Rafferty

Tôi đã viết một bài đăng trên blog mô tả cách thay đổi hình ảnh RatingBar: kozyr.zydako.net/2010/05/23/pretty-ratingbar Nó cũng cho thấy nơi bạn có thể chỉ định kích thước hình ảnh ...
kozyr

Tôi đã hy vọng câu hỏi này dành cho thanh đánh giá nhiều màu như được hiển thị trong các trang web, không thể tìm thấy một câu hỏi cho riêng tôi. Tự tạo một triển khai đơn giản github.com/codebreaker/coloredratingbar-android . Hy vọng điều này sẽ giúp ai đó ngoài kia.
jaga

Câu trả lời:


26

Bước # 1: Tạo kiểu riêng của bạn, bằng cách sao chép một trong các kiểu hiện có (từ $ANDROID_HOME/platforms/$SDK/data/res/values/styles.xml), đặt nó vào dự án của riêng bạn styles.xmlvà tham chiếu nó khi bạn thêm tiện ích vào bố cục.

Bước # 2: Tạo LayerDrawabletài nguyên XML của riêng bạn cho RatingBar, chỉ vào hình ảnh phù hợp để sử dụng cho thanh. Các kiểu ban đầu sẽ chỉ cho bạn các tài nguyên hiện có mà bạn có thể so sánh với. Sau đó, điều chỉnh phong cách của bạn để sử dụng LayerDrawabletài nguyên của riêng bạn , thay vì các tài nguyên tích hợp.


1
Theo bước 2, Điều này không hoạt động đối với các thiết bị Samsung 3 hoặc một số thiết bị khác, điều này không bắt buộc phải là LayerDrawable. Xem tại đây để biết thông tin: stackoverflow.com/questions/30266334/ Kẻ
Kenny

6
Sử dụng android: ProgressTint = "@ color / yellow". Xem câu trả lời của @superpuccio.
Vincent

2
ProgressTint chỉ hỗ trợ trên 21 cấp độ api
Yogesh Rathi

Đây là giải pháp tốt nhất: stackoverflow.com/a/36297738/1935135
André Luiz Reis

120

Có một chút phức tạp tại blog được đề cập, tôi đã sử dụng một cách tương tự nhưng đơn giản hơn. Bạn cần hình ảnh 3 sao (red_star_full.png, red_star_half.png và red_star_empty.png) và một xml, đó là tất cả.

Đặt 3 hình ảnh này ở độ phân giải / vẽ.

Đặt ở đó ratingbar_red.xml sau đây:

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

và cuối cùng, cho biết định nghĩa thanh đánh giá của bạn để sử dụng điều này, tức là

<RatingBar android:progressDrawable="@drawable/ratingbar_red"/>

Đó là nó.


3
Xin chào Alex, tôi đã thử giải pháp này nhưng khi tôi cố gắng đặt xếp hạng thành 1.1, 1.2, v.v ... nó sẽ hiển thị là 1.5. Tôi đã chụp 3 ảnh sao, một trống, một nửa đầy và một đầy. Tôi cho rằng cần phải nội suy giữa chúng để có được các thành phần phân số, tôi chỉ tự hỏi có ai khác có cùng một vấn đề hay tôi đang làm gì đó sai đáng chú ý?
Graham Baitson

Bạn có thể vui lòng gọi cho tôi về những hình ảnh chúng ta nên sử dụng trong thời tiết không, hình ảnh màu và kích thước của hình ảnh tôi không thể giải quyết điều này ...
Prithviraj Shiroor 27/08/2015

1
Mọi người hãy xem câu trả lời cập nhật 2015 dưới đây! Nó dễ dàng và đơn giản hơn nhiều!
katie

Câu trả lời này vẫn cung cấp sự linh hoạt hơn các trạng thái khác nhau của các ngôi sao.
Tom Brinkkemper

Tại sao tôi nhận được các đường thẳng đứng dưới các ngôi sao? Tôi đã thử xác định kiểu tùy chỉnh, chỉ định chiều cao, nhưng vẫn có các đường thẳng đứng bên dưới các ngôi sao trên AVD của tôi.
Aleksandar

93

Hãy thử điều này, nếu bạn chỉ muốn thay đổi màu sắc:

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

1
Chính xác thì PorterDuff.Mode.SRC_ATOPcó nghĩa là gì hay làm gì?
Zapnologica

5
Không hoạt động trên API 5.0 trở lên. Nhu cầu:Drawable stars = rb.getProgressDrawable(); stars.setTint( Color.YELLOW );
zyamys

@zyamys Điều này thực sự hấp dẫn = (Một phương pháp cho "phiên bản cao hơn" và một phương pháp khác cho các phiên bản cũ là cần thiết?
Daniela Morais

1
Nó chỉ hoạt động với độ chính xác 0,5. Mặt khác (độ chính xác <0,5) lớp phủ trở nên kỳ lạ và có vẻ như màu xanh lam vẫn có độ chính xác là 0,5 trong khi màu vàng là chính xác
Teo Inke

1
Cảnh báo: Sự cố trên thiết bị pre-lolipop. Đi với câu trả lời được chấp nhận.
blockwala

70

Cách dễ nhất có hiệu quả với tôi ... nếu bạn đang mở rộng Hoạt động AppCompat

Trong build.gradle của bạn thêm thư viện appcompat mới nhất.

dependencies {  
    compile 'com.android.support:appcompat-v7:X.X.X' // where X.X.X version
}

Làm cho hoạt động của bạn mở rộng android.support.v7.app.AppCompatActivity

public class MainActivity extends AppCompatActivity {  
    ...
}

Khai báo kiểu tùy chỉnh trong tệp kiểu tệp của bạn.

<style name="RatingBar" parent="Theme.AppCompat">  
    <item name="colorControlNormal">@color/indigo</item>
    <item name="colorControlActivated">@color/pink</item>
</style>  

Áp dụng kiểu này cho RatingBar của bạn thông qua thuộc tính android: theme.

<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
Cảm ơn @Vishal Kumar. Tôi đã thử nó trên Kitkat 4.4.4 (Samsung S3 neo) và Marshmallow 6.0.1 (Samsung Galaxy On Nxt), nó đã hoạt động. Nhưng không thành công trên Lollipop 5.1 (Micromax). Đối với Lollipop, tôi đã sử dụng thuộc tính "android: ProgressTint" trong RatingBar và nó hoạt động.
Prashant

Đó là giải pháp tốt nhất.
Arhat Baid

Đây phải là câu trả lời đúng được chọn.
Hampel Előd

1
Đây là giải pháp tốt nhất. Nếu bạn muốn thay đổi kích thước sao, bạn có thể sử dụng style="?android:ratingBarStyleSmall"cùng nhau.
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> và xếp hạng của bạnBar android:theme="@style/RatingBarSmallTheme"
Zakhar Rodionov

47

Cập nhật 2015

Bây giờ bạn có thể sử dụng DrawableCompat để tô màu tất cả các loại drawable. Ví dụ:

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

Điều này tương thích ngược với API 4


Đừng quên đặt lại drawable trên ratingBar.
vắt

15
Điều này gợi ý toàn bộ có thể vẽ thành một màu khiến các ngôi sao trống rất khó phân biệt.
blueice

Điều này chỉ hoạt động với thư viện hỗ trợ Android> = 22 và không hoạt động với thư viện hỗ trợ <22.
Raghav Sharma

2
Nó vẽ 5 ngôi sao màu, không phải 3,5.
CoolMind

1
Tôi sẽ chỉ bao quanh điều đó if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {}vì nó hoạt động theo mặc định từ API 22.
Yoann Hercouet

38

Từ API 21 trở đi, thật dễ dàng để thay đổi màu sắc của các ngôi sao với ba dòng mã này:

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

Làm như thế này, bạn sẽ thay đổi:

  • màu sao đầy (ProgressTint)
  • màu sao chưa được lấp đầy (ProgressBackgroundTint)
  • và màu đường viền (juniorProTHERTint) của các ngôi sao

Thay vì 3,5 nó vẽ 4 sao.
CoolMind

@CoolMind đặt android: stepSize: 1 thay vì 0,5
eLemEnt

4
Làm thế nào để thay đổi màu sắc của một ngôi sao trống?
winklerrr

@winklerrr bạn đã tìm ra giải pháp làm thế nào để thay đổi màu sắc của một ngôi sao trống.
Tarun Kumar

Không kiểm tra thêm để tìm giải pháp
winklerrr

36

Nếu bạn muốn thay đổi màu sắc cho tất cả các ngôi sao, hãy sử dụng:

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

Có cách nào để đặt màu sao dựa trên dữ liệu được tìm nạp từ cơ sở dữ liệu không? Hãy nói rằng tôi có 5 ngôi sao và các dữ liệu trả về từ cơ sở dữ liệu là 4. Vì vậy, thay vì thay đổi tất cả 5, tôi chỉ thay đổi người đầu tiên 4

1
getColor bị phản đối bây giờ, thay thế nào?
Manohar Reddy

2
Bạn có thể tìm thấy câu trả lời ở đây stackoverflow.com/a/32202256/2513291 Ví dụ: phương pháp này ContextCompat.getColor (bối cảnh, R.color.color_name)
Yuriy Vinogradov

hoạt động tốt, nhưng lưu ý rằng, vì một số lý do, thứ tự là quan trọng (2, sau đó 1, sau đó 0). Tôi đã thử đảo ngược và nó dẫn đến một số giao diện người dùng bị trục trặc khi lần đầu tiên màu sắc được thay đổi.
Simon Ninon

25

Các giải pháp mà Alex và CommonsWares đã đăng là chính xác. Một điều mà Android không bao giờ nói về mặc dù là kích thước pixel phù hợp cho các mật độ khác nhau. Dưới đây là các kích thước cần thiết cho mỗi mật độ dựa trên ánh sáng quầng.

Ngôi sao nhỏ

mdpi: 16px
hdpi: 24px
xhdpi: 32px
xxhdpi: 48px

Sao trung bình

mdpi: 24px
hdpi: 36px
xhdpi: 48px
xxhdpi: 72px

Ngôi sao lớn

mdpi: 35px
hdpi: 52px
xhdpi: 69px
xxhdpi: 105px

Tôi có thể sử dụng vectordrawble với các ngôi sao
Mina Fawzy

24

Vì vậy, tôi đã vật lộn với vấn đề này trong hai giờ và tôi đã đưa ra một giải pháp hoạt động cho tất cả các phiên bản API, trong đó xếp hạng một nửa sao cũng được hiển thị.

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

Bạn gọi phương thức với thứ tự này của drawables:

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

LƯU Ý: Ngoài ra, bạn phải chỉ định các thuộc tính "max" và "numStars" trong XML, nếu không thì nửa sao không được hiển thị.


cách duy nhất phù hợp với tôi trên API19, nhưng tôi đã không từ bỏ để tìm cách làm điều này từ xml chỉ T_T
Beeing Jk

@BeeingJk nếu bạn tạo chế độ xem tùy chỉnh mở rộng RatingBar, bạn có thể tạo các thuộc tính xml của riêng mình để chỉ định màu sắc. Sau đó, bạn có một điểm kiểm soát duy nhất để đặt màu và có thể chỉ định màu trong xml. Mong rằng sẽ giúp! Có thể giải thích thêm nếu cần
Forrest Bice

Mode.SRC_INhay Mode.MULTIPLY?
Dr.jacky

12

Bây giờ bạn có thể sử dụng DrawableCompat từ AppCompat v22.1.0 trở đi để tự động điều chỉnh tất cả các loại hình vẽ, hữu ích khi bạn hỗ trợ nhiều chủ đề với một bộ có thể vẽ được. Ví dụ:

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

Điều này tương thích ngược với API 4. Cũng xem bài đăng trên blog của Chris Banes trên Thư viện hỗ trợ v22.1.0

Đối với kích thước và hình dạng thực tế, bạn sẽ cần xác định kiểu dáng mới và các biểu đồ danh sách lớp cho kích thước phù hợp, như những người khác đã trả lời ở trên.


Drawables không phải là mảng làm thế nào bạn truy cập tiến trình [0]?
blueice

@blueice Bạn xin lỗi, Drawable phải là một LayerDrawable, được sửa ngay bây giờ, cảm ơn.
Dan Dar3

Vẫn không có vẻ hiệu quả với tôi, tôi đã kết thúc với những gì Yuriy Vinogradov đưa ra một câu trả lời khác cho câu hỏi này và điều đó dường như có hiệu quả.
blueice

Làm thế nào để thay đổi Drawable thay vì thay đổi màu sắc?
Iman Marashi

@ImanMarashi Xem câu trả lời dựa trên XML của Alex ở trên, LayerDrawable.setDrawable (index, drawable) chỉ có sẵn từ API23 trở đi.
Dan Dar3 15/03/2016

10

Sử dụng android:themethuộc tính:

kiểu tệp

<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

Để chỉ thay đổi màu của thanh Xếp hạng từ xml: -

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

nó không thay đổi màu sao trống
Nainal

7

Để thay đổi màu sắc, bạn chỉ cần đặt tham số 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"
       />

Đối với kích thước tài sản phong cách.


chỉ hoạt động trên API 21 trở lên, cảm ơn
Junaid

5

Cách đơn giản nhất:

android:progressTint="@color/color"

1
Lưu ý rằng điều này chỉ hoạt động trên api 21+
Ixx

4

Xây dựng câu trả lời @ lgvalle.

Cập nhật 2015

Bây giờ bạn có thể sử dụng DrawableCompat để tô màu tất cả các loại drawable. Ví dụ:

Tiến trình có thể rút ra = ratingBar.getProTHERDrawable (); DrawableCompat.setTint (tiến trình, Color.WHITE); Điều này tương thích ngược với 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));

Điều này sẽ giữ cho các bước phân số màu sắc.


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

sử dụng màu của riêng bạn


4

Không thêm phong cách mới, bạn có thể sử dụng màu sắc trong 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

Hoạt động cho Android bên dưới và phiên bản 21

Sau một số nghiên cứu, tôi đã đưa ra phương pháp này để thiết lập tông màu nền, khoảng cách màu (ví dụ: nửa sao) và màu sắc sao.

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

Giải pháp đơn giản, sử dụng AppCompatRatingBar và phương thức setProTHERTintList của nó để đạt được điều này, xem câu trả lời này để tham khảo.


Điều này hoạt động với tôi theo API 28 bằng cách sử dụng com.google.android.m Liệu: liệu: 1.1.0-alpha02
Mark Lapasa

2

Tôi giải quyết vấn đề này như sau:

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

Cảm ơn, nó hoạt động. Nhưng đối với các ngôi sao xếp hạng phân số được sơn toàn bộ.
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);

cho tôi nó hoạt động ....


1

Tôi tìm thấy một giải pháp đơn giản để thay đổi màu sắc của ngôi sao theo chủ đề của bạn.

Xem trang này: http://android-holo-colors.com/

Chọn màu chủ đề của bạn và tạo hình ảnh ngôi sao của bạn.


1

Sử dụng các câu trả lời ở trên, tôi đã tạo ra một phương thức tĩnh nhanh có thể dễ dàng sử dụng lại. Nó chỉ nhằm mục đích pha màu tiến độ cho các ngôi sao được kích hoạt. Những ngôi sao không được kích hoạt vẫn có màu xám.

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

Chỉ cần vượt qua thanh đánh giá của bạn và sử dụng màu getResources().getColor(R.color.my_rating_color)

Như bạn có thể thấy, tôi sử dụng DrawableCompat để nó tương thích ngược.

EDIT: Phương pháp này không hoạt động trên API21 (xem tại sao). Bạn kết thúc với một NullPulumException khi gọi setProTHERBar. Tôi đã kết thúc việc vô hiệu hóa toàn bộ phương thức trên API> = 21.

Đối với API> = 21, tôi sử dụng giải pháp SupperPuccio.


java.lang.ClassCastException: android.support.v4.graphics.drawable.DrawableWrapperHoneycomb không thể được chuyển thành android.graphics.drawable.LayerDrawable trên pre-leets
Ishaan Garg

1
@IshaanGarg bạn nói đúng. Tôi gặp vấn đề tương tự và cập nhật phương pháp của tôi. Tôi đã cập nhật mã của tôi để xử lý trường hợp. Tôi không nghĩ đó là vấn đề của phiên bản Android. Nếu bạn sử dụng phiên bản nhỏ hơn của thanh xếp hạng (với style = "? Android: attr / ratingBarStyleSmall"), thì bản vẽ có thể rút ra vẫn là một LayoutDrawable.
JDenais

Yup, đúng như những gì tôi đã triển khai, chỉ cần chắc chắn sử dụng AppCompatRatingBar. Mặc dù tôi không thể có được một nửa sao khi cài đặt trước xếp hạng từ XML / java. Giống như setRating (3.5) hiển thị 4 ngôi sao đầy đủ
Ishaan Garg

1

Thanh đánh giá được sử dụng tự động trong thời gian chạy để thay đổi màu sắc trên ngôi sao cảm ứng.

Đầu tiên thêm kiểu trong tệp ứng dụng \ src \ main \ res \ value \ 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>

Sau đó, thanh đánh giá của bạn thêm chủ đề như thế này:

<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) khai báo xml này

<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) trong style.xml

<style name="coloredRatingBarStyleSmall">
        <item name="indicator">false</item>
        <item name="type">small</item>
    </style>

3)

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) xếp hạng hoạt động --- chụp bất kỳ hình ảnh nào có màu tối vì nó sẽ được sử dụng làm độ trong suốt của màu cho các xếp hạng khác nhau

rating_inactive - lấy bất kỳ hình ảnh nào có cùng kích thước của hình ảnh trên với nền sáng..tôi sẽ được sử dụng khi không có xếp hạng nào được chọn


0

Một cách rất dễ dàng để thay đổi màu đường viền của các ngôi sao là sử dụng tham số xml:

android:progressBackgroundTint=""

trong khung nhìn ratingBar. Giá trị phải là mã thập lục phân cho một màu.


Tôi không biết tại sao, nhưng có vẻ như phương pháp của bạn chỉ ảnh hưởng đến đường viền của các ngôi sao (màu lấp đầy vẫn là màu mặc định)
superpuccio

Ok, bạn đã bỏ lỡ một số thông số xml. Kiểm tra câu trả lời của tôi ở đây dưới đây.
superpuccio

1
Bạn đúng. Tôi không biết tại sao tôi lại nghĩ anh ta có vấn đề khi thay đổi màu đường viền của ngôi sao (có lẽ vì nếu tôi gặp vấn đề). Câu trả lời của bạn đầy đủ hơn.
Pau Arlandis Martinez 1/15

0

Tôi đã tìm kiếm một phương pháp đáng tin cậy để thực hiện điều này hoàn toàn theo API 9. Giải pháp "truyền tới LayerDrawble" có vẻ như là một giải pháp rủi ro đối với tôi và khi tôi thử nghiệm nó trên điện thoại Android vào ngày 2.3, nó đã thực hiện thành công nhưng cuộc gọi tới DrawableCompat.setTint (...) không có tác dụng.

Nhu cầu tải tài sản có thể rút ra dường như cũng không phải là một giải pháp tốt cho tôi.

Tôi quyết định mã hóa giải pháp của riêng mình, đó là một lớp mở rộng AppCompatRatingBar, sử dụng một Drawable tùy chỉnh để chăm sóc việc vẽ các ngôi sao theo lập trình. Nó hoạt động hoàn hảo cho nhu cầu của tôi, tôi sẽ đăng nó trong trường hợp nó giúp được bất cứ ai:

https://gist.github.com/androidseb/2b8044c90a07c7a52b4bbff3453c8460

Liên kết dễ dàng hơn vì bạn có thể lấy tệp đầy đủ trực tiếp, nhưng đây là mã đầy đủ chỉ trong trường hợp:

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

Một câu trả lời hơi muộn nhưng tôi hy vọng nó sẽ giúp một số người.

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

Và đây là những gì WhiteRatingStar trông giống như

<style name="WhiteRatingStar" parent="Base.Widget.AppCompat.RatingBar.Small">
     <item name="colorAccent">@android:color/white</item>
</style>

Với điều này, các ngôi sao sẽ được tô màu trắng chẳng hạn.



-1

Như câu trả lời trước ngụ ý, không dễ để thay đổi màu của thanh đánh giá. Các ngôi sao không được vẽ theo chương trình, chúng là những hình ảnh có kích thước cố định và độ dốc màu cụ thể. Để thay đổi màu sắc, bạn phải tạo các hình ảnh ngôi sao của riêng mình bằng các màu khác nhau, sau đó tiến hành tạo tài nguyên XML có thể vẽ của riêng bạn và chuyển nó đến lớp xếp hạng bằng cách sử dụng setProTHERDrawable (Drawable d) hoặc thuộc tính XML android: ProgressDrawable.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.