I\'m trying to move button (with animation) upon click. I want it to move 100 pixels to the bottom on first click, 100 pixels up on second, 100 pixels to the bottom on third
Yes, this is normal behavior. This is because animation just rerenders View
's pixels, but it's position on the display remains the same. If you want to relocate your View
to the place where your animation ends, you need to call View.layout()
method and pass there 4 parameters, which describe View
s new position on it's layout. Keep in mind that View.layout()
gets params relative to View
s parent.
View.layout() really works, thanks a lot, teoREtik. Here I provide working variant, which moves the button itself (hope it will be useful for somebody):
public class TestActivity extends Activity {
public final String TAG="TestActivity";
boolean toTop=false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button b=(Button)findViewById(R.id.button);
b.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
int modifierY;
if(toTop) modifierY=-100;
else modifierY=100;
Animation translateAnimation=new TranslateAnimation(0, 0, 0, modifierY);
translateAnimation.setDuration(1000);
translateAnimation.setFillEnabled(true);
MyAnimationListener listener=new MyAnimationListener(v, modifierY,TestActivity.this);
translateAnimation.setAnimationListener(listener);
v.startAnimation(translateAnimation);
toTop=!toTop;
}
});
}
We have to invoke View.layout() only when animation is finished, so we need to use AnimationListener.onAnimationEnd. In order to be able to specify button and modifierY, I created my custom AnimationListener, which receives button and modifierY in constructor:
public class MyAnimationListener implements AnimationListener{
View mView;
int mModifier;
Context mContext;
public MyAnimationListener(View v, int modifier, Context c){
mView=v;
mModifier=modifier;
mContext=c;
}
public void onAnimationEnd(Animation animation) {
int[] pos={mView.getLeft(),mView.getTop()+mModifier,mView.getRight(),mView.getBottom()+mModifier};
mView.layout(pos[0],pos[1],pos[2],pos[3]);
Toast.makeText(mContext, "left="+mView.getLeft()+"\ntop="+mView.getTop(), Toast.LENGTH_SHORT).show();
}
public void onAnimationRepeat(Animation animation) {}
public void onAnimationStart(Animation animation) {}
}
There is an easier way worth mentioning. One can use the View.animate() method which also moves the clickable elements:
v.animate().translationY(100).start(); // move away
v.animate().translationY(0).start(); // move back
An easy solution is to add padding in the onAnimationEnd function:
public void moveAnimation() {
move = new TranslateAnimation(Pos-50, 0, 0, 0);
Pos += 50.0;
move.setDuration(1500);
move.setFillAfter(true);
move.setAnimationListener(new AnimationListener(){
@Override
public void onAnimationEnd(Animation arg0) {
int x=(int) (Pos-50),y=0;
i.setPadding(x,y,0,0);
x+=50; y+=0;
i.setPadding(x,y,0,0);
}
@Override
public void onAnimationRepeat(Animation arg0) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationStart(Animation arg0) {
// TODO Auto-generated method stub
}
});
i.startAnimation(move);
}
where i = (ImageView) findViewById(R.id.imgAMD);