Android doubling number of touches? - java

This android app is acting as if I had double tapped it each time I touch the screen, can anyone see why is this happening? I have it log "touch # " + [the number of touches] and it does "touch 1" and "touch 2" at the same time, same as "touch 3" and "touch 4"
package com.example.mondrianmaker;
import java.util.ArrayList;
import java.util.Random;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MainActivity extends Activity {
int width, height, x, y, color, touch;
ArrayList<Rectangle> rectangles, childsRect;
Bitmap bg;
Canvas canvas;
Display display;
LinearLayout ll;
Point size;
Paint paint;
Random rn;
Rectangle parentRect;
TextView text, info;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//***FULL SCREEN***
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
//---FULL SCREEN---
setContentView(R.layout.activity_main);
display = getWindowManager().getDefaultDisplay();
size = new Point();
display.getSize(size);
width = size.x;
height = size.y;
paint = new Paint(); //paint to color rectangle OBLI
bg = Bitmap.createBitmap(480, 800, Bitmap.Config.ARGB_8888);
canvas = new Canvas(bg);
ll = (LinearLayout) findViewById(R.id.mondrian);
rectangles = new ArrayList<Rectangle>();
text = (TextView) findViewById(R.id.coordinates);
info = (TextView) findViewById(R.id.info);
parentRect = new Rectangle(0, 0, 480, 800); //create super parent rectangle
rectangles.add(parentRect); //add super parent rectangle to list
touch = 0;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
//Get Coordinate
x = (int) event.getX();
y = (int) event.getY();
//set text view to clicked coordinates and number of rectangles on list
text.setText(x + ", " + y + " rectangles: "+rectangles.size());
//set rectangle color *randomly
setColor();
paint.setColor(color);
//get rectangle clicked
parentRect = getRectParent(x, y);
//make children of rectangle clicked
childsRect = makeChilds(parentRect, x, y);
addChildsToRectanglesDeleteParentRect(childsRect, parentRect);
//check on childs
// text.setText(childsRect.get(0) + " " + childsRect.get(1));
//get onTouch action
switch (event.getAction()) {
// case MotionEvent.ACTION_DOWN:
// text.setText(x + ", " + y);
// ll.setBackgroundDrawable(new BitmapDrawable(bg));
// case MotionEvent.ACTION_MOVE:
// ll.setBackgroundDrawable(new BitmapDrawable(bg));
// System.out.println("22222");
case MotionEvent.ACTION_UP:
touch++;
Log.i("info", "touch # " + touch);
// ll.setBackgroundDrawable(new BitmapDrawable(bg));
// System.out.println("33333");
}
return false;
}
public void addChildsToRectanglesDeleteParentRect(ArrayList<Rectangle> childsRect, Rectangle parentRect){
rectangles.remove(parentRect);
rectangles.add(childsRect.get(0));
rectangles.add(childsRect.get(1));
int i = 0;
Log.i("info", "length= "+rectangles.size());
for(Rectangle e : rectangles){
Log.i("info", i+"--> "+ e.toString());
i++;
}
}
public ArrayList<Rectangle> makeChilds(Rectangle parent, int x, int y){
ArrayList<Rectangle> defaults = new ArrayList<Rectangle>();
defaults.add(new Rectangle(0,0,240,800));
defaults.add(new Rectangle(240,0, 480, 800));
ArrayList<Rectangle> childs = new ArrayList<Rectangle>();
for(Rectangle rect : rectangles){
if(x>=rect.getX1() && x<=rect.getX2() && y>=rect.getY1() && y<=rect.getY2()){
childs.add(new Rectangle(rect.getX1(), rect.getY1(), rect.getX2()/2, rect.getY2()/2));
childs.add(new Rectangle(rect.getX2()/2, rect.getY2()/2, rect.getX2(), rect.getY2()));
}
}
if(childs.size()>0){
return childs;
}else{
info.setText(x + ", " + y + " " + parent + "no childs for this parent");
return defaults;
}
}
public Rectangle getRectParent(int x, int y){
for(Rectangle g : rectangles){
if (x > g.getX1() && x < g.getX2() && y > g.getY1() && y < g.getY2()){
info.setText(info.getText() + "\n " + g.getX1()+"_x=" + x +"_"+g.getX2() +"\n"+g.getY1()+"_y="+y+"_"+g.getY2());
return g;
}
}
return null;
}
public void setColor(){
rn = new Random();
switch ((int) Math.floor(rn.nextDouble() * 5)) {
case 0:
color = Color.BLACK;
break;
case 1:
color = Color.RED;
break;
case 2:
color = Color.YELLOW;
break;
case 3:
color = Color.WHITE;
break;
case 4:
color = Color.GREEN;
break;
}
}
}

