2013-10-10 2 views
2

등급 표시 줄에 대해 progressDrawable로 ShapeDrawable을 설정할 수없는 것 같습니다. 나는 다음을 시도했지만 실패Android에서 RatingBar의 progressDrawable과 같은 ShapeDrawable?

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

아무것도 화면에 표시되지 않습니다를.

편집 : 대신 모양의 .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 filter = new LightingColorFilter (0, color);를 사용하는 것이 좋습니다. 원래 색상을 대체합니다. – ravindu1024

+0

감사합니다. 나는 그것을 살펴볼 것입니다! – box

0

당신은 here
<item name="android:progressDrawable">을 설정하려고 단계 ratingBar 스타일링에 의해 단계를 찾을 수 있습니다 이미지가 모양이 아니라 모양이 문제가되는 것입니다.

+0

왜 비트 맵 수 있지만 쉐이프 수 없어? –

+0

모릅니다! 하지만 작동 이후 그것은 png로 그 모양을 만들고 그것을 사용하십시오 –

1

I dating RatingBar (및 그 부모 클래스 ProgressBar) sourc

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

내가 쉐이프가 넣어되지 않은 이유를 모르지만 서브 클래스에 추가 할 것을 고려하고있다 : 전자 코드 및 쉐이프는 ProgressBar의 생성자에서 progressDrawable를 설정하기 전에이라고 tileify()에서 누락 된 것을 발견 암호.

7

도형 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

관련 문제