What I want to do is simple. I want to have a looping background, so that it looks like the ground is moving. Here is how I am trying to do it however, it looks like both images are being dispatched at same time.
public void moveGround(){
startingXPosition =1500.0f;
endingXPosition = -1500.0f;
startingYPosition =0.0f;
endingYPosition =0.0f;
ImageView ground = (ImageView)findViewById(R.id.ground);
TranslateAnimation groundAnimation = new TranslateAnimation(startingXPosition,endingXPosition,startingYPosition,endingYPosition);
groundAnimation.setDuration(1500);
groundAnimation.setRepeatCount(Animation.INFINITE);
ground.startAnimation(groundAnimation);
if(ground.getLeft()<=0) {
float startingXPosition2 = 1500.0f;
float endingXPosition2 = -1500.0f;
float startingYPosition2 = 0.0f;
float endingYPosition2 = 0.0f;
ImageView ground2 = (ImageView) findViewById(R.id.ground2);
TranslateAnimation groundAnimation2 = new TranslateAnimation(startingXPosition2, endingXPosition2, startingYPosition2, endingYPosition2);
groundAnimation2.setDuration(1500);
groundAnimation2.setRepeatCount(Animation.INFINITE);
ground2.startAnimation(groundAnimation2);
}
}
try
yourAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
// do what you want
}
#Override
public void onAnimationRepeat(Animation animation) {
// do what you want
}
});
Related
I make some sort of quiz app and I want that every time an answer button get clicked there will be an animation changing to to yellow. after 0.25sec the next question will appear (and I want it to change back to the old color)
I already did it here:
public void onClick(View v) {
x
for (int i = 0; i < 4; i++) {
if(v == answerButtons[i]){
int j = i;
ValueAnimator valueAnimator = new ValueAnimator();
valueAnimator.setDuration(250);
valueAnimator.setEvaluator(new ArgbEvaluator());
valueAnimator.setIntValues(Color.WHITE,Color.YELLOW);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
answerButtons[j].setBackgroundColor((int)valueAnimator.getAnimatedValue());
}
});
valueAnimator.start();
((MainActivity)getActivity()).num++;
}
}
it does change the color but right after that the next answers(and question) support to appear on the same buttons.
I tried this:
for (int i = 0; i < 4; i++) {
if(v == answerButtons[i]){
int j = i;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
answerButtons[j].setBackgroundColor(Color.rgb(63, 81, 181));
Toast.makeText(getActivity(), "Just changed color to: button "+(j+1), Toast.LENGTH_SHORT).show();
//display(questions.get(((MainActivity)getActivity()).num));
}
},250);
}
}
x
}
but it mostly doesn't work sometimes it does. any idea why it doesn't work everytime? (the only thing it doesn't do is to change the color)
I got a solution for this one :)
apparently the postDelay function is not that precise..
int j = i;
ValueAnimator valueAnimator = new ValueAnimator();
valueAnimator.setDuration(250);
valueAnimator.setEvaluator(new ArgbEvaluator());
valueAnimator.setIntValues(Color.WHITE,Color.YELLOW);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
answerButtons[j].setBackgroundColor((int)valueAnimator.getAnimatedValue());
}
});
valueAnimator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
answerButtons[j].setBackgroundColor(Color.parseColor("#3F51B5"));
display(questions.get(((MainActivity)getActivity()).num));
}
});
valueAnimator.start();
So this is my spin the bottle animation:
public static final Random RANDOM = new Random();
private int lastAngle = -1;
private ImageView bottle;
private void spinTheBottle() {
int angle = RANDOM.nextInt(3600 - 360) + 360;
float pivotX = bottle.getWidth() / 2;
float pivotY = bottle.getHeight() / 2;
final Animation animRotate = new RotateAnimation(lastAngle == -1 ? 0 : lastAngle, angle, pivotX, pivotY);
lastAngle = angle;
animRotate.setDuration(1500);
animRotate.setFillAfter(true);
bottle.startAnimation(animRotate);
}
How can I detect when the animation is done? I tried adding Animator.AnimatorListener, but that does not execute at all:
Animator.AnimatorListener listener = new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
Toast.makeText(FlasketutenActivity.this, "onAnimationStart", Toast.LENGTH_SHORT).show();
}
#Override
public void onAnimationEnd(Animator animation) {
Toast.makeText(FlasketutenActivity.this, "onAnimationEnd", Toast.LENGTH_SHORT).show();
}
#Override
public void onAnimationCancel(Animator animation) {
Toast.makeText(FlasketutenActivity.this, "onAnimationCancel", Toast.LENGTH_SHORT).show();
}
#Override
public void onAnimationRepeat(Animator animation) {
Toast.makeText(FlasketutenActivity.this, "onAnimationRepeat", Toast.LENGTH_SHORT).show();
}
};
Any tips?
It looks like you're creating the listener, but not assigning it to your animation. Try calling setAnimationListener on your animation object like this:
animRotate.setAnimationListener(new Animation.AnimationListener() {
//Listener methods
});
The first.Keep the ImageView witch and height above of zero at time
rotateAnimation.setDuration(1500);
rotateAnimation.setFillAfter(true);
rotateAnimation.setFillEnabled(true);
rotateAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
Log.d(TAG, "onAnimationStart: ");
}
#Override
public void onAnimationEnd(Animation animation) {
Log.d(TAG, "onAnimationEnd: ");
}
#Override
public void onAnimationRepeat(Animation animation) {
Log.d(TAG, "onAnimationRepeat: ");
}
});
view.startAnimation(rotateAnimation);
it is working in my project.
But I use the animation always in xmls,it is Easy to operate and relatively by code.
Animation and Animator is not a same things.
That's all.
Assign your listener that you have created to the animation
animRotate.setAnimationListener(listener);
I have implemented an Android listview with flip checkboxes (GMail style) as shown here: http://techiedreams.com/gmail-like-flip-animated-multi-selection-list-view-with-action-mode/
The problem I have (even in the source code example): If there are multiple items I click/check in a fast sequence, the previous animation stops and will be restared. In other words, the previous animation does not finish and is interrupted by the second one.
Simple download the source code and try it on your own. In comparisson to gmail all animations, no matter how fast I'm clicking, are performed from the start to the end.
I can't find the piece of code in the demo source code to change this behaviour.
Any hints?
Thanks in advance :)
This is the closest I could get to Gmail's flip animation:
In the getView() method (I'm using contextual action mode):
holder.check.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mActionMode == null) {
checked = new SparseBooleanArray(alllists.size());
mActionMode = ((Activity) getActivity()).startActionMode(mActionModeCallback);
animateRow(position);
checked.put(position, true);
mActionMode.setTitle("1");
mActionMode.getMenu().getItem(0).setVisible(true);
} else {
animateRow(position);
if (checked.get(position)) {
checked.put(position, false);
if (checked.indexOfValue(true) < 0) {
mActionMode.finish();
} else {
mActionMode.setTitle(String.valueOf(getCheckedCount()));
}
} else {
checked.put(position, true);
mActionMode.setTitle(String.valueOf(getCheckedCount()));
}
}
}
}
);
Then the animateRow() method:
private void animateRow(final int position) {
if (position >= listView.getFirstVisiblePosition() && position <= listView.getLastVisiblePosition()) {
Log.i("animateRow", String.valueOf(position));
ScaleAnimation anim = new ScaleAnimation(1, 0, 1, 1, Animation.RELATIVE_TO_SELF, 0.5f, 0, 0);
anim.setDuration(150);
anim.setRepeatCount(1);
anim.setRepeatMode(Animation.REVERSE);
viewa = listView.getChildAt(position - listView.getFirstVisiblePosition());
final Button chkButton = (Button) viewa.findViewById(R.id.logo);
if (checked.get(position)) {
anim.setAnimationListener(
new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
Log.i("anim" + position, "Start");
}
#Override
public void onAnimationRepeat(Animation animation) {
Log.i("anim" + position, "Repeat" + animation.getRepeatCount());
viewa.setBackgroundResource(R.color.row_background);
chkButton.setBackgroundResource(R.color.button_background);
chkButton.setText(String.valueOf(alllists.get(position).itemsCount));
}
#Override
public void onAnimationEnd(Animation animation) {
Log.i("anim" + position, "END");
}
}
);
chkButton.startAnimation(anim);
} else {
anim.setAnimationListener(
new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
Log.i("anim" + position, "Start");
}
#Override
public void onAnimationRepeat(Animation animation) {
viewa.setBackgroundResource(R.color.checked_row_background);
chkButton.setBackgroundResource(R.color.checked_button_background);
chkButton.setText("✓");
}
#Override
public void onAnimationEnd(Animation animation) {
Log.i("anim" + position, "END");
}
}
);
chkButton.startAnimation(anim);
}
}
}
I hope it helps.. :)
Now you can forget that method to flip a view, since I've developed a new library FlipView fully customizable, this is exactly what you want. You will be able to swap any kind of views and layouts with any kind of animation you desire.
Please have a look.
In my SMS app, I have a dialog that opens when the user clicks on an attached image to expand it.
Everything worked fine until I decided to add animations. This dialog has 3 buttons (one close ImageButton in the top right corner and two buttons in a bottom bar of the dialog). When the user clicks on the image, the buttons anime out/in. This all works fine except the buttons are still clickable even after they're hidden.
Before Animations:
After Animations:
My code for the dialog below:
// Declare these here to increase scope. (Listeners)
private static boolean ContainerChanged;
private static boolean ActionsHidden;
private static boolean AnimStarted;
private static boolean closeAnimFinished;
private static boolean barAnimFinished;
private void showExpandedImageDialog(Uri imgUri)
{
// Initialize Dialog
final Dialog dialog = new Dialog(ActivitySend.this, R.style.FullHeightDialog);
dialog.setContentView(R.layout.dialog_attachment_image_send);
// Initialize Views
final RelativeLayout Container = (RelativeLayout) dialog.findViewById(R.id.Container);
final LinearLayout actions = (LinearLayout) dialog.findViewById(R.id.Actions);
final ImageButton btnClose = (ImageButton) dialog.findViewById(R.id.btnClose);
Button btnReplace = (Button) dialog.findViewById(R.id.btnReplace);
Button btnRemove = (Button) dialog.findViewById(R.id.btnRemove);
ImageView image = (ImageView) dialog.findViewById(R.id.Image);
// Load Image & Make Zoomable
PhotoViewAttacher mAttacher = new PhotoViewAttacher(image);
image.setImageURI(imgUri);
mAttacher.update();
// Get animations ready
final Animation fiCloseAnim = AnimationUtils.loadAnimation(ActivitySend.this, R.anim.fade_in);
fiCloseAnim.setFillEnabled(true);
fiCloseAnim.setFillAfter(true);
final Animation foCloseAnim = AnimationUtils.loadAnimation(ActivitySend.this, R.anim.fade_out);
foCloseAnim.setFillEnabled(true);
foCloseAnim.setFillAfter(true);
final Animation dBarAnim = AnimationUtils.loadAnimation(ActivitySend.this, R.anim.slide_down);
dBarAnim.setFillEnabled(true);
dBarAnim.setFillAfter(true);
final Animation uBarAnim = AnimationUtils.loadAnimation(ActivitySend.this, R.anim.slide_up);
uBarAnim.setFillEnabled(true);
uBarAnim.setFillAfter(true);
// Reset static variables
ActionsHidden = false;
AnimStarted = false;
closeAnimFinished = false;
barAnimFinished = false;
// Initialize listeners
AnimationListener closeAnimListener = new AnimationListener()
{
#Override
public void onAnimationEnd(Animation animation)
{
closeAnimFinished = true;
if (closeAnimFinished && barAnimFinished)
{
AnimStarted = false;
closeAnimFinished = false;
barAnimFinished = false;
if (ActionsHidden)
{
actions.setVisibility(View.VISIBLE);
btnClose.setVisibility(View.VISIBLE);
}
else
{
actions.setVisibility(View.GONE);
btnClose.setVisibility(View.GONE);
}
ActionsHidden = !ActionsHidden;
}
}
#Override
public void onAnimationRepeat(Animation animation)
{
// Nothing
}
#Override
public void onAnimationStart(Animation animation)
{
AnimStarted = true;
}
};
AnimationListener barAnimListener = new AnimationListener()
{
#Override
public void onAnimationEnd(Animation animation)
{
barAnimFinished = true;
if (closeAnimFinished && barAnimFinished)
{
AnimStarted = false;
closeAnimFinished = false;
barAnimFinished = false;
if (ActionsHidden)
{
actions.setVisibility(View.VISIBLE);
btnClose.setVisibility(View.VISIBLE);
}
else
{
actions.setVisibility(View.GONE);
btnClose.setVisibility(View.GONE);
}
ActionsHidden = !ActionsHidden;
}
}
#Override
public void onAnimationRepeat(Animation animation)
{
// Nothing
}
#Override
public void onAnimationStart(Animation animation)
{
AnimStarted = true;
}
};
// Set listeners
fiCloseAnim.setAnimationListener(closeAnimListener);
foCloseAnim.setAnimationListener(closeAnimListener);
dBarAnim.setAnimationListener(barAnimListener);
uBarAnim.setAnimationListener(barAnimListener);
// Actions Appear/Disappear onTap (Animate)
mAttacher.setOnPhotoTapListener(new OnPhotoTapListener()
{
#Override
public void onPhotoTap(View view, float x, float y)
{
if (!AnimStarted && ActionsHidden)
{
actions.startAnimation(uBarAnim);
btnClose.startAnimation(fiCloseAnim);
}
else if (!AnimStarted)
{
actions.startAnimation(dBarAnim);
btnClose.startAnimation(foCloseAnim);
}
}
});
// Make dialog square
ContainerChanged = false;
ViewTreeObserver vto = Container.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
{
public boolean onPreDraw()
{
// Set boolean to save processing power
if (!ContainerChanged)
{
int width = Container.getMeasuredWidth();
Container.getLayoutParams().height = width;
ContainerChanged = true;
}
return true;
}
});
// Set button listeners
btnClose.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
dialog.dismiss();
}
});
btnReplace.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
}
});
btnRemove.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
}
});
// Show dialog
dialog.show();
}
Everything works perfectly if I remove the animations and only use view.setVisibility(View.GONE) but I really like the animations...
Any ideas on what I could do to fix this?
I could probably use view.setClickable(false); but I'm sure there's a better solution than that.
You can do it like this:
Let your activity implement AnimationListener. Then there will be an overridden method public void onAnimationEnd(Animation arg0), write setClickable(false) or setEnabled(false) in this method for all three of your buttons, enable them again when you are starting your animation....hope you got me..
Hi have a problem with Animation, actually i want to fade my ImageView while it's changing it resource.
It's not working, i can change the resource but without any animation.
private void checkX() {
// TODO Auto-generated method stub
switch (x) {
case (1): {
startingAnimation();
xImg.setImageResource(R.drawable.test_uno);
endingAnimation();
break;
}
case (2): {
startingAnimation();
xImg.setImageResource(R.drawable.test_due);
endingAnimation();
break;
}
case (3): {
startingAnimation();
xImg.setImageResource(R.drawable.test_tre);
endingAnimation();
break;
}
case (4): {
startingAnimation();
xImg.setImageResource(R.drawable.test_quattro);
endingAnimation();
break;
}
case (5): {
x = 1;
checkX();
break;
}
case (0): {
x = 4;
checkX();
break;
}
}
}
private void endingAnimation() {
// TODO Auto-generated method stub
ObjectAnimator animation2 = ObjectAnimator.ofFloat(xImg, "alpha", 255);
animation2.setDuration(1000);
animation2.start();
}
private void startingAnimation() {
// TODO Auto-generated method stub
ObjectAnimator animation = ObjectAnimator.ofFloat(xImg, "alpha", 0);
animation.setDuration(1000);
animation.start();
}
checkX is called each time i press a button(that add or subtract 1 to X).
How i can make both animations and ImageView resource change?
Try changing the image source when the animation's onAnimationEnd is called. For example:
animation.addListener(new AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) { }
#Override
public void onAnimationRepeat(Animator animation) { }
#Override
public void onAnimationEnd(Animator animation) {
// change your ImageView's source here
}
#Override
public void onAnimationCancel(Animator animation) { }
});
Apply fade out animation on your ImageView and set animationListener to it. on animation end change your views resource and set fade in animation on it
For fade in animation
Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator());
fadeIn.setDuration(1000);
final AnimationSet animation = new AnimationSet(false);
animation.addAnimation(fadeIn);
For fade out animation
Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator());
fadeOut.setDuration(300);
final AnimationSet animation = new AnimationSet(false);
animation.addAnimation(fadeOut);
Thats how you implement listner on animation
fadeout.setAnimationListener(new Animation.AnimationListener(){
#Override
public void onAnimationStart(Animation arg0) {
}
#Override
public void onAnimationRepeat(Animation arg0) {
}
#Override
public void onAnimationEnd(Animation arg0) {
//change resource of Imageview here
}
});