Android RatingBar mengubah warna bintang [ditutup]


141

Bagaimana saya bisa mengubah warna dan ukuran bintang?


Saya pikir Anda harus membuat bilah peringkat kustom sendiri jika Anda ingin melakukannya
Donal Rafferty

Saya menulis posting blog yang menjelaskan cara mengubah gambar RatingBar: kozyr.zydako.net/2010/05/23/pretty-ratingbar Ini juga menunjukkan di mana Anda dapat menentukan ukuran gambar ...
kozyr

Saya berharap pertanyaan ini untuk bilah peringkat warna-warni seperti yang ditunjukkan di situs web, tidak dapat menemukannya sendiri. Membuat implementasi sederhana sendiri github.com/codebreaker/coloredratingbar-android . Semoga ini bisa membantu seseorang di luar sana.
jaga

Jawaban:


26

Langkah # 1: Buat gaya Anda sendiri, dengan mengkloning salah satu gaya yang ada (dari $ANDROID_HOME/platforms/$SDK/data/res/values/styles.xml), meletakkannya di proyek Anda sendiristyles.xml , dan merujuknya ketika Anda menambahkan widget ke tata letak.

Langkah # 2: Buat LayerDrawablesumber XML Anda sendiri untuk RatingBar, menunjuk ke gambar yang sesuai untuk digunakan untuk bar. Gaya asli akan mengarahkan Anda ke sumber daya yang ada yang dapat Anda bandingkan. Kemudian, sesuaikan gaya Anda untuk menggunakan LayerDrawablesumber daya Anda sendiri , daripada yang bawaan.


1
Per langkah # 2, Ini tidak berfungsi untuk perangkat Samsung 3 atau yang lainnya, ini tidak harus merupakan LayerDrawable. Lihat di sini untuk info: stackoverflow.com/questions/30266334/…
Kenny

6
Gunakan android: progressTint = "@ color / yellow". Lihat jawaban @superpuccio.
Vincent

2
progressTint hanya didukung di atas level 21 api
Yogesh Rathi


120

Agak rumit di blog yang disebutkan, saya sudah menggunakan cara yang serupa tapi lebih sederhana. Anda perlu 3 gambar bintang (red_star_full.png, red_star_half.png dan red_star_empty.png) dan satu xml, itu saja.

Letakkan 3 gambar ini di res / drawable.

Letakkan di sana ratingbar_red.xml berikut:

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

dan, akhirnya, beri tahu definisi ratingbar Anda untuk menggunakan ini, yaitu

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

Itu dia.


3
Halo Alex, saya sudah mencoba solusi ini tetapi ketika saya mencoba untuk mengatur peringkat ke sesuatu seperti 1.1, 1.2, dll ... itu ditampilkan sebagai 1,5. Saya telah mengambil 3 gambar bintang, satu kosong, satu setengah penuh dan satu lagi penuh. Saya kira itu seharusnya interpolasi di antara mereka untuk mendapatkan komponen fraksional, saya hanya ingin tahu apakah ada orang lain yang memiliki masalah yang sama atau apakah saya melakukan sesuatu yang salah?
Graham Baitson

Bisakah Anda menghubungi saya tentang gambar yang harus kami gunakan jika cuaca berwarna dan ukuran gambar tidak dapat menyelesaikan ini ...
Prithviraj Shiroor

1
Semua orang melihat jawaban pembaruan 2015 di bawah ini! Jauh lebih mudah dan sederhana!
katie

Jawaban ini masih memberikan lebih banyak fleksibilitas atas berbagai status bintang.
Tom Brinkkemper

Mengapa saya mendapatkan garis vertikal di bawah bintang? Saya mencoba mendefinisikan gaya khusus, menentukan ketinggian, tetapi masih ada garis-garis vertikal di bawah bintang pada AVD saya.
Aleksandar

93

Coba ini, jika Anda hanya ingin mengubah warna:

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

1
Apa sebenarnya PorterDuff.Mode.SRC_ATOPartinya atau apa yang dilakukan?
Zapnologica

5
Tidak bekerja di API 5.0 dan lebih tinggi. Kebutuhan:Drawable stars = rb.getProgressDrawable(); stars.setTint( Color.YELLOW );
zyamys