You're probably getting an ACTION_DOWN and an ACTION_MOVE and counting both.
Try moving your ++ to inside the switch case for ACTION_DOWN.

I tested your code and works without any issue however you can try using if statement. Also make sure your switch statement return true or break; tho it works without using any of them; here how you can use if statement:
if(event.getAction() == MotionEvent.ACTION_UP){
// up is called
touch++;
Log.i("info", "touch # " + touch);
return true;
}

Related

How i make movable perticuler dots on image with x y position in android?

I Have a image and i want to make a 8 dot on image, that dot are move when touch dot and drag to screen, is this possible to make that type of touch and movable dots on image?
Show above image on 8 point , i want to result like this image and also that point are move when you touch that point and move on image and also want that point x,y coordinate .
i tried below code but its show dots are not in proper form , and all dots move at the same time.
class DrawingView extends View {
Bitmap bitmap;
float x, y;
public DrawingView(Context context) {
super(context);
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_dot);
}
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
}
break;
case MotionEvent.ACTION_MOVE: {
x = (int) event.getX();
y = (int) event.getY();
invalidate();
}
break;
case MotionEvent.ACTION_UP:
x = (int) event.getX();
y = (int) event.getY();
System.out.println(".................." + x + "......" + y); //x= 345 y=530
invalidate();
break;
}
return true;
}
#Override
public void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
// canvas.drawBitmap(bitmap, x, y, paint); //originally bitmap draw at x=o and y=0
for (int i = 0; i < 8; i++) {
canvas.drawBitmap(bitmap, x++, y++, null);
}
}
}
if anyone know about that type of view or any solution for it then help.
Thanks in advance :)
Create a custom ImageView which extends the androidx.appcompat.widget.AppCompatImageView class, which implements an OnTouchListener with an ArrayList<Dot> which will keep track of the Dots.
You override onDraw(Canvas canvas) of the custom ImageView and iterate through the ArrayList of Dots and draw each Dot in the list using canvas.drawCircle(float cx, float cy, float radius, #NonNull Paint paint).
Whenever MotionEvent.ACTION_DOWN is fired you check if the touch was inside an existing dot.
If it was you set that Dot to a global variable i.e. touchedDot, when the users moves OnTouchListener fires MotionEvent.ACTION_MOVE which you then check if touchedDot != null and if so simply change its x and y to match the events via touchedDot.x = event.getX() and touchedDot.y = event.getY() and then call invalidate() which will call the ImageViews onDraw method and the dot will be moved as the users finger moves. When the user lifts their finger either from a touch or a move, MotionEvent.ACTION_UP is fired, there you simply check if touchedDot == null and if so you then create a new Dot at the x and y they touched in, otherwise you set touchedDot = null to reset it for the next move or touch event.
Here is an example I created using Picasso to load the image into the custom ImageView:
build.gradle:
dependencies {
...
implementation 'com.squareup.picasso:picasso:2.71828'
}
AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
DrawableDotImageView.java:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.ArrayList;
public class DrawableDotImageView extends androidx.appcompat.widget.AppCompatImageView implements View.OnTouchListener {
private final ArrayList<Dot> dots = new ArrayList<>();
private Paint dotPaint;
private Dot touchedDot;
public DrawableDotImageView(#NonNull Context context) {
super(context);
setup();
}
public DrawableDotImageView(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
setup();
}
public DrawableDotImageView(#NonNull Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setup();
}
private void setup() {
setOnTouchListener(this);
dotPaint = new Paint();
dotPaint.setColor(Color.WHITE);
dotPaint.setAlpha(100);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
dots.forEach((dot) -> {
canvas.drawCircle(dot.getX(), dot.getY(), dot.getRadius(), dotPaint);
Log.d("ImageView", "Drawing X: " + dot.x + " Y: " + dot.y);
});
}
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
dots.forEach((dot) -> {
if (dot.isInside(event.getX(), event.getY())) {
touchedDot = dot;
Log.d("ImageView", "Dot touched");
}
});
break;
case MotionEvent.ACTION_MOVE:
if (touchedDot != null) {
touchedDot.x = event.getX();
touchedDot.y = event.getY();
invalidate();
Log.d("ImageView", "Dot moving X: " + touchedDot.x + " Y: " + touchedDot.y);
}
break;
case MotionEvent.ACTION_UP:
if (touchedDot != null) {
touchedDot = null;
} else {
dots.add(new Dot(event.getX(), event.getY(), 35));
invalidate();
Log.d("ImageView", "Dot created X: " + event.getX() + " Y: " + event.getY());
}
break;
case MotionEvent.ACTION_CANCEL:
break;
default:
break;
}
return true;
}
private static class Dot {
private float x;
private float y;
private final float radius;
public Dot(float x, float y, float radius) {
this.x = x;
this.y = y;
this.radius = radius;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public float getRadius() {
return radius;
}
//https://www.geeksforgeeks.org/find-if-a-point-lies-inside-or-on-circle/
public boolean isInside(float x, float y) {
return (getX() - x) * (getX() - x) + (getY() - y) * (getY() - y) <= radius * radius;
}
}
}
TestFrament.xml: (change package name according to your own)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">
<com.example.myapplicationjava.DrawableDotImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY" />
</androidx.constraintlayout.widget.ConstraintLayout>
TestFrament.java:
#Override
public void onViewCreated(#NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
DrawableDotImageView imageView = view.findViewById(R.id.imageView);
Picasso.get().load("https://i.pinimg.com/originals/d4/d8/a0/d4d8a016155f00165411066bb9a0ab42.jpg").into(imageView);
}
Which produces:

