Desired Outcome
I want to draw a red circle at the position the screen is touched then remove it when the touch is released.
Current Outcome
Whenever I touch the screen the red circle appears in the touched location, however when I release the touch the circle stays on the screen.
Extra Help
I am pretty new to coding for android and if a quick gloss over my code shows that I'm using anything unnecessary I would love to be told so I can improve.
My Code
package com.mr.mwood.thumbinput;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
class SampleView extends SurfaceView {
private final SurfaceHolder surfaceHolder;
private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
// CONSTRUCTOR
public SampleView(Context context) {
super(context);
surfaceHolder = getHolder();
paint.setColor(Color.RED);
paint.setStyle(Style.FILL);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
Canvas canvas = surfaceHolder.lockCanvas();
switch (event.getActionMasked()) {
case (MotionEvent.ACTION_DOWN):
canvas.drawColor(Color.BLACK);
canvas.drawCircle(event.getX(), event.getY(), 50, paint);
break;
case (MotionEvent.ACTION_UP):
canvas.drawColor(Color.BLACK);
break;
}
surfaceHolder.unlockCanvasAndPost(canvas);
return false;
}
}
}
Related
I need to make a Button that cleans my canvas and also a safe button.
I would like that the Activity stays like it is . And just Path what was drawn would be deleted.Thank you so much for any help. My Code:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class TouchEventDraw extends View {
//Variable
private Paint paint = new Paint();
private Path path = new Path();
//Konstruktor
public TouchEventDraw(Context context, AttributeSet attrset) {
super(context, attrset);
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStrokeJoin(Paint.Join.MITER);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5f);
}
/**
* The most important step in drawing a custom view is to override the
* #param canvas object that the view can use to draw itself. */
#Override
protected void onDraw(Canvas canvas) {
if(path.isEmpty())
canvas.drawColor(Color.WHITE);
else
canvas.drawPath(path, paint);
}
/**
* Method to handle touch screen motion events.
* #param event The motion event
* #return True if the event was handled, false otherwise.*/
#Override
public boolean onTouchEvent(MotionEvent event) {
float xPos = event.getX();
float yPos = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(xPos,yPos);
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(xPos,yPos);
break;
case MotionEvent.ACTION_UP:
break;
default:
return false;
}
invalidate();
return true;
}
public void clear(){
path = new Path();
invalidate();
}
}
And my Activity with Buttons:
import android.graphics.Canvas;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
public class DrawingScreen extends AppCompatActivity {
Button btn;
TouchEventDraw ted;
Canvas canva;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ted=new TouchEventDraw(this,null);
setContentView(R.layout.activity_drawing_screen);
btn=(Button) findViewById(R.id.button);
btn.setOnClickListener(onClickListener);
}
private final View.OnClickListener onClickListener=new View.OnClickListener() {
#Override
public void onClick(View v) {
ted.clear();
ted.invalidate();
}
};
}
You need to add a method to your TouchEventDraw class, and call the following in it
canva.drawColor(Color.WHITE);
Then on your button click, call the method you created.
You should be able to implement the solution with the information I supplied.
I think there are more fatal issues through your code though, as I see the following:
The view is never being put on screen.
You extend View, rather than SurfaceView.
Another way, you should be able to create a method, and instead set path empty
public void clear(){
path = new Path();
}
then change your draw to
#Override
protected void onDraw(Canvas canvas) {
if(path.isEmpty())
canvas.drawColor(Color.WHITE);
else
canvas.drawPath(path, paint);
}
and call View.invalidate();
I'm trying to scale the text continuously by changing text size. And I implement my own view to drawText on canvas every time the text size changed. But the procedure of invalidate and redraw canvas became very slow which lead to some animation became slow too.
The specific os version is 4.0.3(The application works well on the same kind device with os version 4.1.1)
The hardware acceleration is on.(works well when it's off)
I wrote a simple project to reproduce this issue.
The custom view:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class MyTextView extends View {
private Paint mPaint;
private float mTextSize = 80f;
public MyTextView(Context context) {
this(context, null);
}
public MyTextView(Context context, AttributeSet attr) {
super(context, attr);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setTextSize(mTextSize);
}
#Override
public void onDraw(Canvas canvas) {
canvas.save();
mPaint.setTextSize(mTextSize);
canvas.drawText("Test test test", 200, 200, mPaint);
canvas.restore();
mTextSize += 1f;
}
}
The Activity:
import android.os.Bundle;
import android.view.MotionEvent;
import android.app.Activity;
public class MainActivity extends Activity {
private MyTextView mTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (MyTextView)findViewById(R.id.text);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
mTextView.invalidate();
return true;
}
}
Finally I used StaticLayout.draw(Canvas) instead call Canvas.drawText
I am trying to draw an oval to the screen but all I am getting is a blank white canvas. Not only am I unsure whether I am drawing the oval correctly, but also am getting nothing to the screen. Does anyone know why this is happening, I think the problem is that it isnt getting to the drawing section of the thread...
package hidden;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.shapes.OvalShape;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnTouchListener;
public class Surface extends Activity implements OnTouchListener
{
SurfaceView v;
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
setRequestedOrientation(1);
v = new SView(this);
v.setOnTouchListener(this);
v.setZOrderOnTop(true);
setContentView(v);
}
public class SView extends SurfaceView implements Runnable
{
Thread t1 = null;
SurfaceHolder holder;
boolean isItOk = false;
public SView(Context context)
{
super(context);
holder = getHolder();
holder.setFormat(PixelFormat.TRANSPARENT);
}
public void run()
{
while(isItOk)
{
if(!holder.getSurface().isValid())
{
continue;
}
Canvas c = holder.lockCanvas();
Paint p = new Paint();
p.setColor(Color.BLUE);
//OvalShape oval = new OvalShape();
//oval.draw(c, p);
Paint paint = new Paint();
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.STROKE);
float leftx = 20;
float topy = 20;
float rightx = 50;
float bottomy = 100;
RectF ovalBounds = new RectF(leftx, topy, rightx, bottomy);
c.drawOval(ovalBounds, paint);
holder.unlockCanvasAndPost(c);
}
}
public void pause()
{
isItOk = false;
while(true)
{
try
{
t1.join();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
break;
}
t1 = null;
}
public void resume()
{
isItOk = true;
t1 = new Thread(this);
t1.start();
}
}
public boolean onTouch(View arg0, MotionEvent arg1)
{
return false;
}
}
At first my programm looks like this:
But when i am moving the picture around the screen programm turns to:
Red graph is random-generated in onDraw method. So i want to draging picture around and have static background that not inavalidates while im moving picture.
here is my code:
Custom View:
package com.graph.base;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;
import java.util.Random;
public class CustomView extends View
{
Random random=new Random();
public CustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomView(Context context) {
super(context);
}
public void onDraw (Canvas canvas)
{
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
canvas.drawPaint(paint);
Path path=new Path();
path.moveTo(10, 10);
for (float i=0.5f; i<=140; i+=10)
{
path.quadTo(10+i*5, 10+random.nextInt(500), 10+(i+10)*5, 10+random.nextInt(500));
}
paint.setDither(true);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(2);
canvas.drawPath(path, paint);
}
}
MainActivity
package com.graph.base;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
public class MainActivity extends Activity {
FrameLayout frame;
ImageView image;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
frame=(FrameLayout)findViewById(R.id.frameLayout1);
image=(ImageView)findViewById(R.id.imageView1);
image.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
Log.e("TAG", "Touch happend");
switch (event.getAction())
{
case MotionEvent.ACTION_MOVE:
{
image.setPadding((int)event.getX(), (int)event.getY(), 0, 0);
break;
}
}
return true;
}
});
}
public void invalidateButton_Click (View v)
{
frame.invalidate();
}
}
You're drawing random lines onto your canvas. This code is called each time the screen is invalidated. If you want to keep the drawing from changing, then set a bitmap into a canvas and draw into the bitmap. In your onDraw() method you'll then draw the bitmap onto the canvas.
// Outside of onDraw()
Bitmap bmDest = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas mycanvas = new Canvas(bmDest);
// Do your drawing on the canvas outside of the onDraw() method
In onDraw(), you'll simply do this:
canvas.drawBitmap(bmDest, x, y, null);
Actually, you should not "disable invalidate" but really do call "invalidate"...
In
case MotionEvent.ACTION_MOVE:
{
image.setPadding((int)event.getX(), (int)event.getY(), 0, 0);
// here call frame.invalidate(Rect dirty), with dirty set to where the image was previously
break;
}
Note that if your custom View draws "Randomly", then you can get a Bitmap with the cached version and draw from that (blit copy)
I am new to Android.My application requires to redraw a canvas circle over and over again. However, the speed of redraw is less than what I want. How may I increase the same.
My code is as follows:
--> ImagePracActivity.java
package com.pkg.ImagPrac;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
public class ImagePracActivity extends Activity {
//DrawView drawView;
movement mv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set full screen view
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
mv=new movement(getApplicationContext());
setContentView(mv);
mv.requestFocus();
}
}
--> movement.java
package com.pkg.ImagPrac;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
public class movement extends View implements OnTouchListener{
Display display;
float x=0,y=0;
Paint paint=new Paint();
private boolean flag;
public movement(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
paint.setColor(Color.BLUE);
paint.setAntiAlias(true);
display = ((WindowManager)
context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
x = 0;
y = display.getHeight();
}
#Override
protected void onDraw(Canvas canvas) {
if(x<(display.getWidth()/2))
{
canvas.drawCircle(x++, y--, 5, paint);
}
else if(x<(display.getWidth()))
{
canvas.drawCircle(x++, y++, 5, paint);
}
this.invalidate();
}
public boolean onTouch(View arg0, MotionEvent arg1) {
// TODO Auto-generated method stub
return false;
}
}
A would advice you to use SurfaceView class instead of View, because SurfaceView faster and allows you to have all drawing logic in separate thread. Read more about SurfaceView : http://developer.android.com/guide/topics/graphics/2d-graphics.html
try this
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLUE);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(5);