In my Android project, I encountered some difficulties in the drawing code, so I made up a MCVE below to demonstrate the problem I have.
By running this example, and perform a touch in the screen, you can see two circles coming up.
You can see that the red one is positioned accurately and consistently around the point of touch.
For the green one, you can see that its position is somehow random on repeat touching of the screen.
The red circle is created using an ImageView
with the source as ball.xml
. For the green one, it is done by Canvas.drawCircle()
.
So:
How do I correct the code to make the red circle and green circle appear at exactly the same spot on a touch, regardless of the resolution and dpi of the screen?
Also, btw, the 500X1000 dimension ( Bitmap.createBitmap(500, 1000)
)is just set arbitrarily, it should be according to the screen size of the device.
package com.prime.testdraw;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
ImageView ivPhoto;
FrameLayout fl;
ImageView ivBall;
private Canvas myCV;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivPhoto = ((ImageView) findViewById(R.id.ivPhoto));
fl = ((FrameLayout) findViewById(R.id.fl));
ivBall = ((ImageView) findViewById(R.id.ivBall));
myCV = initDraw(ivPhoto);
ivPhoto.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
myCV = initDraw(ivPhoto);
ivBall.setX(motionEvent.getX() - ivBall.getWidth()/2);
ivBall.setY(motionEvent.getY() - ivBall.getHeight()/2);
Paint p = new Paint();
p.setStrokeWidth(3);
p.setColor(Color.GREEN);
p.setTextSize(100);
int radius = 40;
p.setStyle(Paint.Style.STROKE);
myCV.drawCircle(motionEvent.getX() - radius, motionEvent.getY() - radius, radius, p);
ivPhoto.invalidate();
return false;
}
});
}
private Canvas initDraw(ImageView imageView) {
Bitmap bmp = Bitmap.createBitmap(500, 1000, Bitmap.Config.RGB_565);
Canvas cv = new Canvas(bmp);
imageView.setImageDrawable(new BitmapDrawable(getResources(), bmp));
imageView.invalidate();
return cv;
}
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:id="@+id/fl">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/ivPhoto"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<ImageView
android:layout_width="52dp"
android:layout_height="52dp"
android:id="@+id/ivBall"
android:layout_gravity="left|top"
android:src="@drawable/ball" />
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" >
<stroke
android:width="4dp"
android:color="#FF0000" />
<gradient android:startColor="#FFFF0000" android:endColor="#80FF0000"
android:angle="270"/>
</shape>
Canvas.drawCircle works with these parameters :
Therefore instead of substracting the radius when calling it, simply call drawCircle directly :
myCV.drawCircle(motionEvent.getX(), motionEvent.getY(), radius, p);
Source : Android Canvas doc
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.