ShapeDrawable as progressDrawable for RatingBar in Android?

前端 未结 4 1239
广开言路
广开言路 2021-01-01 07:02

It seems I cannot set ShapeDrawable as progressDrawable for Ratingbar. I tried the following but failed:



        
4条回答
  •  醉梦人生
    2021-01-01 07:29

    Shape XML Drawables + RatingBar a complete mess.

    This is as close as I could get to a solution without writing a whole new class.

    My extended class builds the progress drawable correctly for the ProgressBar clamping it as required.

    Replace your empty and full states with the ones I've prepopulated. Not very flexible at the moment, you could easily abstract the setting of empty/full star states.

    /**
     * Created by chris on 28/08/2014.
     * For Yoyo-Android.
     */
    public class ShapeDrawableRatingBar extends RatingBar {
    
    
        /**
         * TileBitmap to base the width off of.
         */
        @Nullable
        private Bitmap mSampleTile;
    
        public ShapeDrawableRatingBar(final Context context, final AttributeSet attrs) {
            super(context, attrs);
            setProgressDrawable(createProgressDrawable());
        }
    
        @Override
        protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            if (mSampleTile != null) {
                final int width = mSampleTile.getWidth() * getNumStars();
                setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, 0),
                        getMeasuredHeight());
            }
        }
    
        protected LayerDrawable createProgressDrawable() {
            final Drawable backgroundDrawable = createBackgroundDrawableShape();
            LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{
                    backgroundDrawable,
                    backgroundDrawable,
                    createProgressDrawableShape()
            });
            layerDrawable.setId(0, android.R.id.background);
            layerDrawable.setId(1, android.R.id.secondaryProgress);
            layerDrawable.setId(2, android.R.id.progress);
            return layerDrawable;
        }
    
        protected Drawable createBackgroundDrawableShape() {
            final Bitmap tileBitmap = drawableToBitmap(getResources().getDrawable(R.drawable.ic_stamp_circle_empty));
            if (mSampleTile == null) {
                mSampleTile = tileBitmap;
            }
            final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
            final BitmapShader bitmapShader = new BitmapShader(tileBitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
            shapeDrawable.getPaint().setShader(bitmapShader);
            return shapeDrawable;
        }
    
        protected Drawable createProgressDrawableShape() {
            final Bitmap tileBitmap = drawableToBitmap(getResources().getDrawable(R.drawable.ic_stamp_circle_full));
            final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
            final BitmapShader bitmapShader = new BitmapShader(tileBitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
            shapeDrawable.getPaint().setShader(bitmapShader);
            return new ClipDrawable(shapeDrawable, Gravity.LEFT, ClipDrawable.HORIZONTAL);
        }
    
        Shape getDrawableShape() {
            final float[] roundedCorners = new float[]{5, 5, 5, 5, 5, 5, 5, 5};
            return new RoundRectShape(roundedCorners, null, null);
        }
    
        public static Bitmap drawableToBitmap(Drawable drawable) {
            if (drawable instanceof BitmapDrawable) {
                return ((BitmapDrawable) drawable).getBitmap();
            }
    
            int width = drawable.getIntrinsicWidth();
            width = width > 0 ? width : 1;
            int height = drawable.getIntrinsicHeight();
            height = height > 0 ? height : 1;
    
            final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            final Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
            drawable.draw(canvas);
    
            return bitmap;
        }
    
    } 
    

    Calling setMax setMaxStars calls requestLayout so you it will measure the width correctly. No need to work out the android:minWidth, Just set android:layout_width="wrap_content".

    Just remember you will need to add a bit of padding to your ShapeDrawables as they get repeated edge to edge.

提交回复
热议问题