detecting touch event on rectangle in android - android

I Writing a very simple game in android , the game is like touching a shapes (like rectangle,circle,arc...) and for doing this i write a Thread MainGameTread.class:
package com.example.komeil.surfaceview_2;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.SurfaceHolder;
import java.util.Random;
/**
* Created by Komeil on 04/11/2016.
*/
public class MainGameThread extends Thread {
private boolean running;
private SurfaceHolder surfaceHolder;
private MainGameView mainGameView;
private String shapeType;
private Random rnd;
private int xPos;
private int yPos;
private int radius;
private int left;
private int right;
private int top;
private int bottom;
private int color;
public MainGameThread (SurfaceHolder surfaceHolder,MainGameView mainGameView)
{
super();
this.surfaceHolder = surfaceHolder;
this.mainGameView = mainGameView;
}
public void setRunning(boolean running)
{
this.running = running;
}
#Override
public void run() {
while (running)
{
Canvas canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
synchronized (surfaceHolder)
{
makeChoose();
mainGameView.onDraw(canvas);
}
}
finally {
if(canvas != null)
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
private void makeChoose()
{
int radius;
rnd = new Random();
switch (rnd.nextInt(2))
{
case 0:
setShapeType("Rectangle");
setColor(Color.rgb(rnd.nextInt(255),rnd.nextInt(255),rnd.nextInt(255)));
setXpos(rnd.nextInt(mainGameView.getWidth()));
setYpos(rnd.nextInt(mainGameView.getHeight()));
setTop(rnd.nextInt(mainGameView.getHeight()));
setBottom(rnd.nextInt(mainGameView.getHeight()));
setLeft(rnd.nextInt(mainGameView.getWidth()));
setRight(rnd.nextInt(mainGameView.getWidth()));
break;
case 1:
setShapeType("Circle");
setColor(Color.rgb(rnd.nextInt(255),rnd.nextInt(255),rnd.nextInt(255)));
setXpos(rnd.nextInt(mainGameView.getWidth()));
setYpos(rnd.nextInt(mainGameView.getHeight()));
radius = rnd.nextInt(mainGameView.getWidth()-getXpos());
setRadius(radius);
break;
// case 2:
// setShapeType("Arc");
// setXpos(rnd.nextInt(mainGameView.getWidth()));
// setYpos(rnd.nextInt(mainGameView.getHeight()));
// break;
}
}
private void setShapeType(String shapeType)
{
this.shapeType = shapeType;
}
private void setColor(int color) {
this.color = color;
}
public int getColor() {
return color;
}
private void setRadius(int radius)
{
this.radius = radius;
}
public int getRadius()
{
return radius;
}
public int getBottom() {
return bottom;
}
public int getLeft() {
return left;
}
public int getRight() {
return right;
}
public int getTop() {
return top;
}
private void setBottom(int bottom) {
this.bottom = bottom;
}
private void setLeft(int left) {
this.left = left;
}
private void setRight(int right) {
this.right = right;
}
private void setTop(int top) {
this.top = top;
}
private void setXpos(int xPos)
{
this.xPos = xPos;
}
public int getXpos()
{
return xPos;
}
private void setYpos(int yPos)
{
this.yPos = yPos;
}
public int getYpos()
{
return yPos;
}
public String getShapeType()
{
return shapeType;
}
}
so when i use for drawing in UI Thread it's work. but when i touching rectangle
it's like nothing happend(i use score and i want update score when rectangle touched) but score not shown in screen and some times show itself and Disappeared very fast.
This below code for my MainGameView.class:
package com.example.komeil.surfaceview_2;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/**
* Created by Komeil on 04/11/2016.
*/
public class MainGameView extends SurfaceView implements SurfaceHolder.Callback {
private Bitmap bmp;
MainGameThread mainGameThread;
private int x;
private Paint paint;
private Paint textWhite;
private int score;
private Rect rect;
private boolean touched;
public MainGameView(Context context) {
super(context);
getHolder().addCallback(this);
mainGameThread = new MainGameThread(getHolder(),this);
setFocusable(true);
paint = new Paint();
textWhite = new Paint();
textWhite.setAntiAlias(true);
textWhite.setColor(Color.WHITE);
textWhite.setTextSize(30);
paint.setAntiAlias(true);
bmp = BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mainGameThread.setRunning(true);
mainGameThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
mainGameThread.setRunning(false);
while (retry)
{
try {
mainGameThread.join();
retry = false;
}
catch (InterruptedException ex)
{
}
}
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.GRAY);
if(x<getWidth()-bmp.getWidth())
x+=2;
else
x=0;
canvas.drawBitmap(bmp,x,10,null);
switch (mainGameThread.getShapeType())
{
case "Rectangle":
paint.setColor(mainGameThread.getColor());
canvas.drawRect(mainGameThread.getLeft(),mainGameThread.getTop(),mainGameThread.getRight(),mainGameThread.getBottom(),paint);
break;
case "Circle":
paint.setColor(mainGameThread.getColor());
canvas.drawCircle(mainGameThread.getXpos(),mainGameThread.getYpos(),mainGameThread.getRadius(),paint);
break;
// case "Arc":
// paint.setColor(mainGameThread.getColor());
// canvas.drawArc(mainGameThread.getLeft(),mainGameThread.getRight()
// ,mainGameThread.getTop(),mainGameThread.getBottom(),);
// break;
}
if(touched)
{
canvas.drawText(String.valueOf(score),getWidth()/2,50,textWhite);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int eventAction = event.getAction();
int xEvent = (int)event.getX();
int yEvent = (int)event.getY();
switch (eventAction)
{
case MotionEvent.ACTION_DOWN:
switch (mainGameThread.getShapeType())
{
case "Rectangle":
rect = new Rect(mainGameThread.getLeft(),mainGameThread.getTop(),mainGameThread.getRight(),mainGameThread.getBottom());
if(rect.contains(xEvent,yEvent))
{
touched = true;
score +=1;
}
else
{
touched = false;
}
break;
case "Circle":
break;
case "Arc":
break;
}
break;
case MotionEvent.ACTION_UP:
touched = false;
break;
}
return super.onTouchEvent(event);
}
}
So How i can show score and do i need another thread for score?

Related

How to make custom dotted circular progressbar in android?

I have searched for the dotted circular progress bar but i din get any perfect examples , There are circular progressbar but not with the dotted one So I have implemented hoping that it will help someone, and you can keep this as reference and customize further, for beginners it will help a lot to understand the code as its commented on each line what it is doing.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.naveenbm.customcircleprogressbar.MainActivity"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<com.example.custom.customcircleprogressbar.CricleProgressBarCustom
android:layout_width="wrap_content"
android:layout_height="wrap_content"
></com.example.custom.customcircleprogressbar.CricleProgressBarCustom>
</RelativeLayout>
</RelativeLayout>
CircleProgressBarCustom.java
public class CricleProgressBarCustom extends View {
//Normal dot radius
private int dotRadius = 10;
//Expanded Dot Radius
private int bounceDotRadius = 13;
//to get identified in which position dot has to expand its radius
private int dotPosition = 1;
//specify how many dots you need in a progressbar
private int dotAmount = 10;
//specify the circle radius
private int circleRadius = 50;
public CricleProgressBarCustom(Context context) {
super(context);
}
public CricleProgressBarCustom(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CricleProgressBarCustom(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
//Animation called when attaching to the window, i.e to your screen
startAnimation();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//take the point to the center of the screen
canvas.translate(this.getWidth()/2,this.getHeight()/2);
Paint progressPaint = new Paint();
progressPaint.setColor(Color.parseColor("#ff014e"));
//call create dot method
createDotInCircle(canvas,progressPaint);
}
private void createDotInCircle(Canvas canvas,Paint progressPaint) {
//angle for each dot angle = (360/number of dots) i.e (360/10)
int angle = 36;
for(int i = 1; i <= dotAmount; i++){
if(i == dotPosition){
// angle should be in radians i.e formula (angle *(Math.PI / 180))
float x = (float) (circleRadius * (Math.cos((angle * i) * (Math.PI / 180))));
float y = (float) (circleRadius * (Math.sin((angle * i) * (Math.PI / 180))));
canvas.drawCircle(x,y, bounceDotRadius, progressPaint);
}else{
// angle should be in radians i.e formula (angle *(Math.PI / 180))
float x = (float) (circleRadius * (Math.cos((angle * i) * (Math.PI / 180))));
float y = (float) (circleRadius * (Math.sin((angle * i) * (Math.PI / 180))));
canvas.drawCircle(x,y, dotRadius, progressPaint);
}
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = 0;
int height = 0;
//Dynamically setting width and height to progressbar 100 is circle radius, dotRadius * 3 to cover the width and height of Progressbar
width = 100 + (dotRadius*3);
height = 100 + (dotRadius*3);
//MUST CALL THIS
setMeasuredDimension(width, height);
}
private void startAnimation() {
BounceAnimation bounceAnimation = new BounceAnimation();
bounceAnimation.setDuration(150);
bounceAnimation.setRepeatCount(Animation.INFINITE);
bounceAnimation.setInterpolator(new LinearInterpolator());
bounceAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
dotPosition++;
//when dotPosition == dotAmount , then start again applying animation from 0th positon , i.e dotPosition = 0;
if (dotPosition > dotAmount) {
dotPosition = 1;
}
}
});
startAnimation(bounceAnimation);
}
private class BounceAnimation extends Animation {
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
//call invalidate to redraw your view againg.
invalidate();
}
}
}
Snap Shot:
One example I can suggest you for this various Progress Bar with Smooth Working
https://github.com/ybq/Android-SpinKit
You put the class..
if You want Circle progress bar than Work it Like..
Take a TextView Where You Want...
And First Take..On your Class where You Use.(Declaration)
private Circle mCircleDrawable = new Circle();
Than in your Oncreate take this..
mCircleDrawable.setBounds(0, 0, 100, 100);
mCircleDrawable.setColor(R.color.colorPrimary);// What u want of color progress bar dots...
TextView progressBar_text=(TextView)findViewById(R.id.progress);// Your Textview..
progressBar_text.setCompoundDrawables(null, null, mCircleDrawable, null);// Set Progress bar on Textview..
You Need to Start the
mCircleDrawable.start();
You also Stop the Circle when You exit. On Detroyed Or on PostMethod..If use(AYSNC)
mCircleDrawable.stop();
The Classes Used For this...
You can Use all the Library for this and take any progress bar you need using Upper Link Example
Circle.java
import android.animation.ValueAnimator;
import com.github.ybq.android.spinkit.animation.SpriteAnimatorBuilder;
import com.github.ybq.android.spinkit.sprite.CircleSprite;
import com.github.ybq.android.spinkit.sprite.CircleSpriteGroup;
import com.github.ybq.android.spinkit.sprite.Sprite;
public class Circle extends CircleSpriteGroup {
#Override
public Sprite[] onCreateChild() {
Dot[] dots = new Dot[12];
for (int i = 0; i < dots.length; i++) {
dots[i] = new Dot();
dots[i].setAnimationDelay(1200 / 12 * i + -1200);
}
return dots;
}
class Dot extends CircleSprite {
public Dot() {
setScale(0f);
}
#Override
public ValueAnimator getAnimation() {
float fractions[] = new float[]{0f, 0.5f, 1f};
return new SpriteAnimatorBuilder(this).
scale(fractions, 0f, 1f, 0f).
duration(1200).
easeInOut(fractions)
.build();
}
}
}
SpriteAnimatorBuilder.Java
import android.animation.Keyframe;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.util.Property;
import android.view.animation.Animation;
import android.view.animation.Interpolator;
import com.github.ybq.android.spinkit.animation.interpolator.KeyFrameInterpolator;
import com.github.ybq.android.spinkit.sprite.Sprite;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class SpriteAnimatorBuilder {
private Sprite sprite;
private List<PropertyValuesHolder> propertyValuesHolders = new ArrayList<> ();
private Interpolator interpolator;
private int repeatCount = Animation.INFINITE;
private long duration = 2000;
public SpriteAnimatorBuilder(Sprite sprite) {
this.sprite = sprite;
}
public SpriteAnimatorBuilder scale(float fractions[], float... scale) {
holder(fractions, Sprite.SCALE, scale);
return this;
}
public SpriteAnimatorBuilder alpha(float fractions[], int... alpha) {
holder(fractions, Sprite.ALPHA, alpha);
return this;
}
#SuppressWarnings("unused")
public SpriteAnimatorBuilder scaleX(float fractions[], float... scaleX) {
holder(fractions, Sprite.SCALE, scaleX);
return this;
}
public SpriteAnimatorBuilder scaleY(float fractions[], float... scaleY) {
holder(fractions, Sprite.SCALE_Y, scaleY);
return this;
}
public SpriteAnimatorBuilder rotateX(float fractions[], int... rotateX) {
holder(fractions, Sprite.ROTATE_X, rotateX);
return this;
}
public SpriteAnimatorBuilder rotateY(float fractions[], int... rotateY) {
holder(fractions, Sprite.ROTATE_Y, rotateY);
return this;
}
#SuppressWarnings("unused")
public SpriteAnimatorBuilder translateX(float fractions[], int... translateX) {
holder(fractions, Sprite.TRANSLATE_X, translateX);
return this;
}
#SuppressWarnings("unused")
public SpriteAnimatorBuilder translateY(float fractions[], int... translateY) {
holder(fractions, Sprite.TRANSLATE_Y, translateY);
return this;
}
public SpriteAnimatorBuilder rotate(float fractions[], int... rotate) {
holder(fractions, Sprite.ROTATE, rotate);
return this;
}
public SpriteAnimatorBuilder translateXPercentage(float fractions[], float... translateXPercentage) {
holder(fractions, Sprite.TRANSLATE_X_PERCENTAGE, translateXPercentage);
return this;
}
public SpriteAnimatorBuilder translateYPercentage(float[] fractions, float... translateYPercentage) {
holder(fractions, Sprite.TRANSLATE_Y_PERCENTAGE, translateYPercentage);
return this;
}
public PropertyValuesHolder holder(float[] fractions, Property property, float[] values) {
ensurePair(fractions.length, values.length);
Keyframe[] keyframes = new Keyframe[fractions.length];
for (int i = 0; i < values.length; i++) {
keyframes[i] = Keyframe.ofFloat(fractions[i], values[i]);
}
PropertyValuesHolder valuesHolder = PropertyValuesHolder.
ofKeyframe(property
, keyframes
);
propertyValuesHolders.add(valuesHolder);
return valuesHolder;
}
public PropertyValuesHolder holder(float[] fractions, Property property, int[] values) {
ensurePair(fractions.length, values.length);
Keyframe[] keyframes = new Keyframe[fractions.length];
for (int i = 0; i < values.length; i++) {
keyframes[i] = Keyframe.ofInt(fractions[i], values[i]);
}
PropertyValuesHolder valuesHolder = PropertyValuesHolder.
ofKeyframe(property
, keyframes
);
propertyValuesHolders.add(valuesHolder);
return valuesHolder;
}
private void ensurePair(int fractionsLength, int valuesLength) {
if (fractionsLength != valuesLength) {
throw new IllegalStateException(String.format(
Locale.getDefault(),
"The fractions.length must equal values.length, " +
"fraction.length[%d], values.length[%d]",
fractionsLength,
valuesLength));
}
}
public SpriteAnimatorBuilder interpolator(Interpolator interpolator) {
this.interpolator = interpolator;
return this;
}
public SpriteAnimatorBuilder easeInOut(float... fractions) {
interpolator(KeyFrameInterpolator.easeInOut(
fractions
));
return this;
}
public SpriteAnimatorBuilder duration(long duration) {
this.duration = duration;
return this;
}
#SuppressWarnings("unused")
public SpriteAnimatorBuilder repeatCount(int repeatCount) {
this.repeatCount = repeatCount;
return this;
}
public ObjectAnimator build() {
PropertyValuesHolder[] holders = new PropertyValuesHolder[propertyValuesHolders.size()];
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(sprite,
propertyValuesHolders.toArray(holders));
animator.setDuration(duration);
animator.setRepeatCount(repeatCount);
animator.setInterpolator(interpolator);
return animator;
}
}
CircleSprite.java
import android.animation.ValueAnimator;
import android.graphics.Canvas;
import android.graphics.Paint;
public class CircleSprite extends ShapeSprite {
#Override
public ValueAnimator getAnimation() {
return null;
}
#Override
public void drawShape(Canvas canvas, Paint paint) {
if (getDrawBounds() != null) {
int radius = Math.min(getDrawBounds().width(), getDrawBounds().height()) / 2;
canvas.drawCircle(getDrawBounds().centerX(),
getDrawBounds().centerY(),
radius, paint);
}
}
}
ShapeSprite .java
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
public abstract class ShapeSprite extends Sprite {
private Paint mPaint;
private int mUseColor;
private int mBaseColor;
public ShapeSprite() {
setColor(Color.WHITE);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(mUseColor);
}
#Override
public void setColor(int color) {
mBaseColor = color;
updateUseColor();
}
#Override
public int getColor() {
return mBaseColor;
}
#SuppressWarnings("unused")
public int getUseColor() {
return mUseColor;
}
#Override
public void setAlpha(int alpha) {
super.setAlpha(alpha);
updateUseColor();
}
private void updateUseColor() {
int alpha = getAlpha();
alpha += alpha >> 7;
final int baseAlpha = mBaseColor >>> 24;
final int useAlpha = baseAlpha * alpha >> 8;
mUseColor = (mBaseColor << 8 >>> 8) | (useAlpha << 24);
}
#Override
public void setColorFilter(ColorFilter colorFilter) {
mPaint.setColorFilter(colorFilter);
}
#Override
protected final void drawSelf(Canvas canvas) {
mPaint.setColor(mUseColor);
drawShape(canvas, mPaint);
}
public abstract void drawShape(Canvas canvas, Paint paint);
}
CircleSpriteGroup .java
import android.graphics.Canvas;
import android.graphics.Rect;
public abstract class CircleSpriteGroup extends SpriteGroup {
#Override
public void drawChild(Canvas canvas) {
for (int i = 0; i < getChildCount(); i++) {
Sprite sprite = getChildAt(i);
int count = canvas.save();
canvas.rotate(i * 360 / getChildCount(),
getBounds().centerX(),
getBounds().centerY());
sprite.draw(canvas);
canvas.restoreToCount(count);
}
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
bounds = clipSquare(bounds);
int radius = (int) (bounds.width() * Math.PI / 3.6f / getChildCount());
int left = bounds.centerX() - radius;
int right = bounds.centerX() + radius;
for (int i = 0; i < getChildCount(); i++) {
Sprite sprite = getChildAt(i);
sprite.setDrawBounds(left, bounds.top, right, bounds.top + radius * 2);
}
}
}
Sprite.java
import android.animation.ValueAnimator;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.util.Property;
import com.github.ybq.android.spinkit.animation.AnimationUtils;
import com.github.ybq.android.spinkit.animation.FloatProperty;
import com.github.ybq.android.spinkit.animation.IntProperty;
public abstract class Sprite extends Drawable implements
ValueAnimator.AnimatorUpdateListener
, Animatable
, Drawable.Callback {
private float scale = 1;
private float scaleX = 1;
private float scaleY = 1;
private float pivotX;
private float pivotY;
private int animationDelay;
private int rotateX;
private int rotateY;
private int translateX;
private int translateY;
private int rotate;
private float translateXPercentage;
private float translateYPercentage;
private ValueAnimator animator;
private int alpha = 255;
private static final Rect ZERO_BOUNDS_RECT = new Rect();
protected Rect drawBounds = ZERO_BOUNDS_RECT;
private Camera mCamera;
private Matrix mMatrix;
public Sprite() {
mCamera = new Camera();
mMatrix = new Matrix();
}
public abstract int getColor();
public abstract void setColor(int color);
#Override
public void setAlpha(int alpha) {
this.alpha = alpha;
}
#Override
public int getAlpha() {
return alpha;
}
#Override
public int getOpacity() {
return PixelFormat.RGBA_8888;
}
public float getTranslateXPercentage() {
return translateXPercentage;
}
public void setTranslateXPercentage(float translateXPercentage) {
this.translateXPercentage = translateXPercentage;
}
public float getTranslateYPercentage() {
return translateYPercentage;
}
public void setTranslateYPercentage(float translateYPercentage) {
this.translateYPercentage = translateYPercentage;
}
public int getTranslateX() {
return translateX;
}
public void setTranslateX(int translateX) {
this.translateX = translateX;
}
public int getTranslateY() {
return translateY;
}
public void setTranslateY(int translateY) {
this.translateY = translateY;
}
public int getRotate() {
return rotate;
}
public void setRotate(int rotate) {
this.rotate = rotate;
}
public float getScale() {
return scale;
}
public void setScale(float scale) {
this.scale = scale;
setScaleX(scale);
setScaleY(scale);
}
public float getScaleX() {
return scaleX;
}
public void setScaleX(float scaleX) {
this.scaleX = scaleX;
}
public float getScaleY() {
return scaleY;
}
public void setScaleY(float scaleY) {
this.scaleY = scaleY;
}
public int getRotateX() {
return rotateX;
}
public void setRotateX(int rotateX) {
this.rotateX = rotateX;
}
public int getRotateY() {
return rotateY;
}
public void setRotateY(int rotateY) {
this.rotateY = rotateY;
}
public float getPivotX() {
return pivotX;
}
public void setPivotX(float pivotX) {
this.pivotX = pivotX;
}
public float getPivotY() {
return pivotY;
}
public void setPivotY(float pivotY) {
this.pivotY = pivotY;
}
#SuppressWarnings("unused")
public int getAnimationDelay() {
return animationDelay;
}
public Sprite setAnimationDelay(int animationDelay) {
this.animationDelay = animationDelay;
return this;
}
#Override
public void setColorFilter(ColorFilter colorFilter) {
}
public abstract ValueAnimator getAnimation();
#Override
public void start() {
if (AnimationUtils.isStarted(animator)) {
return;
}
animator = obtainAnimation();
if (animator == null) {
return;
}
AnimationUtils.start(animator);
invalidateSelf();
}
public ValueAnimator obtainAnimation() {
if (animator == null) {
animator = getAnimation();
}
if (animator != null) {
animator.addUpdateListener(this);
animator.setStartDelay(animationDelay);
}
return animator;
}
#Override
public void stop() {
if (AnimationUtils.isStarted(animator)) {
animator.removeAllUpdateListeners();
animator.end();
reset();
}
}
protected abstract void drawSelf(Canvas canvas);
public void reset() {
scale = 1;
rotateX = 0;
rotateY = 0;
translateX = 0;
translateY = 0;
rotate = 0;
translateXPercentage = 0f;
translateYPercentage = 0f;
}
#Override
public boolean isRunning() {
return AnimationUtils.isRunning(animator);
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
setDrawBounds(bounds);
}
public void setDrawBounds(Rect drawBounds) {
setDrawBounds(drawBounds.left, drawBounds.top, drawBounds.right, drawBounds.bottom);
}
public void setDrawBounds(int left, int top, int right, int bottom) {
this.drawBounds = new Rect(left, top, right, bottom);
setPivotX(getDrawBounds().centerX());
setPivotY(getDrawBounds().centerY());
}
#Override
public void invalidateDrawable(Drawable who) {
invalidateSelf();
}
#Override
public void scheduleDrawable(Drawable who, Runnable what, long when) {
}
#Override
public void unscheduleDrawable(Drawable who, Runnable what) {
}
#Override
public void onAnimationUpdate(ValueAnimator animation) {
final Callback callback = getCallback();
if (callback != null) {
callback.invalidateDrawable(this);
}
}
public Rect getDrawBounds() {
return drawBounds;
}
#Override
public void draw(Canvas canvas) {
int tx = getTranslateX();
tx = tx == 0 ? (int) (getBounds().width() * getTranslateXPercentage()) : tx;
int ty = getTranslateY();
ty = ty == 0 ? (int) (getBounds().height() * getTranslateYPercentage()) : ty;
canvas.translate(tx, ty);
canvas.scale(getScaleX(), getScaleY(), getPivotX(), getPivotY());
canvas.rotate(getRotate(), getPivotX(), getPivotY());
if (getRotateX() != 0 || getRotateY() != 0) {
mCamera.save();
mCamera.rotateX(getRotateX());
mCamera.rotateY(getRotateY());
mCamera.getMatrix(mMatrix);
mMatrix.preTranslate(-getPivotX(), -getPivotY());
mMatrix.postTranslate(getPivotX(), getPivotY());
mCamera.restore();
canvas.concat(mMatrix);
}
drawSelf(canvas);
}
public Rect clipSquare(Rect rect) {
int w = rect.width();
int h = rect.height();
int min = Math.min(w, h);
int cx = rect.centerX();
int cy = rect.centerY();
int r = min / 2;
return new Rect(
cx - r,
cy - r,
cx + r,
cy + r
);
}
public static final Property<Sprite, Integer> ROTATE_X = new IntProperty<Sprite>("rotateX") {
#Override
public void setValue(Sprite object, int value) {
object.setRotateX(value);
}
#Override
public Integer get(Sprite object) {
return object.getRotateX();
}
};
public static final Property<Sprite, Integer> ROTATE = new IntProperty<Sprite>("rotate") {
#Override
public void setValue(Sprite object, int value) {
object.setRotate(value);
}
#Override
public Integer get(Sprite object) {
return object.getRotate();
}
};
public static final Property<Sprite, Integer> ROTATE_Y = new IntProperty<Sprite>("rotateY") {
#Override
public void setValue(Sprite object, int value) {
object.setRotateY(value);
}
#Override
public Integer get(Sprite object) {
return object.getRotateY();
}
};
#SuppressWarnings("unused")
public static final Property<Sprite, Integer> TRANSLATE_X = new IntProperty<Sprite>("translateX") {
#Override
public void setValue(Sprite object, int value) {
object.setTranslateX(value);
}
#Override
public Integer get(Sprite object) {
return object.getTranslateX();
}
};
#SuppressWarnings("unused")
public static final Property<Sprite, Integer> TRANSLATE_Y = new IntProperty<Sprite>("translateY") {
#Override
public void setValue(Sprite object, int value) {
object.setTranslateY(value);
}
#Override
public Integer get(Sprite object) {
return object.getTranslateY();
}
};
public static final Property<Sprite, Float> TRANSLATE_X_PERCENTAGE = new FloatProperty<Sprite>("translateXPercentage") {
#Override
public void setValue(Sprite object, float value) {
object.setTranslateXPercentage(value);
}
#Override
public Float get(Sprite object) {
return object.getTranslateXPercentage();
}
};
public static final Property<Sprite, Float> TRANSLATE_Y_PERCENTAGE = new FloatProperty<Sprite>("translateYPercentage") {
#Override
public void setValue(Sprite object, float value) {
object.setTranslateYPercentage(value);
}
#Override
public Float get(Sprite object) {
return object.getTranslateYPercentage();
}
};
#SuppressWarnings("unused")
public static final Property<Sprite, Float> SCALE_X = new FloatProperty<Sprite>("scaleX") {
#Override
public void setValue(Sprite object, float value) {
object.setScaleX(value);
}
#Override
public Float get(Sprite object) {
return object.getScaleX();
}
};
public static final Property<Sprite, Float> SCALE_Y = new FloatProperty<Sprite>("scaleY") {
#Override
public void setValue(Sprite object, float value) {
object.setScaleY(value);
}
#Override
public Float get(Sprite object) {
return object.getScaleY();
}
};
public static final Property<Sprite, Float> SCALE = new FloatProperty<Sprite>("scale") {
#Override
public void setValue(Sprite object, float value) {
object.setScale(value);
}
#Override
public Float get(Sprite object) {
return object.getScale();
}
};
public static final Property<Sprite, Integer> ALPHA = new IntProperty<Sprite>("alpha") {
#Override
public void setValue(Sprite object, int value) {
object.setAlpha(value);
}
#Override
public Integer get(Sprite object) {
return object.getAlpha();
}
};
}
KeyFrameInterpolator.java
import android.animation.TimeInterpolator;
import android.view.animation.Interpolator;
public class KeyFrameInterpolator implements Interpolator {
private TimeInterpolator interpolator;
private float[] fractions;
public static KeyFrameInterpolator easeInOut(float... fractions) {
KeyFrameInterpolator interpolator = new KeyFrameInterpolator(Ease.inOut());
interpolator.setFractions(fractions);
return interpolator;
}
public KeyFrameInterpolator(TimeInterpolator interpolator) {
this.interpolator = interpolator;
}
public void setFractions(float... fractions) {
this.fractions = fractions;
}
#Override
public synchronized float getInterpolation(float input) {
if (fractions.length > 1) {
for (int i = 0; i < fractions.length - 1; i++) {
float start = fractions[i];
float end = fractions[i + 1];
float duration = end - start;
if (input >= start && input <= end) {
input = (input - start) / duration;
return start + (interpolator.getInterpolation(input)
* duration);
}
}
}
return interpolator.getInterpolation(input);
}
}
AnimationUtils.java
import android.animation.Animator;
import android.animation.ValueAnimator;
import com.github.ybq.android.spinkit.sprite.Sprite;
public class AnimationUtils {
public static void start(Animator animator) {
if (animator != null && !animator.isStarted()) {
animator.start();
}
}
public static void stop(Animator animator) {
if (animator != null && !animator.isRunning()) {
animator.end();
}
}
public static void start(Sprite... sprites) {
for (Sprite sprite : sprites) {
sprite.start();
}
}
public static void stop(Sprite... sprites) {
for (Sprite sprite : sprites) {
sprite.stop();
}
}
public static boolean isRunning(Sprite... sprites) {
for (Sprite sprite : sprites) {
if (sprite.isRunning()) {
return true;
}
}
return false;
}
public static boolean isRunning(ValueAnimator animator) {
return animator != null && animator.isRunning();
}
public static boolean isStarted(ValueAnimator animator) {
return animator != null && animator.isStarted();
}
}
FloatProperty.java
import android.util.Property;
public abstract class FloatProperty<T> extends Property<T, Float> {
public FloatProperty(String name) {
super(Float.class, name);
}
/**
* A type-specific override of the {#link #set(Object, Float)} that is faster when dealing
* with fields of type <code>float</code>.
*/
public abstract void setValue(T object, float value);
#Override
final public void set(T object, Float value) {
setValue(object, value);
}
}
IntProperty.java
import android.util.Property;
public abstract class IntProperty<T> extends Property<T, Integer> {
public IntProperty(String name) {
super(Integer.class, name);
}
public abstract void setValue(T object, int value);
#Override
final public void set(T object, Integer value) {
setValue(object, value);
}
}
Kotlin way of the great answer from #Naveen Shriyan:
class CustomDottedProgressBar : View {
constructor(context: Context) : super(context)
constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr)
//Normal dot radius
private val dotRadius = 10F
//Expanded Dot Radius
private val bounceDotRadius = 15F
//to get identified in which position dot has to expand its radius
private var dotPosition = 0
//specify the circle radius
private val circleRadius = 50
// specify the sizes of dots
private val dotRadiusList = arrayListOf(2F, 3F, 4F, 5F, 6F, 7F, 8F, 9F, 10F)
//specify how many dots you need in a progressbar
private val dotAmount = dotRadiusList.size
private val progressPaint = Paint()
override fun onAttachedToWindow() {
super.onAttachedToWindow()
//Animation called when attaching to the window, i.e to your screen
startAnimation()
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
//take the point to the center of the screen
canvas.translate((this.width / 2).toFloat(), (this.height / 2).toFloat())
progressPaint.color = context.getColor(R.color.orange)
//call create dot method
createDotInCircle(canvas, progressPaint)
}
private fun createDotInCircle(canvas: Canvas, progressPaint: Paint) {
//angle for each dot angle = (360/number of dots) i.e (360/10)
val angle = 360 / dotAmount
for (i in 0 until dotAmount) {
if (i == dotPosition) {
// angle should be in radians i.e formula (angle *(Math.PI / 180))
val x = (circleRadius * cos(angle * i * (Math.PI / 180))).toFloat()
val y = (circleRadius * sin(angle * i * (Math.PI / 180))).toFloat()
canvas.drawCircle(x, y, bounceDotRadius, progressPaint)
} else {
// angle should be in radians i.e formula (angle *(Math.PI / 180))
val x = (circleRadius * cos(angle * i * (Math.PI / 180))).toFloat()
val y = (circleRadius * sin(angle * i * (Math.PI / 180))).toFloat()
canvas.drawCircle(x, y, dotRadiusList[i], progressPaint)
}
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
//Dynamically setting width and height to progressbar 100 is circle radius, dotRadius * 3 to cover the width and height of Progressbar
val width = 100 + dotRadius * 3
val height = 100 + dotRadius * 3
//MUST CALL THIS
setMeasuredDimension(width.roundToInt(), height.roundToInt())
}
private fun startAnimation() {
val bounceAnimation = BounceAnimation()
bounceAnimation.duration = 75
bounceAnimation.repeatCount = Animation.INFINITE
bounceAnimation.interpolator = LinearInterpolator()
bounceAnimation.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {}
override fun onAnimationEnd(animation: Animation) {}
override fun onAnimationRepeat(animation: Animation) {
dotPosition++
//when dotPosition == dotAmount , then start again applying animation from 0th position , i.e dotPosition = 0;
if (dotPosition > dotAmount) {
dotPosition = 0
}
}
})
startAnimation(bounceAnimation)
}
private inner class BounceAnimation : Animation() {
override fun applyTransformation(interpolatedTime: Float, t: Transformation?) {
super.applyTransformation(interpolatedTime, t)
//call invalidate to redraw your view again.
invalidate()
}
}}