How to change the height and width of button and add buttons through drawable canvas in android studio?

I made the snake and ladder game in android studio. I want to change the height and width of the buttons, and I want to add one more button for exit. Right now I am using only one .png file for all buttons. So, How to change it? When i add the fourth button my application crash and its shows the error.
Check this image
Error
FATAL EXCEPTION: main
Process: com.sixtinbyte.snakeandladder, PID: 25115
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.sixtinbyte.snakeandladder.components.GameButton.onDraw(android.graphics.Canvas)' on a null object reference
at com.sixtinbyte.snakeandladder.HomeView.onDraw(HomeView.java:151)
HomeView. java (This are the java file where i want to change because this is the homescreen of the game)
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.view.MotionEvent;
import android.view.View;
import com.sixtinbyte.snakeandladder.components.GameButton;
import com.sixtinbyte.snakeandladder.constant.Sound;
public class HomeView extends View {
public Context ctx;
private Resources res;
private String refText ="Snakes and Ladders";
private GameButton gButton, sButton, hButton,eButton;
private Bitmap logo, play, settings, help, exit;
private int hWidth, hHeight;
private Point touchCoordinate = new Point();
public HomeView(Context ctx) {
super(ctx);
this.ctx = ctx;
res = getResources();
logo = BitmapFactory.decodeResource(res, R.drawable.snakes_n_ladders);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO: Implement this method
super.onSizeChanged(w, h, oldw, oldh);
hWidth = w;
hHeight = h;
preparePlayButton();
prepareSettingsButton();
prepareHelpButton();
// prepareExitButton();
}
private void preparePlayButton() {
String text =" ";
int textSize = 40;
Point po = getBmpMeasureFrom(text, refText, textSize);
play = getBitmap(R.drawable.play, po.x, po.y);
gButton = new GameButton(play, text, textSize);
gButton.setLocation((hWidth - po.x) / 2, (int)(hHeight * 0.6f));
gButton.setTextColor(Color.CYAN);
}
private void prepareSettingsButton() {
String text =" ";
int textSize = 40;
Point po = getBmpMeasureFrom(text, refText, textSize);
settings = getBitmap(R.drawable.play, po.x, po.y);
sButton = new GameButton(settings, text, textSize);
sButton.setLocation((hWidth - po.x) / 2, (int)(hHeight * 0.7f));
sButton.setTextColor(Color.CYAN);
}
//
//
private void prepareHelpButton() {
String text =" ";
int textSize = 40;
Point po = getBmpMeasureFrom(text, refText, textSize);
help = getBitmap(R.drawable.play, po.x, po.y);
hButton = new GameButton(help, text, textSize);
hButton.setLocation((hWidth - po.x) / 2, (int)(hHeight * 0.8f));
hButton.setTextColor(Color.CYAN);
}
// private void prepareExitButton() {
// String text =" ";
// int textSize = 40;
// Point po = getBmpMeasureFrom(text, refText, textSize);
// help = getBitmap(R.drawable.play, po.x, po.y);
// hButton = new GameButton(help, text, textSize);
// hButton.setLocation((hWidth - po.x) / 2, (int)(hHeight * 0.8f));
// hButton.setTextColor(Color.CYAN);
//
// }
private Point getBmpMeasureFrom(String text, String refText, int textSize) {
Point p = new Point();
Paint pa = new Paint();
pa.setTextSize(textSize);
p.y = (int)(pa.getTextSize() * 2.2f);
String tt = refText.length() > text.length() ?refText: text;
p.x = (int) (pa.measureText(tt) * 1.2f);
return p;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO: Implement this method
int evt = event.getAction();
touchCoordinate.x = (int)event.getX();
touchCoordinate.y = (int)event.getY();
switch (evt) {
case MotionEvent.ACTION_DOWN:
MainActivity.playSound(Sound.BUTTON_CLICK_1, false);
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
// MainActivity.stopSound();
if (gButton.contains(touchCoordinate)) {
Intent intent = new Intent(ctx, GameActivity.class);
ctx. startActivity(intent);
}
if (sButton.contains(touchCoordinate)) {
Intent intent = new Intent(ctx, Playing.class);
ctx.startActivity(intent);
}
if (hButton.contains(touchCoordinate)) {
Intent intent = new Intent(ctx, Aboutus.class);
ctx. startActivity(intent);
}
// if(eButton.contains(touchCoordinate)){
// Intent intent = new Intent(ctx, Exit.class);
// ctx.startActivity(intent);
// }
break;
}
return true;
}
#Override
protected void onDraw(Canvas canvas) {
// TODO: Implement this method
super.onDraw(canvas);
canvas.drawColor(Color.CYAN);
canvas.drawBitmap(logo, (hWidth - logo.getWidth()) / 2, (int)((hHeight - logo.getHeight()) * 0.1), null);
gButton.onDraw(canvas);
sButton.onDraw(canvas);
hButton.onDraw(canvas);
// eButton.onDraw(canvas);
// Paint p= new Paint();
// p.setColor(Color.RED);
// canvas.drawRect(100, 200, 400, 500, p);
invalidate();
}
private Bitmap getBitmap(int drawableRes, int width, int height) {
Drawable d = res.getDrawable(drawableRes);
Canvas c = new Canvas();
Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
c.setBitmap(b);
d.setBounds(0, 0,width, height);
d.draw(c);
return b;
}
}
The prepareExitButton method is assigning hButton, I think it should be assigning eButton. That's why you're getting a NullPointerException there. Also, you're setting the y-coordinate to (int)(hHeight * 0.8f)) which means it will overlap with the help-button.
You may need to alter the GameButton class to get the ability to adjust the button's size. In particular, you'll want to change onDraw to draw the button in the specified size.

