2013-10-10 4 views
2

Кажется, я не могу установить ShapeDrawable как progressDrawable для рейтинга. Я попытался следующие, но не смог:ShapeDrawable as progressDrawable для RatingBar в Android?

<RatingBar 
android:id="@+id/ratingbar" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:layout_alignParentBottom="true" 
android:numStars="5" 
android:stepSize="1.0" 
android:rating="3.0" 
style="@style/myRatingBar" 
/> 

myRatingbar стиль:

<style name="myRatingBar" parent="@android:style/Widget.RatingBar"> 
<item name="android:progressDrawable">@drawable/ratingbar_full</item> 
<item name="android:indeterminateDrawable">@drawable/ratingbar_full</item> 
<item name="android:minHeight">48dip</item> 
<item name="android:maxHeight">48dip</item> 
<item name="android:scaleType">center</item> 
</style> 

ratingbar_full.xml:

<shape 
     android:shape="ring" 
     android:innerRadius="10dip" 
     android:thickness="1dip"> 
     <solid android:color="@color/red" /> 
     <size 
      android:width="48dip" 
      android:height="48dip" 
     /> 
    </shape> 

Ничто не показывает на экране.

EDIT: использовать .png вместо формы работы по этой линии:

@ вытяжке/ratingbar_full

ответ

3

Я настроил метод @ChrisJenkins, поэтому вы можете установить размер значков RatingBar и пользовательских цветов оттенков для оценки изображений. Вы можете установить дополнение на свой RatingBar или задать свою собственную ширину и высоту. Решение @ChrisJenkins помогло мне много, чтобы наконец создать полностью настраиваемый RatingBar. Вы также можете установить параметры в своем XML.

public class DrawableRatingBar extends RatingBar 
{ 
// TileBitmap to base the width and hight off of. 
@Nullable 
private Bitmap iconTile; 
private float scaleIconFactor; 
private @ColorInt int iconBackgroundColor; 
private @ColorInt int iconForegroundColor; 
private @DrawableRes int iconDrawable; 

public DrawableRatingBar(Context context) 
{ 
    super(context); 
    init(); 
} 

public DrawableRatingBar(Context context, AttributeSet attrs) 
{ 
    super(context, attrs); 

    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DrawableRatingBarItem); 
    scaleIconFactor = a.getFloat(R.styleable.DrawableRatingBarItem_scaleIconFactor, 1); 
    iconBackgroundColor = a.getColor(R.styleable.DrawableRatingBarItem_iconBackgroundColor, Color.BLACK); 
    iconForegroundColor = a.getColor(R.styleable.DrawableRatingBarItem_iconForegroundColor, Color.WHITE); 
    iconDrawable = a.getResourceId(R.styleable.DrawableRatingBarItem_iconDrawable, -1); 
    a.recycle(); 

    init(); 
} 

public DrawableRatingBar(Context context, AttributeSet attrs, int defStyleAttr) 
{ 
    super(context, attrs, defStyleAttr); 
    init(); 
} 

@TargetApi(Build.VERSION_CODES.LOLLIPOP) 
public DrawableRatingBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) 
{ 
    super(context, attrs, defStyleAttr, defStyleRes); 
    init(); 
} 