Pause and resume threads in Android

I am beginner to multithreading in Java and in my Android application, i have that SurfaceView on wich am drawing a circle randomlly but i want to be able to pause that drawing by pressing the screen (ACTION_DOWN) and resume it the next time i press it again :
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameView extends SurfaceView /**/implements SurfaceHolder.Callback {
private float x = 100;
private float y = 100;
private int radius = 20;
private Paint paint;
private SurfaceHolder mSurfaceHolder;
private DrawingThread mThread;
private Context myContext;
public GameView(Context context) {
super(context);
this.myContext = context;
setWillNotDraw(false);
paint = new Paint();
/**/
paint.setAntiAlias(true);
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.STROKE);
paint.setTextAlign(Paint.Align.LEFT);
mSurfaceHolder = getHolder();
mSurfaceHolder.addCallback(this);
//paint.setTextSize(15);
}
public void onDraw(Canvas canvas){
canvas.drawCircle(x, y, radius, paint);
}
/**/
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mThread = new DrawingThread(mSurfaceHolder, myContext);
mThread.mRun = true;
mThread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
public synchronized boolean onTouchEvent(MotionEvent event) {
int eventaction = event.getAction();
int X = (int)event.getX();
int Y = (int)event.getY();
switch (eventaction ) {
case MotionEvent.ACTION_DOWN:
this.mThread.canPause = !this.mThread.canPause;
synchronized(this.mSurfaceHolder){
if(this.mThread.canPause){
this.mSurfaceHolder.notify();
}
}
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
break;
}
invalidate();
return true;
}
public final class DrawingThread extends Thread {
public boolean canPause = false;
boolean mRun;
Canvas mcanvas;
SurfaceHolder surfaceHolder;
Context context;
public DrawingThread(SurfaceHolder sholder, Context ctx)
{
surfaceHolder = sholder;
context = ctx;
mRun = false;
}
void setRunning(boolean bRun)
{
mRun = bRun;
}
boolean keepDrawing = true;
#Override
public void run() {
while (keepDrawing) {
Canvas canvas = null;
try {
canvas = mSurfaceHolder.lockCanvas();
synchronized (mSurfaceHolder) {
while(canPause){
try {
mSurfaceHolder.wait();
} catch(InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
waitThreaed();
draw(canvas);
}
}
catch(Exception e){
}
finally {
if (canvas != null)
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
public void waitThreaed() {
try {
x = (float) (getWidth()*Math.random());
y = (float) (getHeight()*Math.random());
this.sleep(1000);
postInvalidate();
} catch (InterruptedException e) {
}
}
}
}
In fact with that code the drawing can be paused but can not be resumed
In order to call wait() you must have synchronized on the object you are waiting on.
See this question for a discussion of that: Why must wait() always be in synchronized block

How to change attributes of the second Activity from Main activity?

In the main activity I have a handler to exchange messages with the bluetooth service. This works fine.
Now, I want launch second activity (SurfaceViewAnimation). I do this with:
startActivity (new Intent (this, SurfaceViewAnimation.class));
but I want change some attributes of SufaceViewAnimation class from main activity when it receives a command for bluetooth.
How I can do this?
The code of SufaceViewAnimation class is:
class BouncingBallView extends SurfaceView implements SurfaceHolder.Callback {
private BouncingBallAnimationThread bbThread = null;
private int xPosition = getWidth()/2;
private int yPosition = getHeight()/2;
private int xDirection = 20;
private int yDirection = 40;
private static int radius = 20;
private static int ballColor = Color.RED;
public BouncingBallView(Context ctx, AttributeSet attrs, int defStyle) {
super(ctx, attrs, defStyle);
getHolder().addCallback(this);
}
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
canvas.drawRect(0,0,getWidth(),getHeight(), paint);
paint.setColor(ballColor);
canvas.drawCircle(xPosition, yPosition, radius, paint);
}
public void surfaceCreated(SurfaceHolder holder) {
if (bbThread!=null) return;
bbThread = new BouncingBallAnimationThread(getHolder());
bbThread.start();
}
public void surfaceChanged(SurfaceHolder holder,int format, int width, int height) { }
public void surfaceDestroyed(SurfaceHolder holder) {
bbThread.stop = true;
}
private class BouncingBallAnimationThread extends Thread {
public boolean stop = false;
private SurfaceHolder surfaceHolder;
public BouncingBallAnimationThread(SurfaceHolder surfaceHolder) {
this.surfaceHolder = surfaceHolder;
}
public void run() {
while (!stop) {
xPosition += xDirection;
yPosition += yDirection;
if (xPosition<0) {
xDirection = -xDirection;
xPosition = radius; }
if (xPosition>getWidth()-radius) {
xDirection = -xDirection;
xPosition = getWidth()-radius; }
if (yPosition<0) {
yDirection = -yDirection;
yPosition = radius; }
if (yPosition>getHeight()-radius) {
yDirection = -yDirection;
yPosition = getHeight()-radius-1; }
Canvas c = null;
try {
c = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
onDraw(c);
}
} finally {
if (c != null) surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() != MotionEvent.ACTION_DOWN) return false;
if (xDirection!=0 || yDirection!=0)
xDirection = yDirection = 0;
else {
xDirection = (int) event.getX() - xPosition;
yDirection = (int) event.getY() - yPosition;
}
if(ballColor==Color.RED)
ballColor=Color.GREEN;
else
ballColor=Color.RED;
return true;
}
public void setxDirection(int xDirection) {
this.xDirection = xDirection;
}
public void setyDirection(int yDirection) {
this.yDirection = yDirection;
}
public void setballColor(int ballColor) {
this.ballColor = ballColor;
}
public void setradius(int radius) {
this.radius = radius;
}
}
public class SurfaceViewAnimation extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new BouncingBallView(this,null,0));
}
}
If you want to change the data in SurfaceViewAnimation while SurfaceViewAnimation is running, you're best off with creating an own handler.
Besides that you can fall back to basic Inter(Process/Activity)Communication using Handlers, static variables or the Observer pattern.

change color of line in surfaceview and retain the color of the previous line

I followed the tutorial from here https://github.com/vivekrk/SurfaceView-Sample and modified it to the code below.
Every time I press on the button to change the color The entire color including the the line which was already present on the view changes.I want only the new line to change its color .
How do I do that?
I am a noob in Android and any help would be greatly appreciated.
Thanks in Advance.
CanvasView.java
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CanvasView extends SurfaceView implements SurfaceHolder.Callback {
private static final float STROKE_WIDTH = 8;
private UIThread uiThread;
private Path mPath;
public static Paint mPaint;
private Path oldPath;
private DrawableObject drawableObject = null;
private float mX;
private float mY;
private float TOUCH_TOLERANCE = 8;
private RectF dirtyRect;
private int mMode = Constants.FREE_DRAWING;
private ArrayList<DrawableObject> objectsToDraw;
public static int colorofpaint;
public CanvasView(Context context) {
super(context);
getHolder().addCallback(this);
objectsToDraw = new ArrayList<DrawableObject>();
mPath = new Path();
}
public void clearCanvas() {
mPath.reset();
}
public void setDrawingMode(int drawingMode) {
mMode = drawingMode;
}
#Override
public void onDraw(Canvas canvas) {
setPaintProperties();
if (canvas != null) {
canvas.drawColor(Color.WHITE);
synchronized (objectsToDraw) {
for (DrawableObject drawableObject : objectsToDraw) {
drawableObject.draw(canvas);
}
}
}
}
public void stopUIThread() {
uiThread.setRunning(false);
}
private void setPaintProperties() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
//mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(STROKE_WIDTH);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
oldPath = mPath;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (mMode) {
case Constants.FREE_DRAWING:
drawableObject = new FreeDrawing(mPath, mPaint);
if (colorofpaint==1) {
mPaint.setColor(Color.GREEN);
}
if (colorofpaint==2) {
mPaint.setColor(Color.RED);
}
if (colorofpaint==3) {
mPaint.setColor(Color.BLUE);
}
if (colorofpaint==4) {
mPaint.setColor(Color.YELLOW);
}
if (colorofpaint==5) {
mPaint.setColor(Color.CYAN);
}
if (colorofpaint==6) {
mPaint.setColor(Color.BLACK);
}
if (colorofpaint==7) {
mPaint.setColor(Color.MAGENTA);
}
break;
default:
break;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
synchronized (objectsToDraw) {
objectsToDraw.add(drawableObject);
}
mPath.moveTo(x, y);
mX = x;
mY = y;
break;
case MotionEvent.ACTION_MOVE:
switch (mMode) {
case Constants.FREE_DRAWING:
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
mX = x;
mY = y;
}
break;
}
break;
case MotionEvent.ACTION_UP:
switch (mMode) {
case Constants.FREE_DRAWING:
mPath.moveTo(x, y);
break;
}
break;
}
return true;
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
uiThread = new UIThread(this);
uiThread.setRunning(true);
uiThread.start();
}
public void restoreOldPath() {
mPath = oldPath;
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
uiThread.setRunning(false);
}
public RectF getDirtyRect() {
if(dirtyRect == null) {
dirtyRect = new RectF();
}
return dirtyRect ;
}
}
UIThread .java
import android.graphics.Canvas;
import android.view.SurfaceHolder;
public class UIThread extends Thread {
private static boolean toRun = false;
private CanvasView canvasView;
private SurfaceHolder surfaceHolder;
public UIThread(CanvasView canvasView) {
this.canvasView = canvasView;
surfaceHolder = canvasView.getHolder();
}
public boolean isThreadRunning() {
return toRun;
}
public void setRunning(boolean run) {
toRun = run;
}
#Override
public void run() {
Canvas c;
while (toRun) {
c = null;
try {
c = surfaceHolder.lockCanvas(null);
canvasView.onDraw(c);
} finally {
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
FreeDrawing .java
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
public class FreeDrawing extends DrawableObject {
private Path mPath;
private Paint mPaint;
public FreeDrawing(Path path, Paint paint) {
mPath = path;
mPaint = paint;
}
#Override
public void draw(Canvas canvas) {
canvas.drawPath(mPath, mPaint);
}
}
DrawableObject .java
import android.graphics.Canvas;
public abstract class DrawableObject {
abstract public void draw(Canvas canvas);
}
Constants .java
public class Constants {
// XXX:Drawing modes
public static final int FREE_DRAWING = 1000;
public static final int LINE_DRAWING = 1001;
public static final int RECT_DRAWING = 1002;
public static final int SELECT = 1003;
}
SurfaceViewSampleActivity .java
import android.app.Activity;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.LightingColorFilter;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.Toast;
public class SurfaceViewSampleActivity extends Activity {
/** Called when the activity is first created. */
private CanvasView view;
private static final int CLEAR = 100;
private FrameLayout surfaceViewFrame;
private RadioGroup mode;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
surfaceViewFrame = (FrameLayout) findViewById(R.id.surfaceviewFrame);
view = new CanvasView(this);
surfaceViewFrame.addView(view, 0);
CanvasView.colorofpaint=6;
view.setDrawingMode(Constants.FREE_DRAWING);
Button b1=(Button)findViewById(R.id.button1);
b1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
CanvasView.colorofpaint=2;
// view.setDrawingMode(Constants.FREE_DRAWING);
}
});
Button b2=(Button)findViewById(R.id.button2);
b2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
CanvasView.colorofpaint=3;
view.setDrawingMode(Constants.FREE_DRAWING);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, CLEAR, 0, "Clear");
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case CLEAR:
view.clearCanvas();
break;
}
return true;
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Toast.makeText(getApplicationContext(), "onConfigurationChanged", Toast.LENGTH_SHORT).show();
}
}

