How to create Custom Ratings bar in Android

前端 未结 13 1230
故里飘歌
故里飘歌 2020-11-22 06:28

Hello all i need to perform Ratings in my application... SO i need to create custom Ratings bar... Can Anyone Help me in this?

相关标签:
13条回答
  • 2020-11-22 07:01

    You can try this rating bar with much better animations

    SmileyRating

    0 讨论(0)
  • 2020-11-22 07:06

    You can create custom material rating bar by defining drawable xml using material icon of your choice and then applying custom drawable to rating bar using progressDrawable attribute.

    For infomration about customizing rating bar see http://www.zoftino.com/android-ratingbar-and-custom-ratingbar-example

    Below drawable xml uses thumbs up icon for rating bar.

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:id="@android:id/background">
            <bitmap
                android:src="@drawable/thumb_up"
                android:tint="?attr/colorControlNormal" />
        </item>
        <item android:id="@android:id/secondaryProgress">
            <bitmap
                android:src="@drawable/thumb_up"
                android:tint="?attr/colorControlActivated" />
        </item>
        <item android:id="@android:id/progress">
            <bitmap
                android:src="@drawable/thumb_up"
                android:tint="?attr/colorControlActivated" />
        </item>
    </layer-list>
    
    0 讨论(0)
  • 2020-11-22 07:06

    You can have 5 imageview with defalut image as star that is empty and fill the rating bar with half or full image base on rating.

     public View getView(int position, View convertView, ViewGroup parent) {
         LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         View grid=inflater.inflate(R.layout.griditem, parent, false);
         imageView=(ImageView)grid.findViewById(R.id.grid_prod);
         imageView.setImageResource(imgId[position]);
         imgoff =(ImageView)grid.findViewById(R.id.offer);
         tv=(TextView)grid.findViewById(R.id.grid_text);
         tv.setText(namesArr[position]);
         tv.setTextColor(Color.BLACK);
         tv.setPadding(0, 2, 0, 0);
       sta=(ImageView)grid.findViewById(R.id.imageView);
        sta1=(ImageView)grid.findViewById(R.id.imageView1);
        sta2=(ImageView)grid.findViewById(R.id.imageView2);
        sta3=(ImageView)grid.findViewById(R.id.imageView3);
        sta4=(ImageView)grid.findViewById(R.id.imageView4);
        Float rate=rateFArr[position];
    
    
       if(rate==5 || rate==4.5)
        {
            sta.setImageResource(R.drawable.full__small);
            sta1.setImageResource(R.drawable.full__small);
            sta2.setImageResource(R.drawable.full__small);
            sta3.setImageResource(R.drawable.full__small);
            if(rate==4.5)
            {
                sta4.setImageResource(R.drawable.half_small);
            }
            else
            {
                sta4.setImageResource(R.drawable.full__small);
            }
        }
        if(rate==4 || rate==3.5)
        {
            sta.setImageResource(R.drawable.full__small);
            sta1.setImageResource(R.drawable.full__small);
            sta2.setImageResource(R.drawable.full__small);
         if(rate==3.5)
            {
                sta3.setImageResource(R.drawable.half_small);
            }
            else
            {
                sta3.setImageResource(R.drawable.full__small);
            }
        }
        if(rate==3 || rate==2.5)
        {
            sta.setImageResource(R.drawable.full__small);
            sta1.setImageResource(R.drawable.full__small);
           if(rate==2.5)
            {
                sta2.setImageResource(R.drawable.half_small);
            }
            else
            {
                sta2.setImageResource(R.drawable.full__small);
            }
        }
        if(rate==2 || rate==1.5)
        {
        sta.setImageResource(R.drawable.full__small);
         if(rate==1.5)
            {
                sta1.setImageResource(R.drawable.half_small);
            }
            else
            {
                sta1.setImageResource(R.drawable.full__small);
            }
        }
        if(rate==1 || rate==0.5)
        {
            if(rate==1)
            sta.setImageResource(R.drawable.full__small);
            else
                sta.setImageResource(R.drawable.half_small);
    
        }
        if(rate>5)
        {
            sta.setImageResource(R.drawable.full__small);
            sta1.setImageResource(R.drawable.full__small);
            sta2.setImageResource(R.drawable.full__small);
            sta3.setImageResource(R.drawable.full__small);
            sta4.setImageResource(R.drawable.full__small);
        }
    
        // rb=(RatingBar)findViewById(R.id.grid_rating);
         //rb.setRating(rateFArr[position]);
            return grid;
        }
    
    0 讨论(0)
  • 2020-11-22 07:08

    For SVG RatingBar I used RatingBar custom Vector Drawables superimposing and the answer of erdomester here. This solution traverses all drawables inside SvgRatingBar view of your layout, so in RecyclerView it has an overhead.

    SvgRatingBar.java:

    import android.annotation.SuppressLint;
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapShader;
    import android.graphics.Canvas;
    import android.graphics.Shader;
    import android.graphics.drawable.BitmapDrawable;
    import android.graphics.drawable.ClipDrawable;
    import android.graphics.drawable.Drawable;
    import android.graphics.drawable.LayerDrawable;
    import android.graphics.drawable.ShapeDrawable;
    import android.graphics.drawable.VectorDrawable;
    import android.graphics.drawable.shapes.RoundRectShape;
    import android.graphics.drawable.shapes.Shape;
    import android.os.Build;
    import android.support.graphics.drawable.VectorDrawableCompat;
    import android.support.v7.graphics.drawable.DrawableWrapper;
    import android.support.v7.widget.AppCompatRatingBar;
    import android.util.AttributeSet;
    import android.view.Gravity;
    
    public class SvgRatingBar extends AppCompatRatingBar {
    
        private Bitmap sampleTile;
    
        public SvgRatingBar(Context context) {
            this(context, null);
        }
    
        public SvgRatingBar(Context context, AttributeSet attrs) {
            this(context, attrs, android.support.v7.appcompat.R.attr.ratingBarStyle);
        }
    
        public SvgRatingBar(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        private void init() {
            LayerDrawable drawable = (LayerDrawable) createTile(getProgressDrawable(), false);
            setProgressDrawable(drawable);
        }
    
        /**
         * Converts a drawable to a tiled version of itself. It will recursively
         * traverse layer and state list drawables.
         */
        @SuppressLint("RestrictedApi")
        private Drawable createTile(Drawable drawable, boolean clip) {
            if (drawable instanceof DrawableWrapper) {
                Drawable inner = ((DrawableWrapper) drawable).getWrappedDrawable();
                if (inner != null) {
                    inner = createTile(inner, clip);
                    ((DrawableWrapper) drawable).setWrappedDrawable(inner);
                }
            } else if (drawable instanceof LayerDrawable) {
                LayerDrawable background = (LayerDrawable) drawable;
                final int n = background.getNumberOfLayers();
                Drawable[] outDrawables = new Drawable[n];
    
                for (int i = 0; i < n; i++) {
                    int id = background.getId(i);
                    outDrawables[i] = createTile(background.getDrawable(i),
                            (id == android.R.id.progress || id == android.R.id.secondaryProgress));
                }
                LayerDrawable newBg = new LayerDrawable(outDrawables);
    
                for (int i = 0; i < n; i++) {
                    newBg.setId(i, background.getId(i));
                }
    
                return newBg;
    
            } else if (drawable instanceof BitmapDrawable) {
                final BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
                final Bitmap tileBitmap = bitmapDrawable.getBitmap();
                if (sampleTile == null) {
                    sampleTile = tileBitmap;
                }
    
                final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
                final BitmapShader bitmapShader = new BitmapShader(tileBitmap,
                        Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
                shapeDrawable.getPaint().setShader(bitmapShader);
                shapeDrawable.getPaint().setColorFilter(bitmapDrawable.getPaint().getColorFilter());
                return (clip) ? new ClipDrawable(shapeDrawable, Gravity.START,
                        ClipDrawable.HORIZONTAL) : shapeDrawable;
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && drawable instanceof VectorDrawable) {
                return createTile(getBitmapDrawableFromVectorDrawable(drawable), clip);
            } else if (drawable instanceof VectorDrawableCompat) {
                // API 19 support.
                return createTile(getBitmapDrawableFromVectorDrawable(drawable), clip);
            }
            return drawable;
        }
    
        private BitmapDrawable getBitmapDrawableFromVectorDrawable(Drawable drawable) {
            Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
            drawable.draw(canvas);
            return new BitmapDrawable(getResources(), bitmap);
        }
    
        @Override
        protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            if (sampleTile != null) {
                final int width = sampleTile.getWidth() * getNumStars();
                setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, 0),
                        getMeasuredHeight());
            }
        }
    
        private Shape getDrawableShape() {
            final float[] roundedCorners = new float[]{5, 5, 5, 5, 5, 5, 5, 5};
            return new RoundRectShape(roundedCorners, null, null);
        }
    }
    

    In your layout:

    <com.example.common.control.SvgRatingBar
        android:id="@+id/rate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:minHeight="13dp"
        android:numStars="5"
        android:progressDrawable="@drawable/rating_bar"
        android:rating="3.5"
        android:stepSize="0.01"
        />
    

    You also have to create rating_bar.xml with two SVG drawables:

    <?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/ic_unfilled_star"
            />
    
        <item
            android:id="@android:id/secondaryProgress"
            android:drawable="@drawable/ic_unfilled_star"
            />
    
        <item
            android:id="@android:id/progress"
            android:drawable="@drawable/ic_filled_star"
            />
    
    </layer-list>
    

    In Kotlin.

    import android.annotation.SuppressLint
    import android.content.Context
    import android.graphics.Bitmap
    import android.graphics.BitmapShader
    import android.graphics.Canvas
    import android.graphics.Shader
    import android.graphics.drawable.*
    import android.graphics.drawable.shapes.RoundRectShape
    import android.os.Build
    import android.util.AttributeSet
    import android.view.Gravity
    import androidx.appcompat.R
    import androidx.appcompat.graphics.drawable.DrawableWrapper
    import androidx.appcompat.widget.AppCompatRatingBar
    import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat
    
    class SvgRatingBar @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null,
                                                 defStyleAttr: Int = R.attr.ratingBarStyle) :
        AppCompatRatingBar(context, attrs, defStyleAttr) {
    
        private var sampleTile: Bitmap? = null
        private val roundedCorners = floatArrayOf(5f, 5f, 5f, 5f, 5f, 5f, 5f, 5f)
        private val roundRectShape = RoundRectShape(roundedCorners, null, null)
    
        init {
            progressDrawable = createTile(progressDrawable, false) as LayerDrawable
        }
    
        /**
         * Converts a drawable to a tiled version of itself. It will recursively
         * traverse layer and state list drawables.
         */
        private fun createTile(drawable: Drawable, clip: Boolean): Drawable =
            when {
                drawable is DrawableWrapper -> {
                    @SuppressLint("RestrictedApi")
                    var inner = drawable.wrappedDrawable
                    if (inner != null) {
                        inner = createTile(inner, clip)
                        @SuppressLint("RestrictedApi")
                        drawable.wrappedDrawable = inner
                    }
                    drawable
                }
                drawable is LayerDrawable -> {
                    val n = drawable.numberOfLayers
                    val outDrawables = arrayOfNulls<Drawable>(n)
                    for (i in 0 until n) {
                        val id = drawable.getId(i)
                        outDrawables[i] = createTile(drawable.getDrawable(i),
                            id == android.R.id.progress || id == android.R.id.secondaryProgress)
                    }
                    val newBg = LayerDrawable(outDrawables)
                    for (i in 0 until n) {
                        newBg.setId(i, drawable.getId(i))
                    }
                    newBg
                }
                drawable is BitmapDrawable -> {
                    val tileBitmap = drawable.bitmap
                    if (sampleTile == null) {
                        sampleTile = tileBitmap
                    }
                    val bitmapShader = BitmapShader(tileBitmap, Shader.TileMode.REPEAT,
                        Shader.TileMode.CLAMP)
                    val shapeDrawable = ShapeDrawable(roundRectShape).apply {
                        paint.shader = bitmapShader
                        paint.colorFilter = drawable.paint.colorFilter
                    }
                    if (clip) ClipDrawable(shapeDrawable, Gravity.START, ClipDrawable.HORIZONTAL)
                    else shapeDrawable
                }
                Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && drawable is VectorDrawable -> {
                    createTile(getBitmapDrawableFromVectorDrawable(drawable), clip)
                }
                drawable is VectorDrawableCompat -> {
                    // Pre-Lollipop support.
                    createTile(getBitmapDrawableFromVectorDrawable(drawable), clip)
                }
                else -> drawable
            }
    
        private fun getBitmapDrawableFromVectorDrawable(drawable: Drawable): BitmapDrawable {
            val bitmap = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight,
                Bitmap.Config.ARGB_8888)
            val canvas = Canvas(bitmap)
            drawable.setBounds(0, 0, canvas.width, canvas.height)
            drawable.draw(canvas)
            return BitmapDrawable(resources, bitmap)
        }
    
        @Synchronized override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec)
            if (sampleTile != null) {
                val width = sampleTile!!.width * numStars
                setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, 0),
                    measuredHeight)
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 07:12

    I made something simular, a RatingBar with individual rating icons, I'm using VectorDrawables for the rating icons but you could use any type of drawable

    https://github.com/manmountain/emoji-ratingbar

    0 讨论(0)
  • 2020-11-22 07:13

    I need to add my solution which is WAY eaiser than the one above. We don't even need to use styles.

    Create a selector file in the drawable folder:

    custom_ratingbar_selector.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/star_off" />
    
     <item android:id="@android:id/secondaryProgress"
        android:drawable="@drawable/star_off" />
    
     <item android:id="@android:id/progress"
        android:drawable="@drawable/star_on" />
    
    </layer-list>
    

    In the layout set the selector file as progressDrawable:

     <RatingBar
            android:id="@+id/ratingBar2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="20dp"
            android:progressDrawable="@drawable/custom_ratingbar_selector"
            android:numStars="8"
            android:stepSize="0.2"
            android:rating="3.0" />
    

    And that's all we need.

    0 讨论(0)
提交回复
热议问题