private void init() 
{ 
    setProgressDrawable(createProgressDrawable()); 
} 

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
{ 
    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 

    if (iconTile != null) 
    { 
     final int width = iconTile.getWidth() * getNumStars(); 
     final int height = iconTile.getHeight(); 
     setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, 0), 
          resolveSizeAndState(height, heightMeasureSpec, 0)); 
    } 
} 

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() 
{ 
    Drawable drawable = ContextCompat.getDrawable(getContext(), iconDrawable); 

    final Bitmap tileBitmap = scaleImageWithColor(drawable, scaleIconFactor, iconBackgroundColor); 
    if (iconTile == null) 
    { 
     iconTile = 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; 
} 


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

protected Drawable createProgressDrawableShape() 
{ 
    Drawable drawable = ContextCompat.getDrawable(getContext(), iconDrawable); 

    final Bitmap tileBitmap = scaleImageWithColor(drawable, scaleIconFactor, iconForegroundColor); 
    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() 
{ 
    return new RectShape(); 
} 

public Bitmap scaleImageWithColor(Drawable drawable, float scaleFactor, @ColorInt int color) 
{ 
    Bitmap b = ((BitmapDrawable) drawable).getBitmap(); 

    int sizeX = Math.round(drawable.getIntrinsicWidth() * scaleFactor); 
    int sizeY = Math.round(drawable.getIntrinsicHeight() * scaleFactor); 

    Bitmap bitmapResized = Bitmap.createScaledBitmap(b, sizeX, sizeY, true); 

    Canvas canvas = new Canvas(bitmapResized); 
    Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG); 
    paint.setAntiAlias(true); 
    ColorFilter filter = new LightingColorFilter(color, 1); 
    paint.setColorFilter(filter); 
    canvas.drawBitmap(bitmapResized, 0, 0, paint); 

    return bitmapResized; 

} 

protected Bitmap fromDrawable(final Drawable drawable, final int height, final int width) 
{ 
    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; 
} 

public float getScaleIconFactor() 
{ 
    return scaleIconFactor; 
} 

public void setScaleIconFactor(float scaleIconFactor) 
{ 
    this.scaleIconFactor = scaleIconFactor; 
} 

public int getIconForegroundColor() 
{ 
    return iconForegroundColor; 
} 

public void setIconForegroundColor(int iconForegroundColor) 
{ 
    this.iconForegroundColor = iconForegroundColor; 
} 

public int getIconBackgroundColor() 
{ 
    return iconBackgroundColor; 
} 

public void setIconBackgroundColor(int iconBackgroundColor) 
{ 
    this.iconBackgroundColor = iconBackgroundColor; 
} 

public int getIconDrawable() 
{ 
    return iconDrawable; 
} 

public void setIconDrawable(int iconDrawable) 
{ 
    this.iconDrawable = iconDrawable; 
} 

}

Пользовательские атрибуты:

<declare-styleable name="DrawableRatingBarItem"> 
    <attr name="scaleIconFactor" format="float"/> 
    <attr name="iconBackgroundColor" format="color"/> 
    <attr name="iconForegroundColor" format="color"/> 
    <attr name="iconDrawable" format="reference"/> 
</declare-styleable> 
+0

Просто для любого будущего читателя, чтобы видеть - это работает отлично. Но с помощью ColorFilter, который вы использовали, он будет умножать цвета при добавлении их в drawable. Я предлагаю вам использовать фильтр ColorFilter = новый LightingColorFilter (0, цвет); для замены исходного цвета. – ravindu1024

+0

Спасибо, я посмотрю! – box

0

Вы можете найти шаг за шагом ratingBar стайлинга here
попытаться установить <item name="android:progressDrawable"> в изображение вместо формы, если оно работает, что означает, что ваша форма вызывает проблему.

+0

почему Bitmap может, но ShapeDrawable не может? –

+0

Не знаю! но, поскольку он работает, создайте эту форму как png и используйте ее –

1

I dig RatingBar (и его родительский класс ProgressBar) sourc е код, и обнаружил, что ShapeDrawable отсутствует tileify(), который вызывается перед установкой progressDrawable в ProgressBar конструктору:

private Drawable tileify(Drawable drawable, boolean clip) { 

    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] = tileify(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 StateListDrawable) { 
     StateListDrawable in = (StateListDrawable) drawable; 
     StateListDrawable out = new StateListDrawable(); 
     int numStates = in.getStateCount(); 
     for (int i = 0; i < numStates; i++) { 
      out.addState(in.getStateSet(i), tileify(in.getStateDrawable(i), clip)); 
     } 
     return out; 

    } else if (drawable instanceof BitmapDrawable) { 
     final Bitmap tileBitmap = ((BitmapDrawable) drawable).getBitmap(); 
     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 (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT, 
       ClipDrawable.HORIZONTAL) : shapeDrawable; 
    } 

    return drawable; 
} 

Я не знаю, почему ShapeDrawable не была поставлена ​​там, но я рассматриваю, чтобы добавить его в подклассах код.

7

Shape XML Drawables + RatingBar полный беспорядок.

Это как можно ближе к решению без написания нового класса.

Мой расширенный класс строит ход, правильно рассчитанный для ProgressBar, зажимающий его по мере необходимости.

Замените пустые и полные состояния теми, которые я предварительно заполнил. Не очень гибкий в данный момент, вы можете легко абстрагироваться от установки пустых/полных звездных состояний.

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

} 

Вызов setMaxsetMaxStars звонки requestLayout так что вы его правильно измерить ширину. Не нужно разрабатывать android:minWidth, просто установите android:layout_width="wrap_content".

Просто помните, что вам нужно будет добавить немного отступов к вашему ShapeDrawables, поскольку они получат повторяющиеся края до края.

+0

спасибо. работал для меня – IndieBoy

Смежные вопросы