Android SurfaceView with touch events

I have custom SurfaceView that containt a circle. I want to rotate this circle via touch events. Everything good except I can't pause run() method of SurfaveView when touch finished.
Here my view and thread
public class CircleSurfaceView extends SurfaceView implements
SurfaceHolder.Callback {
private Circle mCircle;
private DrawThread thread;
private float mRotation = 0;
long mLastMillis = 0L;
Paint clearPaint = new Paint();
public CircleSurfaceView(Context context) {
super(context);
mCircle = new Circle(0, 200, 200);
getHolder().addCallback(this);
this.setZOrderOnTop(true);
this.getHolder().setFormat(PixelFormat.TRANSPARENT);
clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
public void startDrawing() {
if (thread == null) {
thread = new DrawThread(this);
thread.startThread();
}
}
public void stopDrawing() {
if (thread != null) {
thread.stopThread();
// Waiting for the thread to die by calling thread.join,
// repeatedly if necessary
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
}
}
thread = null;
}
}
#Override
protected void onDraw(final Canvas canvas) {
canvas.drawPaint(clearPaint);
mCircle.init();
mCircle.draw(canvas);
super.onDraw(canvas);
}
float degrees;
public void rotateCircle() {
mCircle.rotate(mRotation);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float currentX = event.getX();
float currentY = event.getY();
float deltaX, deltaY;
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
// Modify rotational angles according to movement
deltaX = currentX - previousX;
deltaY = currentY - previousY;
mRotation += deltaX + deltaY;
}
// Save current x, y
previousX = currentX;
previousY = currentY;
rotateCircle();
return true; // Event handled
}
private float previousX;
private float previousY;
private static int SEG_COUNT = 62;
private static float SEG_IN_GRAD = (float) 360 / SEG_COUNT;
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder arg0) {
startDrawing();
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
stopDrawing();
}
public class DrawThread extends Thread {
private boolean mRun = false;
private SurfaceHolder surfaceHolder = null;
private CircleSurfaceView circleSurfaceView = null;
public DrawThread(CircleSurfaceView circleSurfaceView) {
this.circleSurfaceView = circleSurfaceView;
this.surfaceHolder = circleSurfaceView.getHolder();
}
public void startThread() {
if (mRun == false) {
mRun = true;
super.start();
}
}
public void stopThread() {
if (mRun == true) {
mRun = false;
}
}
#Override
public void run() {
Canvas c = null;
while (mRun) {
c = null;
try {
c = surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
if (c != null) {
Log.i("run", "run");
circleSurfaceView.rotateCircle();
circleSurfaceView.onDraw(c);
}
}
} finally {
// do this in a finally so that if an exception is thrown
// we don't leave the Surface in an inconsistent state
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}

Categories

Resources