Android 中的自定义视图显示为黑框
Custom View in Android shows up as a black box
我正在尝试创建类似饼图的视图,但我对 Android 还很陌生,所以它并不总是按照我的计划进行。现在,如果我真的在我的 activity 中得到黑盒子以外的东西,我会很高兴 :) 你能帮忙吗?
这是我的代码:
activity_main.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:orientation="vertical">
<TextView
android:text="@string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.example.wouter.countdownwidget.PieHolder
android:id="@+id/pieHolder"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</com.example.wouter.countdownwidget.PieHolder>
</LinearLayout>
MainActivity.java
public class MainActivity extends Activity {
private static final String LOG_TAG = "MainActivity";
@Override protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PieHolder pieHolder = (PieHolder) findViewById(R.id.pieHolder);
pieHolder.addInterval(new Interval(1, Color.RED));
}
}
PieHolder.java
public class PieHolder extends ViewGroup {
private static final String LOG_TAG = "PieHolder";
private RectF pieBounds = new RectF();
private PieView pieView;
public PieHolder (Context context) {
super(context);
init();
}
public PieHolder (Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init () {
setBackgroundColor(Color.WHITE);
pieView = new PieView(this);
addView(pieView);
}
void addInterval (Interval interval) {
pieView.addInterval(interval);
}
@DebugLog @Override protected void onSizeChanged (int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
float xpad = (float) (getPaddingLeft() + getPaddingRight());
float ypad = (float) (getPaddingTop() + getPaddingBottom());
float ww = (float) w - xpad;
float hh = (float) h - ypad;
float diameter = Math.min(ww, hh);
pieBounds = new RectF(0, 0, diameter, diameter);
pieBounds.offsetTo(getPaddingLeft(), getPaddingTop());
pieView.layout((int) pieBounds.left,
(int) pieBounds.top,
(int) pieBounds.right,
(int) pieBounds.bottom);
}
@DebugLog @Override protected void dispatchDraw (Canvas canvas) {
super.dispatchDraw(canvas);
if (pieView != null) pieView.draw(canvas);
}
@Override protected void onLayout (boolean changed, int l, int t, int r, int b) {
}
}
PieView.java
public class PieView extends SurfaceView{
private static final String LOG_TAG = "PieView";
private PieHolder pieHolder;
//private SurfaceHolder holder;
//private PieViewThread pieViewThread;
private RectF rectF;
private Paint paint;
private List<Interval> intervals;
@DebugLog public PieView (PieHolder pieHolder) {
super(pieHolder.getContext());
this.pieHolder = pieHolder;
intervals = new ArrayList<>();
rectF = new RectF(0, 0, pieHolder.getWidth(), pieHolder.getHeight());
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.GREEN);
}
public void addInterval (Interval interval) {
intervals.add(interval);
}
@DebugLog @Override protected void onDraw (Canvas canvas) {
super.onDraw(canvas);
if (rectF == null) {
rectF = new RectF(0, 0, pieHolder.getWidth(), pieHolder.getHeight());
Log.i(LOG_TAG, "Reinstantiating rectF");
}
canvas.drawColor(Color.RED);
canvas.drawArc(rectF, 0, 180, true, paint);
}
}
您自定义了一个视图组,但其中没有任何内容。如果你只是想做一个视图,你最好从View而不是ViewGroup扩展。
您可以参考 google android 网站的文档:http://developer.android.com/training/custom-views/create-view.html
我找到解决方法了!!!
Android 期望在另一个线程中绘制 SurfaceView
,因此我需要在 PieView
的构造函数中调用 setWillNotDraw(false)
。此外,正如谢所说,创建自定义 ViewGroup
有点毫无意义,所以我也摆脱了它。
这是我的 PieView
class 对于那些感兴趣的人:
class PieView extends SurfaceView{
private Interval[] intervals;
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private RectF rectf;
private int size;
public PieView (Context context, Interval[] intervals) {
super(context);
this.intervals = intervals;
setWillNotDraw(false);
}
@Override protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
size = Math.min(getMeasuredWidth(), getMeasuredHeight());
setMeasuredDimension(size, size);
if (rectf == null || rectf.width() != size ) { rectf = new RectF(0, 0, size, size); }
}
@Override protected void onDraw (Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(getResources().getColor(android.R.color.background_light));
paint.setColor(intervals[0].color);
canvas.drawArc(rectf, -90, 360, true, paint);
paint.setColor(intervals[1].color);
canvas.drawArc(rectf, -90, intervals[1].duration, true, paint);
}
}
PS: 这绝不是我的最终目标,但现在我至少在我的屏幕上画了一些东西
我正在尝试创建类似饼图的视图,但我对 Android 还很陌生,所以它并不总是按照我的计划进行。现在,如果我真的在我的 activity 中得到黑盒子以外的东西,我会很高兴 :) 你能帮忙吗?
这是我的代码:
activity_main.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:orientation="vertical">
<TextView
android:text="@string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.example.wouter.countdownwidget.PieHolder
android:id="@+id/pieHolder"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</com.example.wouter.countdownwidget.PieHolder>
</LinearLayout>
MainActivity.java
public class MainActivity extends Activity {
private static final String LOG_TAG = "MainActivity";
@Override protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PieHolder pieHolder = (PieHolder) findViewById(R.id.pieHolder);
pieHolder.addInterval(new Interval(1, Color.RED));
}
}
PieHolder.java
public class PieHolder extends ViewGroup {
private static final String LOG_TAG = "PieHolder";
private RectF pieBounds = new RectF();
private PieView pieView;
public PieHolder (Context context) {
super(context);
init();
}
public PieHolder (Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init () {
setBackgroundColor(Color.WHITE);
pieView = new PieView(this);
addView(pieView);
}
void addInterval (Interval interval) {
pieView.addInterval(interval);
}
@DebugLog @Override protected void onSizeChanged (int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
float xpad = (float) (getPaddingLeft() + getPaddingRight());
float ypad = (float) (getPaddingTop() + getPaddingBottom());
float ww = (float) w - xpad;
float hh = (float) h - ypad;
float diameter = Math.min(ww, hh);
pieBounds = new RectF(0, 0, diameter, diameter);
pieBounds.offsetTo(getPaddingLeft(), getPaddingTop());
pieView.layout((int) pieBounds.left,
(int) pieBounds.top,
(int) pieBounds.right,
(int) pieBounds.bottom);
}
@DebugLog @Override protected void dispatchDraw (Canvas canvas) {
super.dispatchDraw(canvas);
if (pieView != null) pieView.draw(canvas);
}
@Override protected void onLayout (boolean changed, int l, int t, int r, int b) {
}
}
PieView.java
public class PieView extends SurfaceView{
private static final String LOG_TAG = "PieView";
private PieHolder pieHolder;
//private SurfaceHolder holder;
//private PieViewThread pieViewThread;
private RectF rectF;
private Paint paint;
private List<Interval> intervals;
@DebugLog public PieView (PieHolder pieHolder) {
super(pieHolder.getContext());
this.pieHolder = pieHolder;
intervals = new ArrayList<>();
rectF = new RectF(0, 0, pieHolder.getWidth(), pieHolder.getHeight());
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.GREEN);
}
public void addInterval (Interval interval) {
intervals.add(interval);
}
@DebugLog @Override protected void onDraw (Canvas canvas) {
super.onDraw(canvas);
if (rectF == null) {
rectF = new RectF(0, 0, pieHolder.getWidth(), pieHolder.getHeight());
Log.i(LOG_TAG, "Reinstantiating rectF");
}
canvas.drawColor(Color.RED);
canvas.drawArc(rectF, 0, 180, true, paint);
}
}
您自定义了一个视图组,但其中没有任何内容。如果你只是想做一个视图,你最好从View而不是ViewGroup扩展。
您可以参考 google android 网站的文档:http://developer.android.com/training/custom-views/create-view.html
我找到解决方法了!!!
Android 期望在另一个线程中绘制 SurfaceView
,因此我需要在 PieView
的构造函数中调用 setWillNotDraw(false)
。此外,正如谢所说,创建自定义 ViewGroup
有点毫无意义,所以我也摆脱了它。
这是我的 PieView
class 对于那些感兴趣的人:
class PieView extends SurfaceView{
private Interval[] intervals;
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private RectF rectf;
private int size;
public PieView (Context context, Interval[] intervals) {
super(context);
this.intervals = intervals;
setWillNotDraw(false);
}
@Override protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
size = Math.min(getMeasuredWidth(), getMeasuredHeight());
setMeasuredDimension(size, size);
if (rectf == null || rectf.width() != size ) { rectf = new RectF(0, 0, size, size); }
}
@Override protected void onDraw (Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(getResources().getColor(android.R.color.background_light));
paint.setColor(intervals[0].color);
canvas.drawArc(rectf, -90, 360, true, paint);
paint.setColor(intervals[1].color);
canvas.drawArc(rectf, -90, intervals[1].duration, true, paint);
}
}
PS: 这绝不是我的最终目标,但现在我至少在我的屏幕上画了一些东西