I want to make it so that pressing the screen moves my rectangle. The listener gives output to console but it doesn't invalidate the screen.
public class DrawView extends View{
Paint paint = new Paint();
static int x = 20;
static int y = 20;
public DrawView(Context context){
super(context);
paint.setColor(Color.GREEN);
}
#Override
public void onDraw(Canvas canvas){
canvas.drawRect(x,y,100,100,paint);
}
public void OTListener(){
setOnTouchListener(new OnTouchListener(){
public boolean onTouch(View DrawView, MotionEvent e){
x = 100;
y = 100;
invalidate();
return false;
}
});
}
}
Try this. It should work if it is the top view in your view hierarchy.
You'll have to check out event.getAction() if you want to do more advanced stuff in onTouchEvent()...
public class DrawView extends View {
Paint paintRect = new Paint();
Paint paintClear = new Paint();
private Point touch = new Point();
public DrawView(Context context){
super(context);
paintClear.setColor(Color.BLACK);
paintRect.setColor(Color.GREEN);
}
#Override
public void onDraw(Canvas canvas){
canvas.drawPaint(paintClear);
canvas.drawRect(touch.x-50,touch.y-50,touch.x+50,touch.y+50,paintRect);
}
private void touch(int x, int y) {
touch.set(x,y);
invalidate();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
touch((int)event.getX(), (int)event.getY());
return true;
}
}
Using invalidate() in another method doesn't work. You need to use postinvalidate() if you want to refresh activity from another method.
Related
I am new to android programing. I am trying to draw a new bitmap image every time the user touches the screen. With the current code right now, all it does is change where the bitmap is at. It doesn't make a new one. How could I make a new one?? Here is the code:
public class MainDrawingView extends View {
public float eventX;
public float eventY;
public AlertDialog.Builder alertThing;
Context context = getContext();
//Bitmaps
public Bitmap redSquare;
public String x;
public String y;
//Colors
public boolean red = false;
public boolean blue = false;
//Squares
public boolean topRight = false;
public boolean topLeft = false;
public boolean bottomLeft = false;
public boolean bottomRight = false;
public int width = context.getResources().getDisplayMetrics().widthPixels;
public int height = context.getResources().getDisplayMetrics().heightPixels;
public int center = height/2;
public int widthDiv = width/2;
private Paint paint = new Paint();
private Point pointStart = new Point();
private Point pointEnd = new Point();
public MainDrawingView(Context context, AttributeSet attrs){
super(context, attrs);
paint.setAntiAlias(true);
paint.setStrokeWidth(5f);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
alertThing = new AlertDialog.Builder(context);
//define bitmap
redSquare = BitmapFactory.decodeResource(getResources(), R.drawable.red);
}
#Override
public void onDraw(Canvas canvas){
//canvas.drawPath(path, paint);
canvas.drawLine(pointStart.x, pointStart.y, pointEnd.x, pointEnd.y,paint);
//Makes a straight line go through the center of the screen.
canvas.drawLine(0,height/2.5f, width,height/2.5f,paint);
//Makes a straight line go up and down.
canvas.drawLine(width/2.3f,0, width/2.3f, height,paint);
//Chnages the square colors.
// top left combo
if(topLeft){
if(red){
Toast.makeText(context,"jgjgjgjgjgjgjgjgjjg", Toast.LENGTH_SHORT).show();
new Drawings(redSquare, canvas, eventX, eventY);
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event){
//Gets the coords of the tap
eventX = event.getX();
eventY = event.getY();
int pointX = Math.round(eventX);
int pointY = Math.round(eventY);
x = String.valueOf(eventX);
y = String.valueOf(eventY);
//This is the top left "square"
if(eventY < center && eventX < widthDiv ){
alertThing.setTitle("edit square");
alertThing.setMessage("please choose an option");
alertThing.setPositiveButton("red", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
topLeft = true;
red = true;
invalidate();
}
});
alertThing.setNeutralButton("Chnange color to blue", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
alertThing.create();
alertThing.show();
}
Toast.makeText(context, "center is :" +x, Toast.LENGTH_SHORT ).show();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
//Sets a new starting point
pointStart.set(pointX,pointY);
return true;
case MotionEvent.ACTION_UP:
//Contects the points
pointEnd.set(pointX,pointY);
break;
default:
return false;
}
invalidate();
return true;
}
}
Here is the Drawings class that draws the bitmaps:
public class Drawings {
public Drawings(Bitmap bitmap, Canvas canvas,float x, float y){
canvas.drawBitmap(bitmap, x,y,null);
}
}
You really should see what canvas.drawBitmap does. Of course it changes the position, since the touch position changes too.
You create a new bitmap just like you did it when defining bitmap.
But creating new objects in the onDraw will be very slow.
I ran into this app concept by Oleg Frolov on Dribble.
The implementation seems pretty basic, with a horizontal ScrollView and a button which triggers the reveal animation.
I want to know :-
How to implement the vertical ProgressBar as the background of the
countdown activity
How to sync the progress of the ProgressBar, and the TextView's text change with the Chronometer/ System clock.
this project show you how to implement such a progress bar.
that is very simple to do with a custom drawable, there's no need to use libraries.
below is an UNTESTED example on how to do it.
public class CustomDrawable extends Drawable {
private final int color1;
private final Paint paint;
float level;
public CustomDrawable(int color1, int color2) {
this.color1 = color1;
paint = new Paint();
paint.setColor(color2);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
}
#Override protected boolean onLevelChange(int level) {
invalidateSelf();
return true;
}
#Override public void draw(Canvas canvas) {
canvas.drawColor(color1);
level = getLevel() / 100f;
canvas.drawRect(
0,
canvas.getHeight() * level, // tweak this line if not drawing properly
canvas.getWidth(),
canvas.getHeight(), paint);
}
#Override public void setAlpha(int alpha) {
}
#Override public void setColorFilter(ColorFilter colorFilter) {
}
#Override public int getOpacity() {
return 0;
}
}
on the background view just use this drawable like:
background.setBackground(new CustomDrawable(color1, color2));
then to update the value u call
background.getBackground().setLevel(... between 0-100...);
i want to return true to my method touch, when the sprite is touched (also with the finger) how can I make?
public class SkipButton extends RectangleButton
{
protected TextureAtlas atlasTexture;
protected Sprite sprite;
protected SpriteBatch batch ;
public SkipButton(Vector2 coordinates, float width, float height)
{
super(coordinates, width, height);
atlasTexture = Assets.manager.get(Constants.INTERFACE_ATLAS_PATH,
TextureAtlas.class);
sprite = new Sprite(atlasTexture.findRegion("skip_big"));
}
#Override
public void draw(SpriteBatch batch)
{
sprite.draw(batch);
}
public boolean touch()
{
...........
}
Libgdx has a great Button class which has included a boolean isPressed() which will do what you want. You can still make a public method that returns the result of isPressed if you want your button to be private.
atlasTexture = Assets.manager.get(Constants.INTERFACE_ATLAS_PATH,
TextureAtlas.class);
Drawable drawable = new TextureRegionDrawable(atlasTexture.findRegion("skip_big"));
button = new Button(drawable);
stage.addActor(button);
public boolean touch() {
return button.isPressed();
}
I wanted to use a SurfaceView with a "sticky" canvas. i.e. one that preserves its state and does not get ivalidated. I followed an example that showed how to set up a holder and use a separate thread for the drawing. The idea is that when touching anywhere on the SurfaceView, drawStuff will be called, given some paint, and a random rectangle should be drawn.
Although the code executes perfectly, nothing is drawn at the end.
public class DrawingView extends SurfaceView implements Callback {
Paint currentPaint;
float verts[];
private Boolean drawing = false;
class DrawingThread extends Thread {
private SurfaceHolder surfaceHolder;
private SurfaceView surfaceView;
private Boolean isRunning = false;
public void setIsRunning(Boolean isRunning) {
this.isRunning = isRunning;
}
public DrawingThread(SurfaceHolder surfaceHolder, SurfaceView surfaceView) {
super();
this.surfaceHolder = surfaceHolder;
this.surfaceView = surfaceView;
}
#Override
public void run() {
while(isRunning) {
Canvas c = surfaceHolder.lockCanvas();
surfaceView.draw(c);
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
DrawingThread thread;
public DrawingView(Context context) {
super(context);
this.setWillNotDraw(false);
this.setBackgroundColor(Color.WHITE);
this.getHolder().addCallback(this);
this.thread = new DrawingThread(getHolder(), this);
}
#Override
protected void onDraw(Canvas canvas) {
if (drawing) {
// TEST CODE. WILL NEVER USE THIS IN PRODUCTION
canvas.drawRect(new Rect(new Float(Math.random()*200).intValue(), 20, new Float(Math.random()*200).intValue(), 30), currentPaint);
drawing = false;
}
}
public void drawStuff(Paint paint) {
currentPaint = paint;
drawing = true;
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
thread.setIsRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
thread.setIsRunning(false);
}
}
and the paint set up:
view.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLUE);
paint.setAlpha(55);
((DrawingView) v).drawStuff(paint);
//v.invalidate();
return false;
}
});
In the end, you're not actually drawing things when you think you are. Calling draw() schedules the draw on your UI thread, but doesn't actually call onDraw from your background thread so your Canvas is no longer valid with respect to the surface. You should render whatever you are doing into a Bitmap object and when you are ready to write to the surface, notify the UI thread. The UI thread can then lock the surface, draw the bitmap into the Canvas, then unlock and post the Canvas to the surface.
I have been developing the application for drawing and I have some problems: the mean for drawing by a finger has been done already, but now I need to make anything that allow user to write a common text label on a View. So, please, look at my code:
public class PainterView extends View implements DrawingListener {
private Painter painter;
private Bitmap bitmap;
private Paint bitmapPaint;
private Path path;
private Paint paint;
public PainterView(Context context, Painter painter) {
super(context);
this.painter=painter;
this.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
PainterView.this.painter.touchStart(x, y);
break;
case MotionEvent.ACTION_MOVE:
PainterView.this.painter.touchMove(x, y);
break;
case MotionEvent.ACTION_UP:
PainterView.this.painter.touchUp();
break;
}
return true;
}
});
this.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Log.e("event", "click");
}
});
this.setOnLongClickListener(new OnLongClickListener() {
public boolean onLongClick(View v) {
Log.e("event", "long");
return true;
}
});
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
protected void onDraw(Canvas canvas) {
if (bitmap!=null) {
canvas.drawBitmap(bitmap, 0, 0, bitmapPaint);
canvas.drawPath(path, paint);
}
}
public void onPictureUpdate(Bitmap bitmap, Paint bitmapPaint, Path path, Paint paint) {
this.bitmap=bitmap;
this.bitmapPaint=bitmapPaint;
this.path=path;
this.paint=paint;
invalidate();
}
public void setPainter(Painter painter) {
this.painter=painter;
}
}
It's code for drawing; the process of drawing is in Painter class. So, now I need to allow user to write a simple text. I thought that I can do it using long clicks - user do a long click, keypad is opened, and user can input a text. But it doesn't work! I don't see any strings in my Log.
Please, tell me advice about my problem or some idea how I can realize what I need.
I'm pretty sure the OnTouchListener is consuming the touch event when you return true. Try return super.onTouch(v, event).