@zyamys Ini benar-benar menyebalkan = (Diperlukan metode untuk "versi yang lebih tinggi" dan metode lain untuk versi yang lebih lama?
Daniela Morais

1
Ini hanya bekerja untuk ketelitian 0,5. Jika tidak (presisi <0,5) hamparan menjadi aneh dan sepertinya warna biru masih dengan ketelitian 0,5 sedangkan kuning tepat
Teo Inke

1
Peringatan: Gangguan pada perangkat pra-lolipop. Pergilah dengan jawaban yang diterima.
blockwala

70

Cara termudah yang bekerja untuk saya ... jika Anda memperluas Aktivitas AppCompat

Di build.gradle Anda tambahkan pustaka appcompat terbaru.

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

Buat aktivitas Anda memperpanjang android.support.v7.app.AppCompatActivity

public class MainActivity extends AppCompatActivity {  
    ...
}

Nyatakan gaya khusus di file styles.xml Anda.

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

Terapkan gaya ini ke RatingBar Anda melalui atribut 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
Terima kasih @Vishal Kumar. Saya mencobanya di Kitkat 4.4.4 (Samsung S3 neo) dan Marshmallow 6.0.1 (Samsung Galaxy On Nxt), itu berhasil. Namun tidak berhasil di Lollipop 5.1 (Micromax). Untuk Lollipop saya menggunakan atribut "android: progressTint" di RatingBar dan ya itu berfungsi.
Prashant

Itu solusi terbaik.
Arhat Baid

Ini harus menjadi jawaban yang benar yang dipilih.
Hampel Előd

1
Ini solusi terbaik. Jika Anda ingin mengubah ukuran bintang, Anda bisa menggunakannya style="?android:ratingBarStyleSmall"bersama.
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> dan rating AndaBar android:theme="@style/RatingBarSmallTheme"
Zakhar Rodionov

47

Pembaruan 2015

Sekarang Anda dapat menggunakan DrawableCompat untuk mewarnai semua jenis drawable. Sebagai contoh:

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

Ini kompatibel ke belakang hingga API 4


Jangan lupa untuk mengatur drawable pada ratingBar.
meremas

15
Ini mewarnai keseluruhan gambar menjadi satu warna yang membuat bintang-bintang yang kosong sangat sulit untuk dibedakan.
blueice

Ini hanya berfungsi dengan perpustakaan dukungan android> = 22 dan tidak dengan perpustakaan dukungan <22.
Raghav Sharma

2
Ini menarik 5 bintang berwarna, bukan 3,5.
CoolMind

1
Saya hanya akan mengelilinginya dengan if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {}karena ini bekerja secara default dari API 22.
Yoann Hercouet

38

Dari API 21 , sangat mudah untuk mengubah warna bintang-bintang dengan tiga baris kode ini:

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

Melakukannya seperti ini, Anda akan berubah:

  • warna bintang yang diisi (progressTint)
  • warna bintang yang tidak terisi (progressBackgroundTint)
  • dan warna batas (secondaryProgressTint) dari bintang-bintang

Alih-alih 3,5 itu melukis 4 bintang.
CoolMind

@CoolMind set android: stepSize: 1 bukannya 0,5
eLemEnt

4
Bagaimana cara mengubah warna bintang kosong?
winklerrr

@winklerrr apakah Anda menemukan solusi cara mengubah warna bintang kosong.
Tarun Kumar

Tidak melakukan pengecekan lebih lanjut untuk menemukan solusi
winklerrr

36

Jika Anda ingin mengubah warna untuk semua bintang menyatakan Anda gunakan saya:

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

Apakah ada cara untuk mengatur warna bintang berdasarkan data yang diambil dari database? Katakanlah saya mendapat 5 bintang dan data yang dikembalikan dari basis data adalah 4. Jadi alih-alih mengubah semua 5, saya hanya mengubah 4 yang pertama

1
getColor sudah tidak digunakan lagi sekarang, ada alternatif lain?
Manohar Reddy

2
Anda dapat menemukan jawaban di sini stackoverflow.com/a/32202256/2513291 Misalnya, pendekatan ini ContextCompat.getColor (konteks, R.color.color_name)
Yuriy Vinogradov

berfungsi dengan baik, tetapi perhatikan bahwa, untuk beberapa alasan, urutannya penting (2, lalu 1, lalu 0). Saya mencoba sebaliknya dan itu menyebabkan beberapa gangguan UI saat pertama kali warna berubah.
Simon Ninon

25

Solusi yang diposkan Alex dan CommonsWares sudah benar. Satu hal yang tidak pernah dibicarakan oleh Android adalah ukuran piksel yang tepat untuk kepadatan yang berbeda. Berikut adalah dimensi yang diperlukan untuk setiap kerapatan berdasarkan cahaya halo.

Bintang Kecil

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

Bintang Sedang

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

Bintang Besar

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

dapatkah saya menggunakan vectordrawble dengan bintang
Mina Fawzy

24

Jadi saya telah berjuang dengan masalah ini selama dua jam dan saya telah datang dengan solusi yang berfungsi untuk semua versi API, di mana peringkat setengah bintang juga ditampilkan.

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

Anda memanggil metode dengan urutan drawable ini:

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

CATATAN: Anda juga harus menentukan atribut "max" dan "numStars" dalam XML, jika tidak setengah bintang tidak ditampilkan.


satu-satunya cara yang bekerja untuk saya di API19, tapi saya belum menyerah untuk mencari cara melakukan ini dari xml hanya T_T
Beeing Jk

@BeeingJk jika Anda membuat tampilan kustom yang memperluas RatingBar, Anda dapat membuat atribut xml Anda sendiri untuk menentukan warna warna. Anda kemudian memiliki satu titik kontrol untuk mengatur warna dan dapat menentukan warna dalam xml. Semoga itu bisa membantu! Dapat menjelaskan lebih banyak jika diperlukan
Forrest Bice

Mode.SRC_INatau Mode.MULTIPLY?
Dr.jacky

12

Sekarang Anda dapat menggunakan DrawableCompat dari appcompat v22.1.0 dan seterusnya untuk secara dinamis mewarnai semua jenis digambar, berguna ketika Anda mendukung beberapa tema dengan satu set digambar. Sebagai contoh:

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

Ini kompatibel ke bawah ke API 4. Juga lihat posting blog Chris Banes di Support Libraries v22.1.0

Untuk ukuran dan bentuk yang sebenarnya, Anda perlu menentukan gaya baru dan daftar gambar yang dapat digambar untuk ukuran yang sesuai, seperti yang sudah dijawab orang lain di atas.


Drawable bukan array, bagaimana Anda mengakses kemajuan [0]?
blueice

@blueice Maaf, Drawable harus menjadi LayerDrawable, diperbaiki sekarang, terima kasih.
Dan Dar3

Masih sepertinya tidak bekerja untuk saya, saya berakhir dengan apa yang Yuriy Vinogradov berikan dalam tanggapan berbeda terhadap pertanyaan ini dan itu sepertinya berhasil.
blueice

Bagaimana cara mengubah Drawable, bukan Change color?
Iman Marashi

@ImanMarashi Lihat jawaban berbasis Alex Alex di atas, LayerDrawable.setDrawable (indeks, drawable) hanya tersedia dari API23 dan seterusnya.
Dan Dar3

10

Gunakan android:themeatribut:

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

Untuk hanya mengubah warna Rating bar dari xml: -

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

itu tidak berubah warna bintang yang kosong
Nainal

7

Untuk mengubah warna, Anda hanya perlu mengatur parameter 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"
       />

Untuk ukuran properti gaya.


hanya berfungsi pada API 21 atau lebih tinggi, terima kasih
Junaid

5

Cara paling sederhana:

android:progressTint="@color/color"

1
Perhatikan bahwa ini hanya berfungsi pada api
21+

4

Membangun jawaban @ lgvalle.

Pembaruan 2015

Sekarang Anda dapat menggunakan DrawableCompat untuk mewarnai semua jenis drawable. Sebagai contoh:

Kemajuan yang dapat ditarik = ratingBar.getProgressDrawable (); DrawableCompat.setTint (progres, Color.WHITE); Ini kompatibel ke belakang hingga 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));