Faster way of displaying offscreen bitmap using android/java

I have started to learn android and java using the android studio beta. As a first simple test app I am trying to get a basic Mandelbrot renderer working. I have gotten it to display, but now I want it faster. Can anyone give advice on the following?
The docs say canvas.drawbitmap is depreciated. What should I use instead? What is the fastest ways to show a bitmap onscreen?
How can I show the progress of the calculations? If I unremark the 2 lines marked "update display after each line has been calculated" there is no updating during the calculations and the extra calls to canvas.drawbitmap really slow it all down (79 seconds compared to 31 seconds without it).
Is there anything I can do to speed up the general math calls?
I have tried to keep it as simple as possible for this example.
Many thanks for any tips for a newbie. I don't want to learn bad habits from the start if possible.
The layout has a single imageview aligned to the screen. The full code is
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.Display;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import java.text.DecimalFormat;
import java.util.Random;
import static android.graphics.Color.argb;
import static android.graphics.Color.rgb;
public class myActivity extends Activity {
myView myview;
Bitmap bmp;
Canvas myCanvas;
ImageView img;
Paint paint;
Boolean started=false;
Integer ih,iw,i,redraws,fw,fh;
long startms,finishms;
Random rnd;
double xmin,xmax,ymin,ymax,padding,bailout,bailout_squared,stepx,stepy,x,y,magnitude;
double realiters,tweenval;
Integer col,colval1,colval2;
Integer iterations,maxiterations,superx,supery,samplepixels,square_samplepixels,xloop,yloop;
double zr,zi,cr,ci,xloopdouble,yloopdouble;
int[] colorpalette = new int[256];
int[] pixels;
int r,g,b,r1,g1,b1,r2,g2,b2,totalr,totalg,totalb;
private void init(){
//screen size
Display display = getWindowManager().getDefaultDisplay();
Point sizePoint = new Point();
paint = new Paint();
display.getSize(sizePoint);
iw=sizePoint.x;
ih=sizePoint.y;
//pixels array
fw=iw;
fh=ih;
pixels=new int[fw*fh];
//create bitmap
bmp=Bitmap.createBitmap(iw, ih, Bitmap.Config.RGB_565);
//create canvas
myCanvas =new Canvas();
myCanvas.setBitmap(bmp);
img = (ImageView) findViewById(R.id.imageView1);
rnd = new Random();
}
// calculates and displays the Mandelbrot fractal
private void Mandelbrot(){
startms= SystemClock.uptimeMillis();
//coordinates
// xmin=-1.6345100402832;
// xmax=-1.63043992784288;
// ymin=-0.00209962230258512;
// ymax=0.00209259351094558;
xmin=-2.3;
xmax=2.3;
ymin=-2.1;
ymax=2.1;
fw=iw;
fh=ih;
//adjust coords to match screen aspect
if (iw<ih) {
padding=(xmax-xmin)/iw*(ih-iw);
ymin=ymin-padding/2.0;
ymax=ymax+padding/2.0;
} else {
padding=(ymax-ymin)/ih*(iw-ih);
xmin=xmin-padding/2.0;
xmax=xmax+padding/2.0;
}
bailout=8.0; //needs to be higher than default 2 for the CPM coloring to be smooth
bailout_squared=bailout*bailout;
maxiterations=64;
samplepixels=1;
square_samplepixels=samplepixels*samplepixels;
//random color palette
for (col=0;col<256;col++){
colorpalette[col]=android.graphics.Color.argb(255,rnd.nextInt(256),rnd.nextInt(256),rnd.nextInt(256));
}
stepx=(xmax-xmin)/fw/samplepixels;
stepy=(ymax-ymin)/fh/samplepixels;
for (yloop=0;yloop<fh;yloop++){
for (xloop=0;xloop<fw;xloop++){
totalr=0;
totalg=0;
totalb=0;
r=0;
g=0;
b=0;
xloopdouble=(double)xloop;
yloopdouble=(double)yloop;
for (supery=0;supery<samplepixels;supery++)
{
for (superx=0;superx<samplepixels;superx++)
{
cr = xmin+xloopdouble/(double)fw*(xmax-xmin)+(stepx*(double)superx);
ci = ymin+yloopdouble/(double)fh*(ymax-ymin)+(stepy*(double)supery);
zr = 0.0;
zi = 0.0;
magnitude=0.0;
for(iterations=0; iterations<maxiterations; iterations++)
{
i=iterations;
x = (zr * zr - zi * zi) + cr;
y = (zi * zr + zr * zi) + ci;
magnitude=(x * x + y * y);
if(magnitude>bailout_squared) break;
zr = x;
zi = y;
}
if (iterations>=maxiterations) {
r=0;
g=0;
b=0;
} else {
//CPM smooth colors
realiters=iterations+1-((Math.log(Math.log(Math.sqrt(magnitude)))/Math.log(2.0)));
colval1=(int) Math.floor(realiters % 255);
colval2=(colval1+1) % 255;
tweenval=realiters-Math.floor(realiters);
r1=Color.red(colorpalette[colval1]);
g1=Color.green(colorpalette[colval1]);
b1=Color.blue(colorpalette[colval1]);
r2=Color.red(colorpalette[colval2]);
g2=Color.green(colorpalette[colval2]);
b2=Color.blue(colorpalette[colval2]);
r=(int) (r1+((r2-r1)*tweenval));
g=(int) (g1+((g2-g1)*tweenval));
b=(int) (b1+((b2-b1)*tweenval));
}
totalr=totalr+r;
totalg=totalg+g;
totalb=totalb+b;
}
}
r=(int) totalr/square_samplepixels;
g=(int) totalg/square_samplepixels;
b=(int) totalb/square_samplepixels;
//update pixels array
pixels[xloop+yloop*fw]=rgb(r, g, b);
}
//update display after each line has been calculated
//myCanvas.drawBitmap(pixels,0,fw,0,0,fw,fh,false,null);
//if (img != null) img.invalidate();
}
myCanvas.drawBitmap(pixels,0,fw,0,0,fw,fh,false,null);
finishms=SystemClock.uptimeMillis();
}
private void updateTimeTaken(){
//turn antialiasing on
paint.setAntiAlias(true);
// draw some text using FILL style
paint.setStyle(Paint.Style.FILL);
paint.setTextSize(30);
DecimalFormat myFormatter = new DecimalFormat("#,###,###");
paint.setColor(Color.BLACK);
myCanvas.drawText("Time taken = " + myFormatter.format(finishms - startms) + " ms", 15, 45, paint);
paint.setColor(Color.WHITE);
myCanvas.drawText("Time taken = " + myFormatter.format(finishms - startms) + " ms", 14, 44, paint);
paint.setColor(Color.BLACK);
myCanvas.drawText("Screen size = " + String.valueOf(iw) + " x " + String.valueOf(ih), 15, 85, paint);
paint.setColor(Color.WHITE);
myCanvas.drawText("Screen size = " + String.valueOf(iw) + " x " + String.valueOf(ih), 14, 84, paint);
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
//fullscreen no menu
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
redraws=0;
super.onCreate(savedInstanceState);
myview = new myView(this);
setContentView(myview);
init();
started=true;
Mandelbrot();
updateTimeTaken();
}
private class myView extends View{
public myView(Context context){
super(context);
}
#Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//draw off screen bitmap to screen
if (started==true){
canvas.drawBitmap(bmp,0,0,paint);
}
}
}
}

