Related
Hi I currently have a SurfaceView Runnable public class mapsLayout extends SurfaceView implements Runnable { which draws lines based on current geolocation. My previous solution involved having a main activity which contains the Android location manager - using a FusedLocationProviderClient as recommended by the tutorials provided by Google - and then calling the SurfaceView.
mainActivity with Android location manager -> 'SurfaceView'
However this means that the SurfaceView resets every time the location changes which happens every 10000 ticks.
Is there a way for the SurfaceView to contain the Android location manager.
If it helps I have my SurfaceView Runnable code below
public class mapsActivityLayout extends SurfaceView implements Runnable {
MyThread draw = null;
boolean canDraw = false;
Bitmap map;
SurfaceHolder surfaceHolder;
Context mContext;
Paint paint;
ArrayList<String> endNodes = new ArrayList<String>();
int bitmapX;
int bitmapY;
int viewWidth;
int viewHeight;
Paint red_paintbrush_fill, blue_paintbrush_fill, green_paintbrush_fill;
Paint red_paintbrush_stroke, blue_paintbrush_stroke, green_paintbrush_stroke;
Path line;
Path circle;
public mapsActivityLayout(Context context, ArrayList<String> endNodes) {
super(context);
this.endNodes = endNodes
mContext = context;
surfaceHolder = getHolder();
paint = new Paint();
paint.setColor(Color.DKGRAY);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
viewWidth = w;
viewHeight = h;
draw = new MyThread(viewWidth, viewHeight);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = true;
options.inMutable = true;
map = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.mapimage, options);
setUpBitmap();
}
#Override
public void run() {
Canvas canvas;
prepPaintBrushes();
while (canDraw) {
//draw stuff
if (surfaceHolder.getSurface().isValid()) {
int x = draw.getX();
int y = draw.getY();
//int radius = draw.getRadius();
canvas = surfaceHolder.lockCanvas();
canvas.save();
canvas.drawBitmap(map, bitmapX, bitmapY, paint);
ArrayList<Double> currentLocation = convertGeoToPixel(currentLat, currentLon);
ArrayList<Double> destination = convertGeoToPixel(destinationLat, destinationLat);
int width = 2699;
int height = 2699;
canvas.drawCircle(currentX, currentY, 20, red_paintbrush_fill);
canvas.drawCircle(destX, destY, 20, green_paintbrush_fill);
path.rewind();
canvas.restore();
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
private void updateFrame(int newX, int newY) {
draw.update(newX, newY);
}
/**
* Calculates a randomized location for the bitmap
* and the winning bounding rectangle.
*/
private void setUpBitmap() {
bitmapX = (int) Math.floor(
Math.random() * (viewWidth - backGround.getWidth()));
bitmapY = (int) Math.floor(
Math.random() * (viewHeight - backGround.getHeight()));
}
public void pause() {
canDraw = false;
while (true) {
try {
thread.join();
break;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void resume() {
canDraw = true;
thread = new Thread(this);
thread.start();
}
private void prepPaintBrushes() {
red_paintbrush_fill = new Paint();
red_paintbrush_fill.setColor(Color.RED);
red_paintbrush_fill.setStyle(Paint.Style.FILL);
green_paintbrush_stroke = new Paint();
green_paintbrush_stroke.setColor(Color.GREEN);
green_paintbrush_stroke.setStyle(Paint.Style.STROKE);
green_paintbrush_stroke.setStrokeWidth(10);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
setUpBitmap();
updateFrame((int) x, (int) y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
updateFrame((int) x, (int) y);
invalidate();
break;
default:
}
return true;
}
}
thread code
public class MyThread extends Thread {
private int mX;
private int mY;
public MyThread(int viewWidth, int viewHeight) {
//super()
mX = viewWidth / 2;
mY = viewHeight / 2;
}
/**
* Update the coordinates of the map.
*
* #param newX Changed value for x coordinate.
* #param newY Changed value for y coordinate.
*/
public void update(int newX, int newY) {
mX = newX;
mY = newY;
}
public int getX() {
return mX;
}
public int getY() {
return mY;
}
}
I have a sprite sheet of 612x864 dimension with 5 rows and 5 columns .My problem is how can I load it and animate it? I want to move the cat sprite in y-axis only .I've already try but my code is not working properly. Here is my code.
In GameView.java
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameView extends SurfaceView {
private Bitmap bmp;
private SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private Sprite sprite;
public GameView(Context context) {
super(context);
gameLoopThread = new GameLoopThread(this);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
gameLoopThread.setRunning(false);
while (retry) {
try {
gameLoopThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.catsprite);
sprite = new Sprite(this,bmp);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
sprite.onDraw(canvas);
}
}
GameLoopThread.java
import android.graphics.Canvas;
public class GameLoopThread extends Thread {
static final long FPS = 10;
private GameView view;
private boolean running = false;
public GameLoopThread(GameView view) {
this.view = view;
}
public void setRunning(boolean run) {
running = run;
}
#Override
public void run() {
long ticksPS = 1000 / FPS;
long startTime;
long sleepTime;
while (running) {
Canvas c = null;
startTime = System.currentTimeMillis();
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
view.onDraw(c);
}
} finally {
if (c != null) {
view.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
try {
if (sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
} catch (Exception e) {}
}
}
}
Sprite.java
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
public class Sprite {
private static final int BMP_ROWS = 5;
private static final int BMP_COLUMNS = 5;
private int x = 0;
private int y = 0;
private int ySpeed = 3;
private GameView gameView;
private Bitmap bmp;
private int currentFrame = 1;
private int width;
private int height;
public Sprite(GameView gameView, Bitmap bmp) {
this.gameView = gameView;
this.bmp = bmp;
this.width = bmp.getWidth() / BMP_COLUMNS;
this.height = bmp.getHeight() / BMP_ROWS;
}
private void update() {
if (y > gameView.getWidth() - width - y) {
ySpeed = -5;
}
if (y + y < 0) {
ySpeed = 5;
}
y = y + ySpeed;
currentFrame = ++currentFrame % BMP_COLUMNS;
}
public void onDraw(Canvas canvas) {
update();
int srcX = currentFrame * width;
int srcY = 1 * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
}
I'll recommend you to use this library. It's great for Sprite Animation. It has some limitations though, but it works fine.
Here is the code how I done it.
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.runningcat);
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int frameWidth = width / 5; //you have 5 columns
int frameHeight = height / 5; //and 5 rows
int frameNum = 25; //there would be 25 images
SpriteSheetDrawer spriteSheetDrawer = new SpriteSheetDrawer(
bitmap,
frameWidth,
frameHeight,
frameNum)
.spriteLoop(true)
.frequency(2); //change it as per your need
DisplayObject displayObject = new DisplayObject();
displayObject
.with(spriteSheetDrawer)
.tween()
.tweenLoop(true)
.transform(0, 0) //I have changed it according to my need, you can also do this by changing these values
.toX(4000, 0) //this one too.
.end();
//In actual example, it's set as animation starts from one end of the screen and goes till the other one.
FPSTextureView textureView = (FPSTextureView) findViewById(R.id.fpsAnimation);
textureView.addChild(displayObject).tickStart();
Problem is in src value that you're using in method. canvas.drawBitmap(bmp, src, dst, null); srcY should be zero. I've tested here.
private Bitmap character;
private counter,charFrame;
private RectF annonymousRectF;
private Rect annonymousRect;
public Sprite() {
character=BitmapFactory.decodeResource(context.getResources(), R.drawable.flipchar2);
annonymousRect=new Rect();
annonymousRectF=new RectF();
}
public void update() {
counter++;
if(counter%5==0)
if(charFrame<NO_CHAR_FRAME-1)
charFrame++;
else
charFrame=0;
}
public void draw(){
annonymousRect.set(charFrame*character.getWidth()/NO_CHAR_FRAME,0,(charFrame+1)*character.getWidth()/NO_CHAR_FRAME,character.getHeight());
annonymousRectF.set(-width*.015f,height*.35f,width*.5f,height*.58f); //set value according to where you want to draw
canvas.drawBitmap(character, annonymousRect,annonymousRectF, null);
}
I was trying to animate a sprite for an android app and i've encounter a small problem. I'm drawing on a surfaceView that i add on top of already existing layouts. On this surfaceView, i wanted to animate few sprites so they would walk along a path.
So this is the result i'm facing right now :
The walking sprite is leaving a trail. So i decided to google this problem and apparently i had to clear the canvas first before drawing on it.
This was my onDraw method before :
public void onDraw(Canvas canvas) {
update();
int srcX = currentFrame * width;
int srcY = directionX * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
And this was my onDraw method after
public void onDraw(Canvas canvas) {
canvas.drawRGB(0, 0, 0);
update();
int srcX = currentFrame * width;
int srcY = directionX * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
So i now have this as a result
which is great because it leaves no more trail BUT i cant see the layouts underneath. Is there anyway i can get the best of both world ? I thought clearing the canvas would work but it obviously doesnt not work as expected.
I'll post my code below
SurfaceView :
public class MonsterView extends SurfaceView {
private Bitmap monsterImg;
private SurfaceHolder holder;
private MonsterThread mainThread;
private Sprite monsterSprite;
private int x;
private int xSpeed = 1;
public MonsterView(Context context) {
super(context);
this.mainThread = new MonsterThread(this);
this.x = 0;
holder = getHolder();
holder.setFormat(PixelFormat.TRANSPARENT);
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
mainThread.setRunning(true);
mainThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
mainThread.setRunning(false);
while (retry) {
try {
mainThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
});
setZOrderOnTop(true);
monsterImg = BitmapFactory.decodeResource(getResources(), R.drawable.fire);
monsterSprite = new Sprite(this,monsterImg);
}
#Override
public void onDraw(Canvas canvas) {
if (x == getWidth() - monsterImg.getWidth()) {
xSpeed = -1;
}
if (x == 0) {
xSpeed = 1;
}
x = x + xSpeed;
monsterSprite.onDraw(canvas);
}
Thread :
public class MonsterThread extends Thread {
private MonsterView monsterSurface;
private boolean running;
static final long FPS = 35;
public MonsterThread(MonsterView monsterSurface){
this.monsterSurface = monsterSurface;
this.running = false;
}
#Override
public void run() {
long ticksPS = 1000 / FPS;
long startTime;
long sleepTime;
while(running){
Canvas c = null;
startTime = System.currentTimeMillis();
try{
c = monsterSurface.getHolder().lockCanvas();
synchronized (monsterSurface.getHolder()){
monsterSurface.onDraw(c);
}
} finally {
if( c!= null){
monsterSurface.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
try {
if(sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
} catch (Exception e){}
}
}
public MonsterView getMonsterSurface() {
return monsterSurface;
}
public void setMonsterSurface(MonsterView monsterSurface) {
this.monsterSurface = monsterSurface;
}
public boolean isRunning() {
return running;
}
public void setRunning(boolean running) {
this.running = running;
}
Sprite :
public class Sprite {
private static final int BMP_ROWS = 4;
private static final int BMP_COLUMNS = 3;
private int x = 0;
private int y = 0;
private int xSpeed = 5;
private MonsterView monsterView;
private Bitmap bmp;
private int currentFrame = 0;
private int width;
private int height;
private int directionX;
public Sprite(MonsterView monsterView, Bitmap bmp) {
this.monsterView = monsterView;
this.bmp=bmp;
this.width = bmp.getWidth() / BMP_COLUMNS;
this.height = bmp.getHeight() / BMP_ROWS;
this.directionX = 2;
}
private void update() {
if (x > monsterView.getWidth() - width - xSpeed) {
xSpeed = -5;
directionX = 1;
}
if (x + xSpeed < 0) {
xSpeed = 5;
directionX = 2;
}
x = x + xSpeed;
currentFrame = ++currentFrame % BMP_COLUMNS;
Log.d("test", ""+currentFrame);
}
public void onDraw(Canvas canvas) {
update();
int srcX = currentFrame * width;
int srcY = directionX * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
You're using setZOrderOnTop(), which is putting the Surface part of the SurfaceView on a layer above everything else. (By default, it's a separate layer below everything else.) When you clear it with canvas.drawRGB(0, 0, 0) you're setting the entire layer to opaque black, which is going to obscure the View layer beneath it.
If instead you clear it to transparent black, with canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR), you should get the results you want.
FWIW, you shouldn't override onDraw() if you're only drawing on the Surface. The onDraw() method is called by the View hierarchy to draw on the View part of the SurfaceView. If something manages to invalidate the SurfaceView's View, your onDraw() will be called, and you'll end up with a character sprite on the View layer. (Depending on your layout this may not be visible.) Just give the method a different name.
There are a number of ways to handle this, but generally, the way to do this is by maintaining a background layer (which is just another image), and sprite layers. Instead of clearing, at each frame you blit (copy) your background onto the surface (which erases everything), then you blit your sprites.
So you're going to have to draw the background bitmap onto the surface first before drawing your sprite. Right now you're drawing black which is covering your background layouts.
Alternatively you might be able to do canvas.drawRect with a Paint with paint.setColor to Color.Transparent.
i have 2 java files
this is the first one called ArcLayout
public class ArcLayout extends ViewGroup {
/**
* children will be set the same size.
*/
private int mChildSize;
private int mChildPadding = 5;
private int mLayoutPadding = 10;
public static final float DEFAULT_FROM_DEGREES = 270.0f;
public static final float DEFAULT_TO_DEGREES = 360.0f;
private float mFromDegrees = DEFAULT_FROM_DEGREES;
private float mToDegrees = DEFAULT_TO_DEGREES;
private static final int MIN_RADIUS = 100;
/* the distance between the layout's center and any child's center */
private int mRadius;
private boolean mExpanded = false;
public ArcLayout(Context context) {
super(context);
}
public ArcLayout(Context context, AttributeSet attrs) {
super(context, attrs);
if (attrs != null) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ArcLayout, 0, 0);
mFromDegrees = a.getFloat(R.styleable.ArcLayout_fromDegrees, DEFAULT_FROM_DEGREES);
mToDegrees = a.getFloat(R.styleable.ArcLayout_toDegrees, DEFAULT_TO_DEGREES);
mChildSize = Math.max(a.getDimensionPixelSize(R.styleable.ArcLayout_childSize, 0), 0);
a.recycle();
}
}
private static int computeRadius(final float arcDegrees, final int childCount, final int childSize,
final int childPadding, final int minRadius) {
if (childCount < 2) {
return minRadius;
}
final float perDegrees = arcDegrees / (childCount - 1);
final float perHalfDegrees = perDegrees / 2;
final int perSize = childSize + childPadding;
final int radius = (int) ((perSize / 2) / Math.sin(Math.toRadians(perHalfDegrees)));
return Math.max(radius, minRadius);
}
private static Rect computeChildFrame(final int centerX, final int centerY, final int radius, final float degrees,
final int size) {
final double childCenterX = centerX + radius * Math.cos(Math.toRadians(degrees));
final double childCenterY = centerY + radius * Math.sin(Math.toRadians(degrees));
return new Rect((int) (childCenterX - size / 2), (int) (childCenterY - size / 2),
(int) (childCenterX + size / 2), (int) (childCenterY + size / 2));
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int radius = mRadius = computeRadius(Math.abs(mToDegrees - mFromDegrees), getChildCount(), mChildSize,
mChildPadding, MIN_RADIUS);
final int size = radius * 2 + mChildSize + mChildPadding + mLayoutPadding * 2;
setMeasuredDimension(size, size);
final int count = getChildCount();
for (int i = 0; i < count; i++) {
getChildAt(i).measure(MeasureSpec.makeMeasureSpec(mChildSize, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mChildSize, MeasureSpec.EXACTLY));
}
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int centerX = getWidth() / 2;
final int centerY = getHeight() / 2;
final int radius = mExpanded ? mRadius : 0;
final int childCount = getChildCount();
final float perDegrees = (mToDegrees - mFromDegrees) / (childCount - 1);
float degrees = mFromDegrees;
for (int i = 0; i < childCount; i++) {
Rect frame = computeChildFrame(centerX, centerY, radius, degrees, mChildSize);
degrees += perDegrees;
getChildAt(i).layout(frame.left, frame.top, frame.right, frame.bottom);
}
}
/**
* refers to {#link LayoutAnimationController#getDelayForView(View view)}
*/
private static long computeStartOffset(final int childCount, final boolean expanded, final int index,
final float delayPercent, final long duration, Interpolator interpolator) {
final float delay = delayPercent * duration;
final long viewDelay = (long) (getTransformedIndex(expanded, childCount, index) * delay);
final float totalDelay = delay * childCount;
float normalizedDelay = viewDelay / totalDelay;
normalizedDelay = interpolator.getInterpolation(normalizedDelay);
return (long) (normalizedDelay * totalDelay);
}
private static int getTransformedIndex(final boolean expanded, final int count, final int index) {
if (expanded) {
return count - 1 - index;
}
return index;
}
private static Animation createExpandAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta,
long startOffset, long duration, Interpolator interpolator) {
Animation animation = new RotateAndTranslateAnimation(0, toXDelta, 0, toYDelta, 0, 720);
animation.setStartOffset(startOffset);
animation.setDuration(duration);
animation.setInterpolator(interpolator);
animation.setFillAfter(true);
return animation;
}
private static Animation createShrinkAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta,
long startOffset, long duration, Interpolator interpolator) {
AnimationSet animationSet = new AnimationSet(false);
animationSet.setFillAfter(true);
final long preDuration = duration / 2;
Animation rotateAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setStartOffset(startOffset);
rotateAnimation.setDuration(preDuration);
rotateAnimation.setInterpolator(new LinearInterpolator());
rotateAnimation.setFillAfter(true);
animationSet.addAnimation(rotateAnimation);
Animation translateAnimation = new RotateAndTranslateAnimation(0, toXDelta, 0, toYDelta, 360, 720);
translateAnimation.setStartOffset(startOffset + preDuration);
translateAnimation.setDuration(duration - preDuration);
translateAnimation.setInterpolator(interpolator);
translateAnimation.setFillAfter(true);
animationSet.addAnimation(translateAnimation);
return animationSet;
}
private void bindChildAnimation(final View child, final int index, final long duration) {
final boolean expanded = mExpanded;
final int centerX = getWidth() / 2;
final int centerY = getHeight() / 2;
final int radius = expanded ? 0 : mRadius;
final int childCount = getChildCount();
final float perDegrees = (mToDegrees - mFromDegrees) / (childCount - 1);
Rect frame = computeChildFrame(centerX, centerY, radius, mFromDegrees + index * perDegrees, mChildSize);
final int toXDelta = frame.left - child.getLeft();
final int toYDelta = frame.top - child.getTop();
Interpolator interpolator = mExpanded ? new AccelerateInterpolator() : new OvershootInterpolator(1.5f);
final long startOffset = computeStartOffset(childCount, mExpanded, index, 0.1f, duration, interpolator);
Animation animation = mExpanded ? createShrinkAnimation(0, toXDelta, 0, toYDelta, startOffset, duration,
interpolator) : createExpandAnimation(0, toXDelta, 0, toYDelta, startOffset, duration, interpolator);
final boolean isLast = getTransformedIndex(expanded, childCount, index) == childCount - 1;
animation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
if (isLast) {
postDelayed(new Runnable() {
#Override
public void run() {
onAllAnimationsEnd();
}
}, 0);
}
}
});
child.setAnimation(animation);
}
public boolean isExpanded() {
return mExpanded;
}
public void setArc(float fromDegrees, float toDegrees) {
if (mFromDegrees == fromDegrees && mToDegrees == toDegrees) {
return;
}
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
requestLayout();
}
public void setChildSize(int size) {
if (mChildSize == size || size < 0) {
return;
}
mChildSize = size;
requestLayout();
}
public int getChildSize() {
return mChildSize;
}
/**
* switch between expansion and shrinkage
*
* #param showAnimation
*/
public void switchState(final boolean showAnimation) {
if (showAnimation) {
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
bindChildAnimation(getChildAt(i), i, 300);
}
}
mExpanded = !mExpanded;
if (!showAnimation) {
requestLayout();
}
invalidate();
}
private void onAllAnimationsEnd() {
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
getChildAt(i).clearAnimation();
}
requestLayout();
}
}
this is the second java file called ArcMenu
public class ArcMenu extends RelativeLayout {
private ArcLayout mArcLayout;
private ImageView mHintView;
public ArcMenu(Context context) {
super(context);
init(context);
}
public ArcMenu(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
applyAttrs(attrs);
}
private void init(Context context) {
LayoutInflater li = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
li.inflate(R.layout.arc_menu, this);
mArcLayout = (ArcLayout) findViewById(R.id.item_layout);
final ViewGroup controlLayout = (ViewGroup) findViewById(R.id.control_layout);
controlLayout.setClickable(true);
controlLayout.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mHintView.startAnimation(createHintSwitchAnimation(mArcLayout.isExpanded()));
mArcLayout.switchState(true);
}
return false;
}
});
mHintView = (ImageView) findViewById(R.id.control_hint);
}
private void applyAttrs(AttributeSet attrs) {
if (attrs != null) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ArcLayout, 0, 0);
float fromDegrees = a.getFloat(R.styleable.ArcLayout_fromDegrees, ArcLayout.DEFAULT_FROM_DEGREES);
float toDegrees = a.getFloat(R.styleable.ArcLayout_toDegrees, ArcLayout.DEFAULT_TO_DEGREES);
mArcLayout.setArc(fromDegrees, toDegrees);
int defaultChildSize = mArcLayout.getChildSize();
int newChildSize = a.getDimensionPixelSize(R.styleable.ArcLayout_childSize, defaultChildSize);
mArcLayout.setChildSize(newChildSize);
a.recycle();
}
}
public void addItem(View item, OnClickListener listener) {
mArcLayout.addView(item);
item.setOnClickListener(getItemClickListener(listener));
}
private OnClickListener getItemClickListener(final OnClickListener listener) {
return new OnClickListener() {
#Override
public void onClick(final View viewClicked) {
Animation animation = bindItemAnimation(viewClicked, true, 400);
animation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
postDelayed(new Runnable() {
#Override
public void run() {
itemDidDisappear();
}
}, 0);
}
});
final int itemCount = mArcLayout.getChildCount();
for (int i = 0; i < itemCount; i++) {
View item = mArcLayout.getChildAt(i);
if (viewClicked != item) {
bindItemAnimation(item, false, 300);
}
}
mArcLayout.invalidate();
mHintView.startAnimation(createHintSwitchAnimation(true));
if (listener != null) {
listener.onClick(viewClicked);
}
}
};
}
private Animation bindItemAnimation(final View child, final boolean isClicked, final long duration) {
Animation animation = createItemDisapperAnimation(duration, isClicked);
child.setAnimation(animation);
return animation;
}
private void itemDidDisappear() {
final int itemCount = mArcLayout.getChildCount();
for (int i = 0; i < itemCount; i++) {
View item = mArcLayout.getChildAt(i);
item.clearAnimation();
}
mArcLayout.switchState(false);
}
private static Animation createItemDisapperAnimation(final long duration, final boolean isClicked) {
AnimationSet animationSet = new AnimationSet(true);
animationSet.addAnimation(new ScaleAnimation(1.0f, isClicked ? 2.0f : 0.0f, 1.0f, isClicked ? 2.0f : 0.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f));
animationSet.addAnimation(new AlphaAnimation(1.0f, 0.0f));
animationSet.setDuration(duration);
animationSet.setInterpolator(new DecelerateInterpolator());
animationSet.setFillAfter(true);
return animationSet;
}
private static Animation createHintSwitchAnimation(final boolean expanded) {
Animation animation = new RotateAnimation(expanded ? 45 : 0, expanded ? 0 : 45, Animation.RELATIVE_TO_SELF,
0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation.setStartOffset(0);
animation.setDuration(100);
animation.setInterpolator(new DecelerateInterpolator());
animation.setFillAfter(true);
return animation;
}
}
I think it has something to do with the x and y axes but i'm not sure in which of the java files
i need to change that or where exactly
After a few good hours i figured out where to make the change, its in the XML file for the arc menu
<com.capricorn.ArcMenu
android:id="#+id/arc_menu_2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="-210dp"
a ndroid:layout_marginBottom="-0dp"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
arc:fromDegrees="#dimen/menuFromDegrees"
arc:toDegrees="#dimen/menuToDegrees"
arc:childSize="#dimen/menuChildSize"/>
but i got it as far as left side of the screen.,still having trouble getting it at bottom of screen it's hanging out kind of in the middle far left of screen no matter what i do
i have created live wallpaper using canvas now i want to add the layout like(relative layout)
if its possible?
in live wallpaper we can able to use layout?
please guide me how to add layout here if its possible?
if possible means how can i called that layout in my canvas class?
in this canvas how can i overwrite the ondraw mathod?
i have searched hole internet i can't able to fine any information.
i'm new to android live wallpaper and jave plz guide me.
here is my code
public class AquariumWallpaperService extends WallpaperService {
private float mTouchX = -1;
private float mTouchY = -1;
int count = 1;
public AquaticAnimal animal;
public static final String SHARED_PREFS_NAME = "livewallpapertemplatesettings";
#Override
public Engine onCreateEngine() {
return new AquariumWallpaperEngine();
}
class AquariumWallpaperEngine extends Engine {
private Aquarium aquarium;
public AquariumWallpaperEngine() {
this.aquarium = new Aquarium();
this.aquarium.initialize(getBaseContext(), getSurfaceHolder());
}
#Override
public void onCreate(SurfaceHolder surfaceHolder) {
super.onCreate(surfaceHolder);
// By default we don't get touch events, so enable them.
setTouchEventsEnabled(true);
}
#Override
public void onVisibilityChanged(boolean visible) {
if (visible) {
this.aquarium.render();
}
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
}
#Override
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder);
this.aquarium.start();
}
#Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
super.onSurfaceDestroyed(holder);
this.aquarium.stop();
}
}
this is my canvas class
public class Aquarium {
private AquariumThread aquariumThread;
private SurfaceHolder surfaceHolder;
private ArrayList<Renderable> fishes;
private Bitmap backgroundImage, backgroundImage1;
private Bitmap boble;
public Boolean bgchange = false;
private Context context;
public int count = 1, x = 100, y = 500, x1 = 400, y1 = 500, x2 = 10,
y2 = 250;
public AquariumWallpaperEngine aqua;
public void render() {
Canvas canvas = null;
try {
count++;
if (count > 5) {
if (count % 8 == 0) {
x2++;
y--;
y1--;
}
}
if (y == -20) {
y = 600;
y1 = 600;
}
if (x2 == 700) {
x2 = -20;
}
if (count > 3000) {
bgchange = true;
}
if (count > 6000) {
bgchange = false;
count = 0;
}
//System.out.println("count" + count);
canvas = this.surfaceHolder.lockCanvas(null);
synchronized (this.surfaceHolder) {
this.onDraw(canvas);
}
} finally {
if (canvas != null) {
this.surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
protected void onDraw(Canvas canvas) {
this.renderBackGround(canvas);
for (Renderable renderable : this.fishes) {
renderable.render(canvas);
}
};
public void start() {
this.aquariumThread.switchOn();
}
public void stop() {
boolean retry = true;
this.aquariumThread.switchOff();
while (retry) {
try {
this.aquariumThread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
public int getLeft() {
return 0;
}
public int getRight() {
return this.backgroundImage.getWidth();
}
public int getRightbg() {
return this.backgroundImage1.getWidth();
}
public void initialize(Context context, SurfaceHolder surfaceHolder) {
this.aquariumThread = new AquariumThread(this);
this.surfaceHolder = surfaceHolder;
this.fishes = new ArrayList<Renderable>();
this.context = context;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
this.backgroundImage = BitmapFactory.decodeResource(
context.getResources(), com.thinkpal.live.R.drawable.aquarium,
options);
this.backgroundImage1 = BitmapFactory.decodeResource(
context.getResources(), com.thinkpal.live.R.drawable.waquarium,
options);
this.boble = BitmapFactory.decodeResource(context.getResources(),
com.thinkpal.live.R.drawable.bubble, options);
this.addFishes();
}
private void addFishes() {
Point startPoint = new Point(100, 100);
this.fishes.add(new ClownFish(this.context, this, startPoint, 90));
Point startPoint1 = new Point(100, 300);
this.fishes.add(new ClownFish(this.context, this, startPoint1, 50));
Point startPoint2 = new Point(200, 200);
this.fishes.add(new ClownFish(this.context, this, startPoint2, 15));
}
private void renderBackGround(Canvas canvas) {
Paint paint = new Paint();
canvas.drawBitmap(this.backgroundImage, 0, 0, null);
if (bgchange) {
canvas.drawBitmap(this.backgroundImage1, 0, 0, null);
}
canvas.drawBitmap(this.boble, x, y, null);
canvas.drawBitmap(this.boble, x1, y1, null);
canvas.drawBitmap(this.boble, x2, y2, null);
canvas.drawText("Think palm", x + 10, y + 45, paint);
canvas.drawText("Cochin", x1 + 20, y1 + 45, paint);
canvas.drawText("Welcome to", x2 + 10, y2 + 45, paint);
}
}
YOu could always call getTheme() in WallpaperService and then apply layouts to that, not sure what use it will be to you though. It looks like you've already got everything working, wouldn't really bother with layouts if I were you...