Ini akan menjaga warna langkah pecahan.


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

gunakan warna Anda sendiri


4

Tanpa menambahkan gaya baru, Anda dapat menggunakan warna rona di dalamnya 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

Bekerja untuk Android di bawah dan di atas versi 21

Setelah beberapa penelitian saya datang dengan metode ini untuk mengatur warna latar belakang, warna celah (misalnya: setengah bintang) dan warna warna bintang.

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

Solusi sederhana, gunakan AppCompatRatingBar dan metode setProgressTintList untuk mencapai ini, lihat jawaban ini untuk referensi.


Ini bekerja untuk saya di bawah API 28 menggunakan com.google.android.material: material: 1.1.0-alpha02
Mark Lapasa

2

Saya mengatasi masalah ini sebagai berikut:

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

Terima kasih, ini berhasil. Tetapi untuk peringkat fraksional bintang dicat seluruhnya.
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);

bagi saya ini berfungsi ....



1

Dengan menggunakan jawaban di atas, saya membuat metode statis cepat yang dapat dengan mudah digunakan kembali. Ini hanya bertujuan untuk mewarnai warna progres untuk bintang yang diaktifkan. Bintang-bintang yang tidak diaktifkan tetap berwarna abu-abu.

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

Cukup lewati bilah penilaian dan Warna Anda menggunakan getResources().getColor(R.color.my_rating_color)

