Known Indirect Subclasses
PathShape
//需要有个Shape
ShapeDrawable shapeDrawable = new ShapeDrawable(s)
//我们new一个Shape的子类PathShape,
//PathShape需要一个Path路径,和这个Path可以绘制区域的长和宽
PathShape pathShape = new PathShape(path, stdWidth, stdHeight)
为了方便我们自定义一个View
public class StarsScoreView extends View {
// 五角星半径
private float mRadiusOut = 20;
// 内部五边形半径
private float mRadiusIn;
// 一个空的五角星的轮廓边距
private float mStroke = 2;
private Paint mShapeDrawablePaint;
private float length;
private Path mPath;
private int color = 0xFF0000;
private final static float DEGREE = 36; // 五角星角度
// 36度的弧度值
private float radian;
private ShapeDrawable shapeDrawable;
public StarsScoreView(Context context) {
super(context);
}
public StarsScoreView(Context context, AttributeSet attrs) {
super(context, attrs);
try {
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.StarsScoreView);
this.color = a
.getColor(R.styleable.StarsScoreView_viewcolor, color);
this.mRadiusOut = a.getDimensionPixelSize(
R.styleable.StarsScoreView_radius, (int) mRadiusOut);
this.mStroke = a.getDimensionPixelSize(
R.styleable.StarsScoreView_stroke, (int) mStroke);
a.recycle();
} catch (Exception e) {
}
init();
}
private void init() {
shapeDrawable = new ShapeDrawable();
mShapeDrawablePaint = shapeDrawable.getPaint();
mShapeDrawablePaint.setStyle(Style.STROKE);
mShapeDrawablePaint.setStrokeWidth(mStroke);
mShapeDrawablePaint.setColor(color);
mShapeDrawablePaint.setStrokeJoin(Join.ROUND);
mShapeDrawablePaint.setStrokeCap(Cap.ROUND);
radian = degree2Radian(DEGREE);
mRadiusIn = (float) (mRadiusOut * Math.sin(radian / 2) / Math
.cos(radian)); // 中间五边形的半径
mPath = createEmptyStarPath();
// Measure the path
PathMeasure measure = new PathMeasure(mPath, false);
length = measure.getLength();
}
private float degree2Radian(float degree) {
return (float) (Math.PI * degree / 180);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else {
width = (int) (getPaddingLeft() + mRadiusOut * Math.cos(radian / 2)
* 2 + getPaddingRight());
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else {
height = (int) (getPaddingTop() + mRadiusOut + mRadiusOut
* Math.cos(radian) + getPaddingBottom());
}
setMeasuredDimension(width, height);
PathShape pathShape = new PathShape(mPath, width, height);
shapeDrawable.setShape(pathShape);
setBackgroundDrawable(shapeDrawable);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
private Path createEmptyStarPath() {
float x_cos_out = (float) (mRadiusOut * Math.cos(radian / 2));
Path path = new Path();
// 1
path.moveTo(x_cos_out, mStroke);
// 2
path.lineTo(
(float) (x_cos_out + mRadiusIn * Math.sin(radian) - mStroke
* Math.sin(radian)),
(float) (mRadiusOut - mRadiusOut * Math.sin(radian / 2) + mStroke
* Math.cos(radian)));
// 3
path.lineTo(
(float) (x_cos_out * 2 - mStroke * Math.cos(radian / 2)),
(float) (mRadiusOut - mRadiusOut * Math.sin(radian / 2) + mStroke
* Math.sin(radian / 2)));
// 4
path.lineTo(
(float) (x_cos_out + (mRadiusIn - mStroke)
* Math.cos(radian / 2)),
(float) (mRadiusOut + (mRadiusIn - mStroke)
* Math.sin(radian / 2)));
// 5
path.lineTo(
(float) (x_cos_out + (mRadiusOut - mStroke) * Math.sin(radian)),
(float) (mRadiusOut + (mRadiusOut - mStroke) * Math.cos(radian)));
// 6
path.lineTo(x_cos_out, (float) (mRadiusOut + mRadiusIn - mStroke));
// 7
path.lineTo(
(float) (x_cos_out - (mRadiusOut - mStroke) * Math.sin(radian)),
(float) (mRadiusOut + (mRadiusOut - mStroke) * Math.cos(radian)));
// 8
path.lineTo(
(float) (x_cos_out - (mRadiusIn - mStroke)
* Math.cos(radian / 2)),
(float) (mRadiusOut + (mRadiusIn - mStroke)
* Math.sin(radian / 2)));
// 9
path.lineTo(
(float) (mStroke * Math.cos(radian / 2)),
(float) (mRadiusOut - (mRadiusOut - mStroke)
* Math.sin(radian / 2)));
// 10
path.lineTo(
(float) (x_cos_out - (mRadiusIn - mStroke) * Math.sin(radian)),
(float) (mRadiusOut - mRadiusOut * Math.sin(radian / 2) + mStroke
* Math.cos(radian)));
path.close();
return path;
}
public void setPhase(float phase) {
mShapeDrawablePaint
.setPathEffect(createPathEffect(length, phase, 0.0f));
invalidate();
}
private static PathEffect createPathEffect(float pathLength, float phase,
float offset) {
return new DashPathEffect(new float[] { pathLength, pathLength },
pathLength - phase * pathLength);
// return new DashPathEffect(new float[] { phase*pathLength, pathLength
// },
// 0);
}
}
<declare-styleable name="StarsScoreView">
<attr name="viewcolor" format="color|reference" />
<attr name="radius" format="dimension" />
<attr name="stroke" format="dimension" />
</declare-styleable>
布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.example.bitmapdrawable.view.StarsScoreView
android:id="@+id/viewO1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginTop="20dip"
android:background="#987594"
android:padding="4dp"
app:radius="100dp"
app:stroke="2dp"
app:viewcolor="@color/red" >
</com.example.bitmapdrawable.view.StarsScoreView>
</RelativeLayout>
StarsScoreView viewO1;
ObjectAnimator animator;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shape_drawable);
viewO1 = (StarsScoreView) findViewById(R.id.viewO1);
animator = ObjectAnimator.ofFloat(viewO1, "phase", 0.0f,
1.0f);
animator.setDuration(3000);
viewO1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
animator.cancel();
animator.start();
// if(animator.isRunning()){
// animator.cancel();
// animator.resume(); //API19
// animator.pause();//API19
// }else{
// animator.start();
// }
}
});
}
效果
RectShape
RectShape rectShape = new RectShape();
ShapeDrawable shapeDrawable = new ShapeDrawable(rectShape);
shapeDrawable.getPaint().setColor(Color.BLUE);
txt01.setBackgroundDrawable(shapeDrawable);
ArcSahpe、OvalShape、RoundRectShape
都是RectShape的子类
ArcShape arcShape = new ArcShape(0, 90);
ShapeDrawable shapeDrawable = new ShapeDrawable(arcShape);
shapeDrawable.getPaint().setColor(Color.BLUE);
txt01.setBackgroundDrawable(shapeDrawable);
OvalShape ovalShape = new OvalShape();
ShapeDrawable shapeDrawable = new ShapeDrawable(ovalShape);
shapeDrawable.getPaint().setColor(Color.BLUE);
txt01.setBackgroundDrawable(shapeDrawable);
//1、2左上角,3、4右上角,5、6右下角,7、8左下角,可以传入null
RoundRectShape roundRectShape = new RoundRectShape(
new float[]{50,50,30,30,50,50,30,30},
new RectF(50, 50, 50, 50),
new float[]{50,50,50,50,50,50,50,50});
ShapeDrawable shapeDrawable = new ShapeDrawable(roundRectShape);
shapeDrawable.getPaint().setColor(Color.BLUE);
txt01.setBackgroundDrawable(shapeDrawable);
顺便说一下,这个RoundRectShape最好玩,它内部有个矩形,相当于从最外面的大矩形里抠出来小的矩形,抠出来的区域是不是透明的了,如果我们用属性动画控制内外矩形之间的边距,是不是可以做出看似把里面的内容一点一点显示出来。
类似于这个
|