I'm puzzled with the problem "AnimationDrawable not change frames" for some time.I'm confirmed I've added all the frames I need into the AnimationDrawable object,and I've called start(),and the result I called isRunning() is true,but the AnimationDrawable can't change the frame.
I called the start() in MainActivity's handler,not in onCreate() or onResume(),although the the called of start() is in the onResume() state.
Thanks for your thinkings.
----^_^ banlalaotou.
Added code which has the problem.
public class MainActivity extends Activity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ma = new Ma(this);
ablt = ma.ablt;
setContentView(ablt);
mt = new MinorThread(this);
new Thread(mt).start();
while(true){
if(mt.mHandler==null) continue;
else{
Message msg = new Message();
mt.mHandler.sendMessage(msg);
break;
}
}
}
Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
ma.control();
Message msg1 = new Message();
mt.mHandler.sendMessage(msg1);
}
};
#Override
public boolean onKeyDown(int keyCode,KeyEvent event){
switch(keyCode){
case KeyEvent.KEYCODE_BACK:
System.exit(0);
}
return true;
}
private MinorThread mt = null;
private ImageView v1 = null;
private Ma ma = null;
private int x = 0;
private int y = 0;
private int width = 0;
private int height = 0;
private AbsoluteLayout ablt = null;
}
class MinorThread implements Runnable{
#Override
public void run() {
Looper.prepare();
mHandler = new Handler(){
#Override
public void handleMessage(Message msg){
Message msg2 = new Message();
mainActivity.handler.sendMessage(msg2);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Looper.loop();
}
public MinorThread(MainActivity mainAcitivy){
this.mainActivity = mainAcitivy;
}
private MainActivity mainActivity = null;
public Handler mHandler = null;
}
class Ma{
public Ma(MainActivity context){
ablt = new AbsoluteLayout(context);
TestView v = new TestView(context);
AbsoluteLayout.LayoutParams lp = new LayoutParams(480,320,0,0);
ablt.addView(v, lp);
Drawable d = null;
ad = new AnimationDrawable();
d = context.getResources().getDrawable(R.drawable.f1);
ad.addFrame(d, 100); d = context.getResources().getDrawable(R.drawable.f2);
ad.addFrame(d, 100); d = context.getResources().getDrawable(R.drawable.f3);
ad.addFrame(d, 100); d = context.getResources().getDrawable(R.drawable.f4);
ad.addFrame(d, 100); d = context.getResources().getDrawable(R.drawable.f5);
ad.addFrame(d, 100);
v1 = new ImageView(context);
v1.setImageDrawable(ad);
String tag = "test";
v1.setTag(tag);
ablt.addView(v1, new LayoutParams(100, 40, 20, 20));
}
public void control(){
v1 = (ImageView) ablt.findViewWithTag("test");
if(x<480&&y<320){
x+=10;
y+=5;
v1.layout(x, y, x+100, y+40);
AnimationDrawable ad = (AnimationDrawable)v1.getDrawable();
ad.start();
}
}
public AbsoluteLayout ablt = null;
private AnimationDrawable ad = null;
private ImageView v1 = null;
private int x = 0;
private int y = 0;
private int width = 0;
private int height = 0;
}
class TestView extends View{
public TestView(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas){
paint.setColor(Color.WHITE);
canvas.drawRect(0,0,480,320, paint);
}
private Paint paint = new Paint();
}
I'sorry for not uploaded the frames,because my reputation is less than 10.
If you execute the code,you need to find some pictures to let the animation run.
thanks.
=============================
Now,I know how to let the result show,but I can't know the resaon.
The solution of the problem is that add a ImageView object into the layout object before show the all ImageView,and, "add a ImageView..." and "show the all ImageView" can't been processed in an function.The right method is like that "if(..){add a ImageView}else{show the all ImageView}".
Although,this method can resolve the problem I'd puzzeled,but why Android can't show the all ImageView's animations at first time?
Try to use start() in onWindowFocusChange(boolean focus) when focus is true.
Related
I am making horizontal scrollview gallery, and I want to autoscroll it. Now it's scrolling from left to right but when I reach end of list I just simply jump to first one, but it looks really bad, so I want to go scroll around from beginning avoiding just skipping to first one, or if it is not possible just start scrolling to the other side when I reach last view on right (maybe better option). Could someone help me how to do this?
private LinearLayout horizontalOuterLayout;
private HorizontalScrollView horizontalScrollview;
private int scrollMax;
private int scrollPos = 0;
private TimerTask clickSchedule;
private TimerTask scrollerSchedule;
private TimerTask faceAnimationSchedule;
private Timer scrollTimer = null;
private Timer faceTimer = null;
private String[] imageNameArray ={ "sponsors_czarnykot", "sponsors_estradarzeszow","sponsors_klubp","sponsors_kula","sponsors_czarnykot", "sponsors_estradarzeszow","sponsors_klubp","sponsors_kula" };
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.horizontal_layout);
horizontalScrollview = (HorizontalScrollView) findViewById(R.id.horiztonal_scrollview_id);
horizontalOuterLayout = (LinearLayout) findViewById(R.id.horiztonal_outer_layout_id);
horizontalScrollview.setHorizontalScrollBarEnabled(false);
addImagesToView();
ViewTreeObserver vto = horizontalOuterLayout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
#Override
public void onGlobalLayout()
{
horizontalOuterLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
getScrollMaxAmount();
startAutoScrolling();
}
});
}
public void getScrollMaxAmount()
{
int actualWidth = (horizontalOuterLayout.getMeasuredWidth() - 512);
scrollMax = actualWidth;
}
public void startAutoScrolling()
{
if (scrollTimer == null)
{
scrollTimer = new Timer();
final Runnable Timer_Tick = new Runnable()
{
public void run()
{
moveScrollViewRight();
}
};
if (scrollerSchedule != null)
{
scrollerSchedule.cancel();
scrollerSchedule = null;
}
scrollerSchedule = new TimerTask()
{
#Override
public void run()
{
runOnUiThread(Timer_Tick);
}
};
scrollTimer.schedule(scrollerSchedule, 30, 30);
}
}
public void moveScrollViewRight()
{
scrollPos = (int) (horizontalScrollview.getScrollX() + 1.0);
if (scrollPos >= scrollMax)
{
scrollPos = 0;
}
horizontalScrollview.scrollTo(scrollPos, 0);
}
/** Adds the images to view. */
public void addImagesToView()
{
for (int i = 0; i < imageNameArray.length; i++)
{
final ImageView imageView = new ImageView(this);
int imageResourceId = getResources().getIdentifier(imageNameArray[i], "drawable", getPackageName());
Drawable image = this.getResources().getDrawable(imageResourceId);
imageView.setBackgroundDrawable(image);
imageView.setTag(i);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(180, 123);
params.setMargins(0, 25, 0, 25);
imageView.setLayoutParams(params);
horizontalOuterLayout.addView(imageView);
}
}
public void stopAutoScrolling()
{
if (scrollTimer != null)
{
scrollTimer.cancel();
scrollTimer = null;
}
}
public void onBackPressed()
{
super.onBackPressed();
finish();
}
public void onPause()
{
super.onPause();
finish();
}
public void onDestroy()
{
clearTimerTaks(clickSchedule);
clearTimerTaks(scrollerSchedule);
clearTimerTaks(faceAnimationSchedule);
clearTimers(scrollTimer);
clearTimers(faceTimer);
clickSchedule = null;
scrollerSchedule = null;
faceAnimationSchedule = null;
scrollTimer = null;
faceTimer = null;
super.onDestroy();
}
private void clearTimers(Timer timer)
{
if (timer != null)
{
timer.cancel();
timer = null;
}
}
private void clearTimerTaks(TimerTask timerTask)
{
if (timerTask != null)
{
timerTask.cancel();
timerTask = null;
}
}
scrolling back the other way would be easiest.
add in a instance variable that is set to 1.0 (called say scrollDist)
then change this line
scrollPos = (int) (horizontalScrollview.getScrollX() + 1.0);
to
scrollPos = (int) (horizontalScrollview.getScrollX() + scrollDist);
and this line
scrollPos = 0;
to
scrollDist *= -1.0;
this way it will reverse each time it hits the end of the scrollview.
For endless scrolling use the following snnipet
public void getScrollMaxAmount() {
int actualWidth = (horizontalOuterLayout.getMeasuredWidth() - getWindowManager().getDefaultDisplay().getWidth());
scrollMax = actualWidth;
}
public void moveScrollView() {
// ********************* Scrollable Speed ***********************
scrollPos = (int) (horizontalScrollview.getScrollX() + 1.0);
if (scrollPos >= scrollMax) {
Log.v("childCount", ""+scrollMax);
addImagesToView();
getScrollMaxAmount();
}
horizontalScrollview.scrollTo(scrollPos, 0);
}
I'm current creating a game and i've made 3 main classes - GameView (which extends surfaceview), GameViewThread (which is a thread used for surfaceview) and a MainActivity.
I want to enter a background image in SurfaceView, but have not been able to figure out how to do so.
Using setBackground() in the onDraw method of GameView doesn't work as well.
I would greatly appreciate any help you guys can provide me with.
Here is my GameView class:
public class GameView extends SurfaceView implements SurfaceHolder.Callback {
private Bitmap bmp1;
private SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private Sprite sprite;
private float sensorX = 0;
private Platform platform[] = new Platform[7];
private Bonus GravUp[] = new Bonus[3];
private Bonus GravDown[] = new Bonus[3];
private Bitmap bmp2;
private Bitmap bmp3;
private boolean collision;
private int a;
private int b;
private int c1;
private double c2;
int agility = 50;
private Bitmap bmp4;
public double getsensorX() {
return sensorX;
}
public double setsensorX(float s) {
return sensorX = s;
}
synchronized public int getSpriteY() {
return sprite.y;
}
synchronized public int getSpriteX() {
return sprite.x;
}
synchronized public int getSpriteHeight() {
return sprite.height;
}
synchronized public int getSpriteWidth() {
return sprite.width;
}
public GameView(Context context) {
super(context);
gameLoopThread = new GameLoopThread(this);
holder = getHolder();
holder.addCallback(this);
bmp1 = BitmapFactory.decodeResource(getResources(), R.drawable.russel);
sprite = new Sprite(this);
sprite.getBMP(bmp1);
bmp2 = BitmapFactory.decodeResource(getResources(), R.drawable.brick);
bmp3 = BitmapFactory.decodeResource(getResources(), R.drawable.gravup);
bmp4 = BitmapFactory.decodeResource(getResources(), R.drawable.gravdown);
for (int i = 0; i < GravUp.length; i++) {
GravUp[i] = new Bonus(this, bmp3);
}
for (int i = 0; i < GravDown.length; i++) {
GravDown[i] = new Bonus(this, bmp4);
}
for (int i = 0; i < platform.length; i++) {
Random r = new Random();
platform[i] = new Platform(this, bmp2, 850 + 200 * i,
400 - r.nextInt(250));
}
}
#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) {
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.YELLOW);
sprite.Draw(canvas);
for (int i = 0; i < platform.length; i++) {
platform[i].Draw(canvas);
}
for (int i = 0; i < GravUp.length; i++) {
GravUp[i].Draw(canvas);
}
for (int i = 0; i < GravDown.length; i++) {
GravDown[i].Draw(canvas);
}
}
My MainActivity Class:
public class MainActivity extends Activity {
GameView gameView;
FrameLayout game;
RelativeLayout GameButtons;
Button butOne;
Button butTwo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gameView = new GameView(this);
game = new FrameLayout(this);
GameButtons = new RelativeLayout(this);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT);
GameButtons.setLayoutParams(params);
game.addView(gameView);
game.addView(GameButtons);
setContentView(game);
}
}
How can I use an image I have saved in res/drawable-hdpi folder as the background to my game?
Should I use the command in GameView or MainActivity?
Do let me know if you need more information in order to help me out!
Thank you
I am a newbie in android and started with livewallpaper development using Wallpaper Engine. My problem is the run() method inside Runnable is not called dont know why.... Am I missing something?
Here is my code:
public class Hearts extends WallpaperService {
public static boolean LANDSCAPE;
public static Paint backgroundPaint;
public static Point backgroundSize;
public static Point globalCanvasSize;
public static boolean landscapeMode = false;
public static int maxScreenSize;
Bitmap background;
private final Handler mHandler = new Handler();
public void onCreate() {
super.onCreate();
}
public WallpaperService.Engine onCreateEngine() {
return new HeartsEngine();
}
public void onDestroy() {
super.onDestroy();
}
class HeartsEngine extends Engine {
private final int amountOfFlakes = 40;
private final Paint backgroundPaint = new Paint();
private Canvas c;
public Flake[] flakeArray = new Flake[40];
final SurfaceHolder holder = getSurfaceHolder();
private final Runnable mDrawCube = new Runnable() {
#Override
public void run() {
Log.d("tag", "Inside Run Called");
drawFrame();
}
};
float mXOffset;
float mYOffset;
private float oldScreen;
Random random = new Random();
Resources res = Hearts.this.getResources();
HeartsEngine() {
super();
Log.d("tag", "Constructyor");
}
void drawFrame() {
Log.d("tag", "drawFrame");
this.oldScreen -= this.mXOffset;
Flake.scrollSpeed = 48.0F * this.oldScreen;
this.oldScreen = this.mXOffset;
this.c = null;
this.c = this.holder.lockCanvas();
try {
if (this.c != null)
this.c.drawBitmap(Hearts.this.background, 0.0F, 0.0F, null);
for (int i = 0;; i++) {
if (i >= 40) {
this.holder.unlockCanvasAndPost(this.c);
Hearts.this.mHandler.postDelayed(this.mDrawCube, 16L);
}
this.flakeArray[i].updateFlake(this.random, this.res,
this.c);
}
} catch (IllegalArgumentException localIllegalArgumentException) {
// break label94;
localIllegalArgumentException.printStackTrace();
return;
}
}
You call drawFrame() only inside the mDrawCube Runnable. So there is no a first time call for the drawFrame() method
I'm developing a simple game like BSD robots. This game contains a rather large board (over 40 cells) and it doesn't look nice even at 10 inch tablet. My decision was to scroll (move) surface view and not to scale each figure which size is like finger spot.
I've read tons articles about surface view but I cannot understand how to move it?
My activity code:
package ru.onyanov.robots;
public class MainActivity extends Activity {
public BoardView board;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
board = new BoardView(this);
setContentView(board);
}
}
Class Board:
package ru.onyanov.robots;
public class BoardView extends SurfaceView {
private GameThread mThread;
private boolean running = false;
public final int sizeX = 50;
public final int sizeY = 35;
public final int cellSize = 64;
private int robotCount = 4;
public ArrayList<Cell> cells = new ArrayList<Cell>();
private ArrayList<Robot> robots = new ArrayList<Robot>();
private Hero hero;
public Bitmap imageCell;
public Bitmap imageRobot;
public Bitmap imageHero;
public BoardView(Context context) {
super(context);
makeGraphic();
constructCells();
constructRobots();
hero = new Hero(this, 3, 2, imageHero);
mThread = new GameThread(this);
getHolder().addCallback(new SurfaceHolder.Callback() {
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
mThread.setRunning(false);
while (retry) {
try {
mThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
mThread.setRunning(true);
mThread.start();
}
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
}
private void makeGraphic() {
Bitmap cellImageSource = BitmapFactory.decodeResource(getResources(),
R.drawable.cell);
imageCell = Bitmap.createScaledBitmap(cellImageSource, cellSize,
cellSize, false);
imageRobot = BitmapFactory.decodeResource(getResources(),
R.drawable.robot);
imageHero = BitmapFactory.decodeResource(getResources(),
R.drawable.hero);
}
private void constructRobots() {
Robot robot;
Random rand = new Random();
for (int r = 0; r < robotCount; r++) {
int x = rand.nextInt(sizeX);
int y = rand.nextInt(sizeY);
robot = new Robot(this, x, y, imageRobot);
robots.add(robot);
}
return;
}
private void constructCells() {
Cell cell;
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
cell = new Cell(this, x, y, imageCell);
cells.add(cell);
}
}
return;
}
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
Cell cell;
for (int c = 0; c < cells.size(); c++) {
cell = cells.get(c);
cell.onDraw(canvas);
}
Robot robot;
for (int r = 0; r < robots.size(); r++) {
robot = robots.get(r);
robot.onDraw(canvas);
}
hero.onDraw(canvas);
}
public boolean onTouchEvent(MotionEvent e) {
int shotX = (int) e.getX();
int shotY = (int) e.getY();
if (e.getAction() == MotionEvent.ACTION_MOVE){
//TODO move board
showToast("move Board");
} else if (e.getAction() == MotionEvent.ACTION_UP) {
showToast("touchPoint: " + shotX + ", "+shotY);
hero.moveByDirection(shotX, shotY);
this.scrollTo(shotX, shotY);
}
return true;
}
public void showToast(String mes) {
Toast toast = Toast.makeText(getContext(), mes, Toast.LENGTH_LONG);
toast.show();
}
public class GameThread extends Thread {
private BoardView view;
public GameThread(BoardView view) {
this.view = view;
}
public void setRunning(boolean run) {
running = run;
}
public void run() {
while (running) {
Canvas canvas = null;
try {
canvas = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
onDraw(canvas);
}
canvas.scale(300, 300);
} catch (Exception e) {
} finally {
if (canvas != null) {
view.getHolder().unlockCanvasAndPost(canvas);
}
}
}
}
}
}
Some magic digits here are temporary. Now I just want to move BoardView;
The issue was to add x and y fields to SurfaceView, change them at onTouchEvent and draw all the elements in canvas with x- and y-offset. It's strange that I didn't recieved any answers...
Is it possible to pass arguments to an Android Handler?? I have two pieces of code.
new Thread(){
public void run(){
for(;;){
uiCallback.sendEmptyMessage(0);
Thread.sleep(2000); //sleep for 2 seconds
}
}
}.start();
private Handler uiCallback = new Handler(){
public void handleMessage(Message msg){
//add a new blossom to the blossom ArrayList!!
blossomArrayList.add(new Blossom(context, R.drawable.blossom));
}
};
I of course get an error because the Handler method cannot see my context. This is probably because of this piece of code
public BoardView(Context context){
super(context);
Context is not visible elsewhere, and I'm wondering if I can pass it as an argument to my Handler.
EDIT: I am posting the two main pieces of code to answer a question about why my Blossom object needs context. I myself am not 100% sure >.> Maybe you could have a look and see what's going on.
public class Blossom{
private Bitmap blossom;
private float blossomX = 0;
private float blossomY = 0;
private Random generator = new Random();
public Blossom(Context context, int drawable)
{
blossom = BitmapFactory.decodeResource(context.getResources(), drawable);
blossomX = generator.nextInt(300);
}
public Bitmap getBitmap()
{
return blossom;
}
public float getBlossomX()
{
return blossomX;
}
public float getBlossomY()
{
return blossomY;
}
public void Fall(Canvas canvas, float boxY)
{
//draws the flower falling
canvas.drawBitmap(blossom, blossomX,
blossomY = blossomY+3 , null);
//collision detection, currently not working after
//implementing random start location
//if(blossomY + 29 == boxY)
//{
//canvas.drawBitmap(blossom,0,0,null);
//}
}
}
public class BoardView extends SurfaceView implements SurfaceHolder.Callback{
Context mContext;
Bitmap box =
(BitmapFactory.decodeResource
(getResources(), R.drawable.box));
private BoardThread thread;
private float box_x = 140;
private float box_y = 378;
private float boxWidth = box.getWidth();
private float boxHeight = box.getHeight();
private ArrayList<Blossom> blossomArrayList = new ArrayList<Blossom>();;
boolean mode = false;
RectF boxRect = new RectF(box_x,box_y, box_x + boxWidth, box_y + boxHeight);
public BoardView(Context context){
super(context);
//surfaceHolder provides canvas that we draw on
getHolder().addCallback(this);
// controls drawings
thread = new BoardThread(getHolder(),this);
//pass variables to instance of Blossom
//for(int i = 0; i <= 3; i++)
//{
//blossomArrayList.add(new Blossom(context, R.drawable.blossom));
//}
new Thread(){
public void run(){
for(;;){
uiCallback.sendEmptyMessage(0);
Thread.sleep(2000); //sleep for 2 seconds
}
}
}.start();
//intercepts touch events
setFocusable(true);
}
#Override
public void onDraw(Canvas canvas){
canvas.drawColor(Color.WHITE);
//draw box and set start location
canvas.drawBitmap(box, box_x - (boxWidth/2),
box_y - (boxHeight/2), null);
for(int i = 0; i<= 3; i++)
{
blossomArrayList.get(i).Fall(canvas, box_y);
}
}
#Override
public boolean onTouchEvent(MotionEvent event){
if(event.getAction() == MotionEvent.ACTION_DOWN){
if(boxRect.contains(event.getX(),event.getY())){
mode = true;
}
}
if(event.getAction() == MotionEvent.ACTION_MOVE) {
if(boxRect.contains(event.getX(),event.getY())){
mode = true;
}
if(mode == true){
box_x = (int)event.getX();
boxRect.set(box_x,box_y, box_x + boxWidth, box_y + boxHeight);
}
}
if(event.getAction() == MotionEvent.ACTION_UP){
mode = false;
}
invalidate();
return true;
}
#Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height ){
}
#Override
public void surfaceCreated(SurfaceHolder holder){
thread.startRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder){
thread.startRunning(false);
thread.stop();
}
private Handler uiCallback = new Handler(){
public void handleMessage(Message msg){
//add a new blossom to the blossom ArrayList!!
blossomArrayList.add(new Blossom(context, R.drawable.blossom));
}
};
}
Create a class that extends Handler, and store a weak reference to the context. This will help prevent some memory issues.
public class SomeHandler extends Handler {
// A weak reference to the enclosing context
private WeakReference<Context> mContext;
public SomeHandler (Context context) {
mContext = new WeakReference<Context>(context);
}
public void handleMessage(Message msg) {
// Get an actual reference to the DownloadActivity
// from the WeakReference.
Context context=mContext.get();
...
}
}
What if you create a subclass which extends Handler? That way you could pass any parameters you want.
But just out of curiosity, why does the Blossom object require the context object? It's usually best to separate your logic from GUI dependencies.