Seperti yang Anda lihat, saya menggunakan DrawableCompat sehingga kompatibel dengan backward.

EDIT: Metode ini tidak berfungsi pada API21 (lihat gambar mengapa). Anda berakhir dengan NullPointerException saat memanggil setProgressBar. Saya akhirnya menonaktifkan seluruh metode pada API> = 21.

Untuk API> = 21, saya menggunakan solusi SupperPuccio.


java.lang.ClassCastException: android.support.v4.graphics.drawable.DrawableWrapperHoneycomb tidak dapat dilemparkan ke android.graphics.drawable.LayerDrawable di pre-lollipop
Ishaan Garg

1
@IshaanGarg Anda benar. Saya mengalami masalah yang sama dan memperbarui metode saya. Saya memperbarui kode saya untuk menangani kasus ini. Saya tidak berpikir ini masalah versi Android. Jika Anda menggunakan versi bar rating yang lebih kecil (dengan style = "? Android: attr / ratingBarStyleSmall"), maka drawable yang dikembalikan masih berupa LayoutDrawable.
JDenais

Yup, hanya apa yang telah saya terapkan, pastikan untuk menggunakan AppCompatRatingBar. Meskipun saya tidak bisa mendapatkan setengah bintang saat mengatur peringkat dari XML / java. Seperti setRating (3.5) menunjukkan 4 bintang penuh
Ishaan Garg

1

Rating bar digunakan secara otomatis pada waktu berjalan untuk mengubah warna pada bintang sentuh.

Pertama tambahkan gaya dalam file 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>

Kemudian bilah nilai Anda menambahkan tema seperti ini:

<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) nyatakan xml ini

<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) di 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) peringkat aktif --- ambil gambar dengan warna gelap karena akan digunakan sebagai transparansi warna untuk peringkat yang berbeda

rating_inactive - mengambil gambar dengan ukuran yang sama dari gambar di atas dengan latar belakang yang terang..itu akan digunakan ketika tidak ada peringkat yang dipilih


0

Cara yang sangat mudah untuk mengubah warna batas bintang adalah menggunakan parameter xml:

android:progressBackgroundTint=""

dalam tampilan ratingBar. Nilai harus berupa kode heksadesimal untuk suatu warna.


Saya tidak tahu mengapa, tetapi tampaknya metode Anda hanya memengaruhi batas bintang (warna isian tetap menjadi warna default)
superpuccio

Oke, Anda melewatkan beberapa xml params. Lihat jawaban saya di sini di bawah ini.
superpuccio

1
Kamu benar. Saya tidak tahu mengapa saya berpikir dia memiliki masalah dalam mengubah warna perbatasan bintang (mungkin karena jika saya punya masalah). Jawaban Anda lebih lengkap.
Pau Arlandis Martinez

0

Saya sedang mencari metode yang dapat diandalkan untuk melakukan ini hingga API 9 setidaknya. Solusi "casting to LayerDrawble" tampak seperti solusi berisiko bagi saya, dan ketika saya mengujinya pada ponsel Android pada 2.3, itu berhasil, tetapi panggilan ke DrawableCompat.setTint (...) tidak memiliki efek apa pun.

Kebutuhan untuk memuat aset yang dapat ditarik tampaknya juga bukan solusi yang baik bagi saya.

Saya memutuskan untuk membuat kode solusi saya sendiri yang merupakan kelas yang memperluas AppCompatRatingBar, menggunakan Drawable yang disesuaikan untuk menggambar bintang-bintang secara terprogram. Ini berfungsi dengan baik untuk kebutuhan saya, saya akan mempostingnya jika itu membantu siapa pun:

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

Tautan lebih mudah karena Anda bisa mendapatkan file lengkap secara langsung, tetapi di sini adalah kode lengkap untuk berjaga-jaga:

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

Jawabannya agak terlambat tapi saya harap ini akan membantu beberapa orang.

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

Dan inilah tampilan WhiteRatingStar

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

Dengan ini bintang-bintang akan berwarna putih misalnya.



-1

Seperti yang disiratkan oleh jawaban sebelumnya, tidak mudah untuk mengubah warna dari bar penilaian. Bintang-bintang tidak ditarik secara pemrograman, mereka adalah gambar dengan ukuran tetap dan gradien warna tertentu. Untuk mengubah warna Anda harus membuat gambar bintang Anda sendiri dengan warna yang berbeda kemudian lanjutkan untuk membuat sumber daya XML Anda sendiri yang dapat ditarik dan meneruskannya ke peringkat kelasBar menggunakan setProgressDrawable (Drawable d) atau XML atribut android: progressDrawable.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.