我要尝试在我的自定义视图上绘制一个简单的弧,但它不会显示任何内容。很长一段时间以来一直困扰着我。
这是主要的行为:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//setContentView(new Ring(this));
}}
这是主要的xml:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ring="http://schemas.android.com/apk/res/com.shockwave.arandomer"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/scrollView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal|center"
android:orientation="vertical" >
<com.shockwave.arandomer.Ring
android:id="@+id/ring"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
ring:ring_color="red"
ring:stroke_width="5.0"/>
</LinearLayout>
</ScrollView>
然后这是绘图的主要类:
public class Ring extends ViewGroup{
Paint paint = null;
float stroke_w;
int ring_color;
public Ring(Context context,AttributeSet attrs) {
super(context,attrs);
setFocusable(true);
TypedArray type = context.getTheme().obtainStyledAttributes(attrs,R.styleable.Ring,0,0);
try{
stroke_w = type.getFloat(R.styleable.Ring_stroke_width, (float)3.0);
ring_color = type.getInteger(R.styleable.Ring_ring_color, 0);//default: black
}finally{
type.recycle();
}
switch(ring_color){
case 0:
ring_color = Color.BLACK;
break;
case 1:
ring_color = Color.RED;
break;
case 2:
ring_color = Color.GREEN;
break;
}
Ring_main ring_view = new Ring_main(getContext());
addView(ring_view);
//ring_view.invalidate();
}
@Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
int w = Math.max(minw, MeasureSpec.getSize(widthMeasureSpec));
int minh = getPaddingTop() + getPaddingBottom() + getSuggestedMinimumHeight();
int h = Math.max(MeasureSpec.getSize(heightMeasureSpec), minh);
setMeasuredDimension(w, h);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh){
super.onSizeChanged(w, h, oldw, oldh);
}
private class Ring_main extends View{
public Ring_main(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public Ring_main(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(ring_color);
paint.setStrokeWidth(stroke_w);
paint.setStyle(Style.STROKE);
RectF oval = new RectF();
oval.set(100, 100, 300, 300);
canvas.drawArc(oval, 90, 180, false, paint);
}
}
@Override
protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
// TODO Auto-generated method stub
}
}
感谢您的帮助
答案 0 :(得分:0)
您的内部班级Ring_main
不会覆盖onMeasure
,因此它的高度和宽度将为零。
您的外部课程Ring
在onLayout
中没有执行任何操作,并告诉孩子应该在屏幕上绘制哪些内容,这样也会导致问题。十分之九,您将要想要子类化LinearLayout,RelativeLayout或FrameLayout,而不是ViewGroup,因此您不必覆盖onMeasure
和onLayout
。
但是,当只有一个子视图时,您是否有任何理由使用视图组?您似乎可以将onDraw
方法移动到父Ring
中,删除内部Ring_main
类,并将Ring
更改为子类View,并且您将完成大部分工作
修改强>
在以下评论中回复您的代码:
您的onMeasure
实现是错误的,因为您忽略了附加到传入宽度和高度的可能模式。例如,在布局xml中,父级的高度为wrap_content
,因此onMeasure
的高度参数的模式为UNSPECIFIED
,当您调用{{1}时它将返回一个无用的数字(虽然它似乎默认为零)。
这是一个更正确的实现,尽管最终会有更多细节需要考虑,例如您是否希望弧展开以填充视图可用的任何空间量,或者始终保持相同大小,只是在视图中居中。
MeasureSpec.getSize(aHeight)
如果您的min SDK为11或更高版本,使用static final float DESIRED_WIDTH_BEFORE_PADDING = 100;
static final float DESIRED_HEIGHT_BEFORE_PADDING = 200;
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int wDesired = getPaddingLeft() + getPaddingRight() +
Math.max(DESIRED_WIDTH_BEFORE_PADDING, getSuggestedMinimumWidth());
int wSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int w = 0;
switch(wSpecMode){
case MeasureSpec.EXACTLY:
w = MeasureSpec.getSize(widthMeasureSpec);
break;
case MeasureSpec.AT_MOST:
w = Math.min(wDesired, MeasureSpec.getSize(widthMeasureSpec));
break;
case MeasureSpec.UNSPECIFIED:
w = wDesired;
break;
}
int hDesired = getPaddingTop() + getPaddingBottom() +
Math.max(DESIRED_HEIGHT_BEFORE_PADDING, getSuggestedMinimumHeight());
int hSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int h = 0;
switch(hSpecMode){
case MeasureSpec.EXACTLY:
h = MeasureSpec.getSize(heightMeasureSpec);
break;
case MeasureSpec.AT_MOST:
h = Math.min(hDesired, MeasureSpec.getSize(heightMeasureSpec));
break;
case MeasureSpec.UNSPECIFIED:
h = hDesired;
break;
}
setMeasuredDimension(w, h);
}
方法可以简化这一过程。
注意上面的内容被简化为忽略DIP。这两个静态浮点数应该是DIP单位,然后在resolveSizeAndState
中使用时将它们乘以密度。
您还可以覆盖onMeasure
来计算用于绘制圆弧的实际高度和宽度,以及可能使弧在视图中居中所需的任何偏移。然后,这些值将在onSizeChanged
中使用,以确保弧线绘制到您想要的位置。