I have a fragment that has an animation of textView fadein. The animation must start after some time delay say 2 seconds after fragment is loaded. I wrote a code for this. but the animation part is done and then the view is rendered. How can I load the fragment and after some time delay start my animation
My code is as below: Note: the class extends Fragment
Animation animFadein;
MenuClickHelper mClickHelper;
TextView tv;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_main_menu,
container, false);
mClickHelper = new MenuClickHelper(rootView, getFragmentManager());
tv = (TextView) rootView.findViewById(R.id.tvPresentation);
animFadein = AnimationUtils.loadAnimation(getActivity()
.getApplicationContext(), R.anim.fade_in);
animFadein.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animation animation) {
if (animation == animFadein) {
Toast.makeText(getActivity().getApplicationContext(),
"Animation Stopped", Toast.LENGTH_SHORT).show();
}
}
});
try {
Thread.sleep(2000);
tv.startAnimation(animFadein);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return rootView;
}
Thread.sleep(2000); dont block your main using the sleep method instead you can use the Handler class and use postdelay to delay the animation:
sample:
change this:
try {
Thread.sleep(2000);
tv.startAnimation(animFadein);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
to
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
tv.startAnimation(animFadein);
}
}, 2000); //will start animation in 2 seconds
You can achieve the same result with
android:startOffset="2000"
in your XML animation set file.
Related
Im rotating a LinearLayout, using an ObjectAnimator. Clicking the button causes the LinearLayout to rotate 360(degrees) with the bottom part as the Pivot.
After the Layout completes the rotation, it leaves back a 'trail'/black mark and the complete view looks odd. How do I avoid this from happening? After the Layout completes the 360 animation, I want the view to look as it did in the beginning (clean basically).
Is there a view.refresh or update command im suppose to call somewhere?
1)How do I have a clean looking view at the end?
2)When the image is is in the intermediatestate, why does the back-part appear black? How do I get that to look while(ie,color of the relative layout)?
InitialState>IntermediateState>FinalState:
MainActivity
Button bt1;
float pivotX=0f;
float pivotY=0f;
int a=0;
float width,height;
ViewGroup mContainer=null;
Thread t;
private Handler mHandler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt1 = (Button) findViewById(R.id.button1);
mContainer = (ViewGroup) findViewById(R.id.container);
bt1.setOnClickListener(this);
t=new Thread()
{
#Override
public void run()
{
try {
while(true)
{
relativeLayout.postInvalidate();
}
} catch (Exception e) {
// TODO: handle exception
}
}
};
}
#Override
public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
//Here you can get the size!
width = mContainer.getWidth();
height = mContainer.getHeight();
pivotX = mContainer.getPivotX()+width;
pivotY = mContainer.getPivotY()+height;
mContainer.setPivotX(pivotX);
mContainer.setPivotY(pivotY);
}
private void rotate()
{
a -=360;
ObjectAnimator rotate = ObjectAnimator.ofFloat(mContainer, View.ROTATION_X,a);
rotate.setDuration(2000);
AnimatorSet aSet = new AnimatorSet();
aSet.play(rotate);
aSet.start();
mHandler.post(new Runnable()
{
#Override
public void run()
{
b+=1;
relativeLayout.invalidate();
relativeLayout.postInvalidate();
bt1.setText(Integer.toString(b));
}
});
rotate.addListener(new AnimatorListener()
{
#Override
public void onAnimationStart(Animator animation) {
// TODO Auto-generated method stub
//relativeLayout.invalidate();
t.start();
}
#Override
public void onAnimationRepeat(Animator animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animator animation) {
// TODO Auto-generated method stub
//mContainer.invalidate();
//relativeLayout.invalidate();
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onAnimationCancel(Animator animation) {
// TODO Auto-generated method stub
}
});
}
#Override
public void onClick(View v)
{
switch(v.getId())
{
case R.id.button1:
rotate();
break;
}
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:context=".MainActivity" >
<LinearLayout
android:id="#+id/container"
android:layout_width="fill_parent"
android:layout_height="200dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:background="#140A1F"
android:orientation="horizontal" >
</LinearLayout>
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/container"
android:layout_centerHorizontal="true"
android:layout_marginTop="80dp"
android:text="Rotate" />
</RelativeLayout>
Edit: Added a thread.
**Edit2:**** Added a handler and commented out the thread
Adding this to the code fixes the view once the animation is competed, but the intermediate stage still looks the same. Will update this once I figure that out.
rotate.addListener(new AnimatorListener()
{
#Override
public void onAnimationStart(Animator animation) {
// TODO Auto-generated method stub
relativeLayout.invalidate();
}
#Override
public void onAnimationRepeat(Animator animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animator animation) {
// TODO Auto-generated method stub
//mContainer.invalidate();
relativeLayout.invalidate();
}
#Override
public void onAnimationCancel(Animator animation) {
// TODO Auto-generated method stub
}
});
I am building a snake game app.
So fur it works, except for the what it shows.
For some reason it shows two snakes: the original snake that moves and can be controlled, and another begginging of a snake that doesn't do anything.
Before that I drew at every cycle in the loop a background color, so it would cover the last canvas, and there was no problem.
Then I decided to divide the snake from the background, so I have made the snake canvas's background transparent and that it would clear the canvas each time it wants to draw a new canvas (each loop-to move the snake).
Here is the code:
The run of the thread:
public void run() {
long stepPerSecond=1000/FPS;
long startTime;
long sleepTime;
while(isRunning){
Canvas c=null;
startTime=System.currentTimeMillis();
try{
c=this.getHolder().lockCanvas();
synchronized (this.getHolder()) {
this.onDraw(c);
}
}
catch(Exception e){
}
finally{
if(c!=null){
this.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime= stepPerSecond-(System.currentTimeMillis()-startTime);
if(sleepTime>0)
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The snake's ondraw (it uses the snake's class on draw):
public void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.drawColor(color.transparent, Mode.CLEAR);
snake.onDraw(canvas);
}
The snake's class onDraw:
public void onDraw(Canvas canvas){
switch(dirTransfare(dir)){
case 1://RIGHT
xLoc=xLoc+PART_SIZE;
break;
case 2://UP
yLoc=yLoc-PART_SIZE;
break;
case -1://LEFT
xLoc=xLoc-PART_SIZE;
break;
case -2://DOWN
yLoc=yLoc+PART_SIZE;
break;
}//swich
int x=xLoc;
int y=yLoc;
for(Brick bp:SnakeBody){
bp.setR(0+x, 0+y, PART_SIZE+x, PART_SIZE+y);
canvas.drawRect(bp.getR(),bp.getP());
int xtemp=bp.getX();
int ytemp=bp.getY();
bp.setX(x);
bp.setY(y);
x=xtemp;
y=ytemp;
}//for each
}//onDraw
Here is the mainActivity, which summons the snakeVew and the backgorundView (snake is the game view and the background is the arena)
public class MainActivity extends Activity {
GameView gv;
ImageView left;
ImageView right;
ImageView up;
ImageView down;
Arena a;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/*requestWindowFeature(Window.FEATURE_NO_TITLE);
v= new GameView1(this);
setContentView(v);
*/
gv= new GameView(this);
a=new Arena(this);
setContentView(R.layout.game_view);
LinearLayout surface = new LinearLayout(this);
LinearLayout backGround = new LinearLayout(this);
surface = (LinearLayout)findViewById(R.id.surface);
backGround = (LinearLayout)findViewById(R.id.background);
surface.addView(gv);
backGround.addView(a);
left=(ImageView) findViewById(R.id.left);
right=(ImageView) findViewById(R.id.right);
up=(ImageView) findViewById(R.id.up);
down=(ImageView) findViewById(R.id.down);
left.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(gv.snake.getDir()!="LEFT"&&gv.snake.getDir()!="RIGHT"){
gv.snake.Left();
}
}
});
right.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(gv.snake.getDir()!="RIGHT"&&gv.snake.getDir()!="LEFT"){
gv.snake.Right();
}
}
});
up.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(gv.snake.getDir()!="UP"&&gv.snake.getDir()!="DOWN"){
gv.snake.Up();
}
}
});
down.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(gv.snake.getDir()!="DOWN"&&gv.snake.getDir()!="UP"){
gv.snake.Down();
}
}
});
}
The problem is not in the background (the arena class); I have alredy took it down and confirmed that (it worked the same away, with the bug, even without using the arena class).
Here is how it looks with the bug:
http://i.tinyuploads.com/q7oztz.jpg
(you can see two snakes - the long one is the real one)
The blue background is from class arena.
Any ideas? Tnx for help :D
I am building a snake game, and it works, but with a little bug that really irritates me.
when I click on one of the buttons that in the xml, the snake changes it's direction according to the button.
the problem is that if you have clicked on a button after it's has already re-entered the loop inside the run() of the thread and entered the loop inside the the onDraw() (you can see in the code) it will first finish the loop of the run() and then re-enter and do the turn. and by that a delay is created from the click time to when it turns.
the turn works like this- there is a String variable that gets "LEFT","RIGHT", "UP" or "DOWN", according to what it gets it moves the snake. when you click on a button it changes the variable accoring to what button u have clicked on.
heres the code of how it moves the snake accoring to the direction:
public void onDraw(Canvas canvas){
switch(direction){
case "RIGHT"
xLoc=xLoc+PART_SIZE;
break;
case "UP"
yLoc=yLoc-PART_SIZE;
break;
case "LEFT"
xLoc=xLoc-PART_SIZE;
break;
case "DOWN"
yLoc=yLoc+PART_SIZE;
break;
}//swich
int x=xLoc;
int y=yLoc;
for(BodyPart bp:WholeBody){
Rect r=new Rect();
r.set(0+x, 0+y, PART_SIZE+x, PART_SIZE+y);
bp.setR(r);
canvas.drawRect(bp.getR(),bp.getP());
int xtemp=bp.getX();
int ytemp=bp.getY();
bp.setX(x);
bp.setY(y);
x=xtemp;
y=ytemp;
}//for each
}//onDraw
the xLoc and the yLoc is the location of where the head of the snake will go to, and the its moves each body part(each rect of the snake-each bodypart is an equall rect) the the location of where the bodypart before it was.
here are the onClick()s:
left.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(gv.snake.getDir()!="LEFT"&&gv.snake.getDir()!="RIGHT"){
gv.snake.Left();
}
}
});
right.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(gv.snake.getDir()!="RIGHT"&&gv.snake.getDir()!="LEFT"){
gv.snake.Right();
}
}
});
up.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(gv.snake.getDir()!="UP"&&gv.snake.getDir()!="DOWN"){
gv.snake.Up();
}
}
});
down.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(gv.snake.getDir()!="DOWN"&&gv.snake.getDir()!="UP"){
gv.snake.Down();
}
}
});
gv is an variable from class gameView which in it has a variable from the class snake
here are the setDirection:
public void Left(){
direction="LEFT";
}
public void Up(){
direction="UP";
}
public void Right(){
direction="RIGHT";
}
public void Down(){
direction="DOWN";
}
and here is the run of the thread:
public void run() {
long stepPerSecond=1000/FPS;
long startTime;
long sleepTime;
while(isRunning){
Canvas c= null;
startTime=System.currentTimeMillis();
try{
c=this.getHolder().lockCanvas();
synchronized (this.getHolder()) {
this.onDraw(c);
}
}
catch(Exception e){
}
finally{
if(c!=null){
this.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime= stepPerSecond-(System.currentTimeMillis()-startTime);
if(sleepTime>0)
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
else
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
is there someway that there will not be that delay?
maby when you click on a button it will stop the run() and redo it after it had updated the direction variable acording to the click.
First I have to admit that I am a beginer with the android programing and may not understand things correctly.
Secondly, the problem:
In my app, I've created a loading screen, and with a theard I have tried to restrict the time of this screen so when the time is over - it's move via intent to another screen.
The code:
public class MainActivity extends Activity implements OnClickListener {
ImageView iv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.loading_screen);
iv=(ImageView)findViewById(R.id.imgBtn1);
iv.setBackgroundResource(R.anim.loading_i_animation);
iv.setOnClickListener(this);
}
public void onClick(final View iv) {
// TODO Auto-generated method stub
Thread t1=new Thread(new Runnable() {
#Override
public void run() {
AnimationDrawable anim=(AnimationDrawable) iv.getBackground();
anim.start();
}
});
t1.start();
try {
t1.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t1.stop();
//The moving to the other screen
Intent st=new Intent(MainActivity.this,Welcome.class);
startActivity(st);
} }
The intent itself work, as well as the animation of the loading_screen. However when I writed "t1.stop();" in order to stop the thread - it earsed it.
I understand. I forgot to use finish() and to proceed I have the option of "finally".
Correct code:
public class MainActivity extends Activity implements OnClickListener {
ImageView iv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.loading_screen);
iv=(ImageView)findViewById(R.id.imgBtn1);
iv.setBackgroundResource(R.anim.loading_i_animation);
iv.setOnClickListener(this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public void onClick(final View iv) {
// TODO Auto-generated method stub
Thread t1=new Thread(new Runnable() {
#Override
public void run() {
AnimationDrawable anim=(AnimationDrawable) iv.getBackground();
anim.start();
}
});
t1.start();
try {
t1.sleep(1000);
finish();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
Intent st=new Intent(MainActivity.this,Welcome.class);
startActivity(st);
}
}
}
i need some good advice for my code.
here is what i want to do.
i have an activity that has some views that can be selected by user. assumed that the user selected a view, i want to deselect this view automatically after, let's say, 5 seconds.
I do this by a thread.
when the user selects the view, i call...
Deselector deselect = new Deselector(mp.getDuration(), clickedview);
deselect.start();
...in the activity.
the deselector class:
class Deselector extends Thread
{
int millis=0;
View view = null;
Deselector(int millis, View view)
{
this.millis = millis;
this.view = view ;
}
#Override
public void run() {
// TODO Auto-generated method stub
try {
this.sleep(millis);
view.setSelected(false);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
my program crashes and logkitty says
12-11 14:29:37.457: ERROR/AndroidRuntime(3263): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
how to do it right?
thanks in advance
m.d.
Use postDelayed() on a widget or a Handler, rather than a background thread, to do work after your proposed delay.
i got it working by doing the following
clickedview.postDelayed(new Deselector(clickedview), mp.getDuration());
with my deselctor runnable now a bit shorter:
class Deselector implements Runnable
{
View view = null;
Deselector(View view)
{
this.view = view ;
}
#Override
public void run() {
// TODO Auto-generated method stub
try {
view.setSelected(false);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}