我必须显示一个可调整大小的矩形。
我的xml文件:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".exampleActivity">
<ImageView
android:id="@+id/office"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/office"
android:src="@raw/office" />
<com.lambdahash.sonic.example.draw.DrawView
android:id="@+id/drawView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
显示此活动矩形的代码:
public class DrawView extends View {
Point point1, point3;
Point point2, point4;
/**
* point1 and point 3 are of same group and same as point 2 and point4
*/
int groupId = -1;
private ArrayList<ColorBall> colorballs = new ArrayList<ColorBall>();
// array that holds the balls
private int balID = 0;
// variable to know what ball is being dragged
Paint paint;
Canvas canvas;
public DrawView(Context context) {
super(context);
paint = new Paint();
setFocusable(true); // necessary for getting the touch events
canvas = new Canvas();
// this.setWillNotDraw(false); //?
Log.d("TEST:","DrawView() being called.");
// setting the start point for the balls
point1 = new Point();
point1.x = 50;
point1.y = 20;
point2 = new Point();
point2.x = 150;
point2.y = 20;
point3 = new Point();
point3.x = 150;
point3.y = 120;
point4 = new Point();
point4.x = 50;
point4.y = 120;
// declare each ball with the ColorBall class
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point1));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point2));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point3));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point4));
}
public DrawView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint();
setFocusable(true); // necessary for getting the touch events
canvas = new Canvas();
// setting the start point for the balls
point1 = new Point();
point1.x = 50;
point1.y = 20;
point2 = new Point();
point2.x = 150;
point2.y = 20;
point3 = new Point();
point3.x = 150;
point3.y = 120;
point4 = new Point();
point4.x = 50;
point4.y = 120;
// declare each ball with the ColorBall class
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point1));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point2));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point3));
colorballs.add(new ColorBall(context, R.drawable.gray_circle, point4));
}
// the method that draws the balls
@Override
protected void onDraw(Canvas canvas) {
Log.d("TEST:","onDraw() being called.");
// canvas.drawColor(0xFFCCCCCC); //if you want another background color
paint.setAntiAlias(true);
paint.setDither(true);
paint.setColor(Color.parseColor("#55000000"));
paint.setStyle(Paint.Style.FILL);
paint.setStrokeJoin(Paint.Join.ROUND);
// mPaint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(5);
canvas.drawPaint(paint);
paint.setColor(Color.parseColor("#55FFFFFF"));
if (groupId == 1) {
canvas.drawRect(point1.x + colorballs.get(0).getWidthOfBall() / 2,
point3.y + colorballs.get(2).getWidthOfBall() / 2, point3.x
+ colorballs.get(2).getWidthOfBall() / 2, point1.y
+ colorballs.get(0).getWidthOfBall() / 2, paint);
} else {
canvas.drawRect(point2.x + colorballs.get(1).getWidthOfBall() / 2,
point4.y + colorballs.get(3).getWidthOfBall() / 2, point4.x
+ colorballs.get(3).getWidthOfBall() / 2, point2.y
+ colorballs.get(1).getWidthOfBall() / 2, paint);
}
BitmapDrawable mBitmap;
mBitmap = new BitmapDrawable();
// draw the balls on the canvas
for (ColorBall ball : colorballs) {
canvas.drawBitmap(ball.getBitmap(), ball.getX(), ball.getY(),
new Paint());
}
}
//??????????????????
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.d("TEST2:","onMeasure() being called.");
Log.v("Chart onMeasure w", MeasureSpec.toString(widthMeasureSpec));
Log.v("Chart onMeasure h", MeasureSpec.toString(heightMeasureSpec));
int desiredWidth = getSuggestedMinimumWidth() + getPaddingLeft() + getPaddingRight();
int desiredHeight = getSuggestedMinimumHeight() + getPaddingTop() + getPaddingBottom();
setMeasuredDimension(measureDimension(desiredWidth, widthMeasureSpec),
measureDimension(desiredHeight, heightMeasureSpec));
}
private int measureDimension(int desiredSize, int measureSpec) {
int result;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = desiredSize;
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
if (result < desiredSize){
Log.e("ChartView", "The view is too small, the content might get cut");
}
return result;
}
// events when touching the screen
public boolean onTouchEvent(MotionEvent event) {
int eventaction = event.getAction();
int X = (int) event.getX();
int Y = (int) event.getY();
switch (eventaction) {
case MotionEvent.ACTION_DOWN: // touch down so check if the finger is on
// a ball
balID = -1;
groupId = -1;
for (ColorBall ball : colorballs) {
// check if inside the bounds of the ball (circle)
// get the center for the ball
//Utils.logd("Id : " + ball.getID());
//Utils.logd("getX : " + ball.getX() + " getY() : " + ball.getY());
int centerX = ball.getX() + ball.getWidthOfBall();
int centerY = ball.getY() + ball.getHeightOfBall();
paint.setColor(Color.CYAN);
// calculate the radius from the touch to the center of the ball
double radCircle = Math
.sqrt((double) (((centerX - X) * (centerX - X)) + (centerY - Y)
* (centerY - Y)));
//Utils.logd("X : " + X + " Y : " + Y + " centerX : " + centerX + " CenterY : " + centerY + " radCircle : " + radCircle);
if (radCircle < ball.getWidthOfBall()) {
balID = ball.getID();
//Utils.logd("Selected ball : " + balID);
if (balID == 1 || balID == 3) {
groupId = 2;
canvas.drawRect(point1.x, point3.y, point3.x, point1.y,
paint);
} else {
groupId = 1;
canvas.drawRect(point2.x, point4.y, point4.x, point2.y,
paint);
}
invalidate();
break;
}
invalidate();
}
break;
case MotionEvent.ACTION_MOVE: // touch drag with the ball
// move the balls the same as the finger
if (balID > -1) {
//Utils.logd("Moving Ball : " + balID);
Log.d("Moving Ball : " ,"" + balID);
colorballs.get(balID).setX(X);
colorballs.get(balID).setY(Y);
paint.setColor(Color.CYAN);
if (groupId == 1) {
colorballs.get(1).setX(colorballs.get(0).getX());
colorballs.get(1).setY(colorballs.get(2).getY());
colorballs.get(3).setX(colorballs.get(2).getX());
colorballs.get(3).setY(colorballs.get(0).getY());
canvas.drawRect(point1.x, point3.y, point3.x, point1.y,
paint);
} else {
colorballs.get(0).setX(colorballs.get(1).getX());
colorballs.get(0).setY(colorballs.get(3).getY());
colorballs.get(2).setX(colorballs.get(3).getX());
colorballs.get(2).setY(colorballs.get(1).getY());
canvas.drawRect(point2.x, point4.y, point4.x, point2.y,
paint);
}
invalidate();
}
break;
case MotionEvent.ACTION_UP:
// touch drop - just do things here after dropping
break;
}
// redraw the canvas
invalidate();
return true;
}
public void shade_region_between_points() {
canvas.drawRect(point1.x, point3.y, point3.x, point1.y, paint);
}
}
最后,使用以下命令在activity.xml上调用它:
public class exampleActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example);
DrawView dv = new DrawView(getApplicationContext());
}
因此,当我在活动中在onCreate()中调用myDrawView时,我会得到
TEST: myDrawView() constructor called.
。但是,在那之后,我没有得到 TEST: onDraw() method called.
onDraw()方法由于某种原因未被调用。该怎么办?
答案 0 :(得分:1)
实际上没有将MyDrawView添加到您的UI的任何操作。它不在您发布的布局中。它不是以编程方式添加到布局中的。仅创建视图不会显示它。
答案 1 :(得分:1)
看起来您既没有在布局文件中也没有在活动代码中添加自定义视图。 尝试像这样添加它。
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".exampleActivity"
>
<ImageView
android:id="@+id/office"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/office"
android:src="@raw/office"
/>
<your.package.name.MyDrawView
android:id="@+id/myAwesomeDrawView"
android:layout_width="match_parent"
android:layout_height="200dp"
/>
</RelativeLayout>
然后它应该显示在您的应用中。
请注意,作为@GabeSechan said,某些容器在测量其宽度和高度为0时不会对视图进行布局。您必须在xml布局文件中指定视图的尺寸,或者提供correct onMeasure()
。
如果您仍然想以编程方式添加它,则可以使用onCreate()
方法,例如:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final RelativeLayout myAwesomeLayout = findViewById(R.id.your_container_id);
final View myAwesomeView = new View(this);
someViewsetLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
myAwesomeLayout.addView(myAwesomeView);
}
请注意,约定是在Java中类名以大写字母开头。
一些其他要点:
onDraw()
中分配了很多对象
方法,可能会导致内存消耗增加和性能下降
性能,最好避免这种情况并尝试重用对象
而不是创建新的。 public class MyDrawView extends View {
// for example only
@ColorInt final int fillColor;
public MyDrawView(final Context context) {
this(context, null);
}
public MyDrawView(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public MyDrawView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
// initialize here, like
fillColor = Color.parseInt("something");
}
}
答案 2 :(得分:0)
<ImageView android:id="@+id/office"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/office" android:src="@raw/office" />
这可能是拼写错误吗?那应该是@ draw / office吗?