Bitmap images saving

##MyDraw.java##
This part of the code is where the bitmap image is created, the bitmap sits on the canvas, form this point I want to be able to save the image that is created on the bitmap, I have a drop down menu in the MainActivity with a 'save' option.
package com.example.save_file;
import java.util.Random;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.View;
import android.view.MotionEvent;
public class MyDraw extends View
{
Canvas c;
Bitmap bmp;
Paint paint;
Random g;
float X, Y;
public MyDraw (Context context)
{
super(context);
g = new Random ();
Bitmap.Config conf = Bitmap.Config.ARGB_8888;
bmp = Bitmap.createBitmap (1100, 1800, conf);
paint = new Paint ();
paint.setStyle (Paint.Style.STROKE);
paint.setColor (Color.WHITE);
this.setOnTouchListener (new OnTouchListener()
{
public boolean onTouch (View v, MotionEvent event)
{
int h, w, R, G, B, A;
float x, y;
c = new Canvas (bmp);
x = event.getX ();
y = event.getY ();
System.out.printf ("%f %f\n", X, Y);
paint.setAntiAlias (true);
w = g.nextInt (70)+90;
h = g.nextInt (70);
R = g.nextInt (255);
G = g.nextInt (255);
B = g.nextInt (255);
A = g.nextInt (255);
paint.setStyle (Paint.Style.FILL);
paint.setColor ((A << 24) + (R << 16) + (G << 8) + (B << 0));
if (MyApp.fill == 0) // FILLED SHAPE
{
paint.setStyle (Paint.Style.FILL);
paint.setColor ((A << 24) + (R << 16) + (G << 8) + (B << 0));
if (MyApp.shape == 0)
c.drawRect (x, y, x + w, y + h, paint);
else
c.drawOval(new RectF (x, y, x + w, y + h), paint);
paint.setStyle (Paint.Style.STROKE);
paint.setColor (Color.BLACK);
if (MyApp.shape == 0)
c.drawRect (x, y, x + w, y + h, paint);
else
c.drawOval(new RectF (x, y, x + w, y + h), paint);
}
else // OUTLINED SHAPE
{
paint.setStyle (Paint.Style.STROKE);
paint.setColor ((A << 24) + (R << 16) + (G << 8) + (B << 0));
if (MyApp.shape == 0)
c.drawRect (x, y, x + w, y + h, paint);
else
c.drawOval(new RectF (x, y, x + w, y + h), paint);
}
paint.setColor (Color.WHITE);
invalidate ();
return true;
}
});
}
#Override
protected void onDraw (Canvas c)
{
super.onDraw (c);
c.drawBitmap (bmp, 0, 0, paint);
}
}
##MyApp.java##
package com.example.save_file;
public class MyApp
{
static public int shape = 0;
static public int fill = 0;
}
##MainActivity.java##
This is the part of the code where the menu code is, I want to be able to pres the save button here and for the bitmap image to be saved to the phone, preferably a standard gallery folder.
package com.example.save_file;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Random;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.view.Menu;
import android.view.MenuItem;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.view.Menu;
//import android.gesture.GestureOverlayView;
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
MyDraw d = new MyDraw (this);
setContentView (d);
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
super.onCreateOptionsMenu (menu);
MenuItem menu1 = menu.add(0, 0, Menu.NONE, "Filled Shape");
MenuItem menu2 = menu.add(0, 1, Menu.NONE, "Outline Shape");
MenuItem menu3 = menu.add(0, 2, Menu.NONE, "Rectangle");
MenuItem menu4 = menu.add(0, 3, Menu.NONE, "Oval");
MenuItem menu5 = menu.add(0, 4, Menu.NONE, "Save!");
return true;
}
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case 0:
MyApp.fill = 0;
return true;
case 1:
MyApp.fill = 1;
return true;
case 2:
MyApp.shape = 0;
return true;
case 3:
MyApp.shape = 1;
return true;
default:
return super.onOptionsItemSelected(item);
case 4:
bmp.setDrawingCacheEnabled(true);
Bitmap bitmap = bmp.getDrawingCache();
File root = Environment.getExternalStorageDirectory();
File file = new
File(root.getAbsolutePath()+"/DCIM/Camera/img.jpg");
try
{
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 100, ostream);
ostream.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
I use this code to save any graphic drawed using canvas, like fingerpaint or similar, I hope can be useful for your case
Set the instance as global
MyDraw d;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
d = new MyDraw (this);
setContentView (d);
}
And put this in the case of your onOptionsItemSelected();
case 4:
try {
Bitmap bitmap = Bitmap.createBitmap(d.getWidth(),d.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
d.draw(canvas);
File folder = new File(Environment.getExternalStorageDirectory()+ "/DCIM/Camera/");
if (!folder.exists())
folder.mkdirs();
String fileName = Environment.getExternalStorageDirectory()+ "/DCIM/Camera/img.jpg"";
if (new File(fileName).exists())
new File(fileName).delete();
OutputStream stream = new FileOutputStream(fileName);
/*
* Write bitmap to file using JPEG or PNG and 100% quality hint
* for JPEG.
*/
bitmap.compress(CompressFormat.JPEG, 100, stream);
stream.close();
} catch (Exception e) {
// TODO Auto-generated catch block
Toast.makeText(this, "Error: " + e.getMessage(),Toast.LENGTH_LONG).show();
}
break;
UPDATE:
Check that your emulated device has SD Card
Remind that you have to add the permissions to manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Recreate an object without deleting the last one

I'm creating an app that allows user to draw on the screen. My code actually creates a Path and next creates a line. But this when the user takes up his finger of the screen and goes to another part of the screen it make a line as it happen in the next video.
http://youtu.be/CBv1wtUC2g4
The following code is the code of the drawview.
public class DrawView extends View implements OnTouchListener {
private static final String TAG = "DrawView";
List<Point> points = new ArrayList<Point>();
Paint paint = new Paint();
int action;
int draw=0;
Boolean finger=true;
public DrawView(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
paint.setAntiAlias(true);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
Path path = new Path();
boolean first = true;
for(int i = 0; i < points.size(); i += 2){
Point point = points.get(i);
if(first){
first = false;
path.moveTo(point.x, point.y);
}
else if(i < points.size() - 1){
Point next = points.get(i + 1);
path.quadTo(point.x, point.y, next.x, next.y);
}
else {
path.lineTo(point.x, point.y);
}
}
canvas.drawPath(path, paint);
}
public boolean onTouch(View view, MotionEvent event) {
action = event.getAction();
Point point = new Point();
point.x = event.getX();
point.y = event.getY();
points.add(point);
invalidate();
Log.d(TAG, "point: " + point);
if (action == MotionEvent.ACTION_MOVE) {
finger = true;
}
if (action == MotionEvent.ACTION_UP) {
finger = false;
}
draw++;
return true;
}
}
class Point {
float x, y;
#Override
public String toString() {
return x + ", " + y;
}
}
Also I think that maybe what i want I need is an array that contains objects (paths and lines) but i don't know how to do it. Using this method i think that i'm will be able to go back deleting the last object can be this possible?
You need to create a different "Path" each time the user uplifts the finger. I've changed your code to make that. Try it to see if it's what you need.
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
public class DrawView extends View implements OnTouchListener {
private static final String TAG = "DrawView";
private List<List<Point>> _paths = new ArrayList<List<Point>>();
private List<Point> _lastPath;
private Paint _paint = new Paint();
private Path _path = new Path();
public DrawView(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
setOnTouchListener(this);
_paint.setColor(Color.BLACK);
_paint.setStyle(Paint.Style.STROKE);
_paint.setStrokeWidth(5);
_paint.setAntiAlias(true);
}
#Override
protected void onDraw(Canvas canvas) {
for (List<Point> pointsPath : _paths) {
_path.reset();
boolean first = true;
for (int i = 0; i < pointsPath.size(); i += 2) {
Point point = pointsPath.get(i);
if (first) {
first = false;
_path.moveTo(point.x, point.y);
} else if (i < pointsPath.size() - 1) {
Point next = pointsPath.get(i + 1);
_path.quadTo(point.x, point.y, next.x, next.y);
} else {
_path.lineTo(point.x, point.y);
}
}
canvas.drawPath(_path, _paint);
}
}
public boolean onTouch(View view, MotionEvent event) {
Point point = new Point();
point.x = event.getX();
point.y = event.getY();
Log.d(TAG, "point: " + point);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
_lastPath = new ArrayList<Point>();
_lastPath.add(point);
_paths.add(_lastPath);
break;
case MotionEvent.ACTION_MOVE:
_lastPath.add(point);
break;
}
invalidate();
return true;
}
private class Point {
float x, y;
#Override
public String toString() {
return x + ", " + y;
}
}
}

Categories