AnimationDrawable not showing on 4.03 device - android

I have a framelayout in the layout for a row in a ListView. When an item appears in the listview an AnimationDrawable is triggered.
This works fine on the Nexus 4 and Nexus 5. I had to change from using view.setBackground to view.setBackgroundDrawable to support slightly older devices. Making this change hasn't broken it on either of the Nexus devices. It also worked on an old gingerbread device.
On the HTC One V, running 4.03. the AnimationDrawable never appears. If, however, I hardcode the row xml file to show a standard drawable, rather than the animationdrawable, it appears fine.
Here is the xml file the animationdrawable
<item
android:drawable="#drawable/alert_red"
android:duration="700"/>
<item
android:drawable="#drawable/alert_red_glow"
android:duration="700"/>
</animation-list>
Here is the code which starts the animation
#SuppressWarnings("deprecation")
public void startGlowingRow() {
notificationStatus
.setBackgroundDrawable(getResources().getDrawable(
R.drawable.glowing_emergency_notification));
glowRequest = new GlowRequest();
notificationStatus.post(glowRequest);
}
public void stopGlowingRow() {
try {
// Remove any callbacks to make background glowing
if (glowRequest != null)
notificationStatus.removeCallbacks(glowRequest);
glowDrawable = (AnimationDrawable) notificationStatus
.getBackground();
glowDrawable.stop();
} catch (ClassCastException cce) {
// Not the correct background in view so don't try to stop
}
}
// Runnable which sets glowing effect after view has loaded
private class GlowRequest implements Runnable {
public void run() {
glowDrawable = (AnimationDrawable) notificationStatus
.getBackground();
glowDrawable.start();
}
}

I finally figured this out. It was because the view that contained the animation was using padding to show it's background. When I changed this so that it's first child used a margin instead it worked just fine

Related

Disabling all animations in an android app

I want to disable all the animations that happen when launching a new activity in my android app (for all the activities). Is there a way to achieve this once and for all? Or should I go to each and every activity and use Intent.FLAG_ACTIVITY_NO_ANIMATION or overridePendingTransition or both?
You can use style if you want:
<style name="noAnimTheme" parent="android:Theme">
<item name="android:windowAnimationStyle">#null</item>
</style>
And set them for your activity:
<activity android:name=".ui.ArticlesActivity" android:theme="#style/noAnimTheme">
</activity>
Let me know if thats what you meant...
Credit to #Santosh https://stackoverflow.com/a/9312957/3180983
When I built my app, I used only one activity. On the activity there was 4 Custom views. Each custom view represent another "Activity" its not really activity... Im playing with few custom view so each one is another window...
Here is the code with animation (*** IF you don't want animation SKIP THIS CODE to the next goToRegistrationPage() down below.):
//This code change the view so that the register form will appear. instead of changing activity with animation.
public void goToRegistrationPage()
{
Animation animationRightX1 = AnimationUtils.loadAnimation(this, R.anim.translate_right_x1);
//animationRightX1.
Animation animationRightX2 = AnimationUtils.loadAnimation(this, R.anim.translate_right_x2);
Animation animationRightX3 = AnimationUtils.loadAnimation(this, R.anim.translate_right_x3);
final int width = this.getWindowManager().getDefaultDisplay().getWidth();
layout.MainView.setVisibility(View.GONE);
layout.MainLogin.startAnimation(animationRightX1);
layout.MainRegister.startAnimation(animationRightX1);
animationRightX1.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
layout.layoutScroll.scrollTo((width*2), 0);
layout.MainView.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
And here is the code without the animation (This is what you need):
//This code change the view so that the register form will appear. instead of changing activity
//Go to the registration form from the main view.
public void goToRegistrationPageFromMainView()
{
final int width = this.getWindowManager().getDefaultDisplay().getWidth();
layout.layoutScroll.scrollTo((width*2), 0); // its width*2 because there is the "some other view" so it need to go 2 times width to the right side...
}
So basically what you do here is scrolling windows with width amount of pixels.
layoutscroll is the pink color in the picture.
layout is a class which I created to store all the layouts... its a personal preference you could do this.layoutscroll....
Mainview, other view, and registration form are custom views that extending linearlayout... you can attach to each one of them XML file with linear layout inflater...
Ofcorse that you make the scroll view unscrollable....

Background TransitionDrawable not redrawing on some devices

I'm using a TransitionDrawable two go between two GradientDrawables, and I'm setting that as the background drawable of a Button. This works fine transitioning between two ColorDrawables, but when I try doing it with GradientDrawables I get some very strange results.
On my 2.3.5 device everything works peachy.
On my 4.2.2 device, the buttons just takes on the first gradient and don't redraw at all.
If I add a call to view.refreshDrawableState() or view.setBackgroundDrawable(drawable) after I've started the transition, it will refresh but things get even weirder:
some buttons work correctly
some buttons flicker at points during the transition
one button, for whatever reason, transitions to black instead of to the second gradient drawable
I am looping the transition with a recursive post to the view, but I don't think that's problem because I get the same problems when I don't do it.
Does anyone know what I can do to fix this? Here's the relevant code:
private static void highlightView(View view, Context context) {
TransitionDrawable drawable;
GradientDrawable d1 = new GradientDrawable(Orientation.TOP_BOTTOM, new int[] { HIGHLIGHT_COLOR_1, HIGHLIGHT_COLOR_G1 });
d1.setCornerRadius(3f);
GradientDrawable d2 = new GradientDrawable(Orientation.TOP_BOTTOM,
new int[] { HIGHLIGHT_COLOR_2, HIGHLIGHT_COLOR_G2 });
d2.setCornerRadius(3f);
drawable = new TransitionDrawable(new Drawable[] {
d1,
d2
});
view.setBackgroundDrawable(drawable);
drawable.setCrossFadeEnabled(true);
animateBackground(drawable, true, view);
}
private static void animateBackground(final TransitionDrawable drawable,
final boolean forward, final View view) {
if (view.getBackground() != drawable) return;
if (forward) {
drawable.startTransition(HIGHLIGHT_CYCLE / 2);
} else {
drawable.reverseTransition(HIGHLIGHT_CYCLE / 2);
}
view.postDelayed(new Runnable() {
#Override
public void run() {
animateBackground(drawable, !forward, view);
}
}, HIGHLIGHT_CYCLE / 2);
view.refreshDrawableState(); //without this, no transition occurs at all
}

Create animation in imageviews

I have an imageview with a default image. Now when I try to click it, I want it to animate that displays 4 frames of images. How could I accomplish this, I tried a simpler approach (more of a dumb approach) by changing the imageresource 4 times, as expected the image changes so fast that the animating image effect is not visible. Any ideas?
I tried this approach:
Gem = (ImageView)v;
Gem.setImageResource(com.example.gems.R.drawable.bd1);
Gem.postDelayed(new Runnable() {
public void run() {
Gem.setImageResource(com.example.gems.R.drawable.bd2);
Gem.postDelayed(new Runnable() {
public void run() {
Gem.setImageResource(com.example.gems.R.drawable.bd3);
Gem.postDelayed(new Runnable() {
public void run() {
Gem.setImageResource(com.example.gems.R.drawable.bd4);
Gem.postDelayed(new Runnable() {
public void run() {
}
}, 500);
}
}, 500);
}
}, 500);
}
}, 500);
It worked, but is there a better way to this without coding too much lines? I have 25 kinds of images and each image has 4 frames.
EDIT:
I tried using xml transition files:
Java file:
Resources res = this.getResources();
Gem = (ImageView)v;
TransitionDrawable transition;
transition = (TransitionDrawable)
res.getDrawable(R.drawable.blue_diamond_animation);
Gem.setImageDrawable(transition);
transition.startTransition(3000);
xml file:
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/bd1"></item>
<item android:drawable="#drawable/bd2"></item>
<item android:drawable="#drawable/bd3"></item>
<item android:drawable="#drawable/bd4"></item>
<item android:drawable="#drawable/invi"></item>
</transition>
This seems to work, but I don't want to draw this images in a transition. I want to change the background in a transition. I tried changing this android:drawable to android:drawable but it doesn't work.
It turns out that there is an exact class for this: AnimationDrawable
Basically, just add frames with the other pictures to use in the animation to the AnimationDrawable object and specify how long they should display using addFrame(Drawable frame, int duration)
Then set the ImageView to display whatever image it should start with and set the background to the AnimationDrawable you just made using setBackgroundDrawable(Animation)
Lastly, start the animation in the onClick listener
EDIT: FOR EXAMPLE
AnimationDrawable ad = new AnimationDrawable();
ad.addFrame(getResources().getDrawable(R.drawable.image1), 100);
ad.addFrame(getResources().getDrawable(R.drawable.image2), 500);
ad.addFrame(getResources().getDrawable(R.drawable.image3), 300);
ImageView iv = (ImageView) findViewById(R.id.img);
iv.setBackgroundDrawable(animation);
And then in your onClick listener, just call ad.start
It depends on what you are trying to accomplish. You have not given enough info to go on
The viewproperty animator is really the easiest thing to use have a look. It can also be used with older API's using nineoldandroids jar (google it)
http://developer.android.com/reference/android/view/ViewPropertyAnimator.html
The ObjectAnimator and ValueAnimator are also available similar and slightly more difficult to implement
http://developer.android.com/reference/android/animation/ObjectAnimator.html
http://developer.android.com/reference/android/animation/ValueAnimator.html
Have a look at the APIdemos in the sample packs there are a few examples mainly using the ValueAnimator.
http://developer.android.com/tools/samples/index.html
There are also Sprites to consider but it is basically a bitmap , you can user the timer obect to choreograph

Animation flickering in ANDROID

I am trying to implement something relatively simple in ADNROID. I have a bunch of Drawables stored in a list. I want to create an effect where the drawables are displayed on top of each other, one by one, using a fade-in effect.
I have had partial success with the code below. It actually works flawlessly on my phone (Nexus S), but it shows flickering on my tablet (ASUS TF101). This is probably due to the fact that the tablet has a faster CPU.
Here is my setup: I have stored all the Drawables in the drawables list. I have also defined two images in my layout, one on top of the other: imageViewForeground and imageViewBackground.
The idea is to set the background image first, then start an animation where the foreground image starts from alpha-0 and goes to alpha-1. Then replace the background with the new foreground image, choose a new foreground (i.e. the next drawable) and loop forever.
The counter object is a simple wrapper for an int counter.
Here is my code:
final Animation fadeInAnimation = new AlphaAnimation(0f, 1f);
fadeInAnimation.setDuration(2000);
fadeInAnimation.setStartOffset(3000);
fadeInAnimation.setFillBefore(false);
fadeInAnimation.setFillAfter(true);
fadeInAnimation.setRepeatCount(Animation.INFINITE);
fadeInAnimation.setRepeatMode(Animation.RESTART);
fadeInAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
imageViewForeground.setImageDrawable(drawables.get(counter.value()));
Log.d(TAG, "onAnimationStart");
}
#Override
public void onAnimationEnd(Animation animation) {
Log.d(TAG, "onAnimationEnd");
}
#Override
public void onAnimationRepeat(Animation animation) {
imageViewBackground.setImageDrawable(drawables.get(counter.value()));
counter.increase();
// the problem appears in this line,
// where the foreground becomes visible for a very small period,
// causing the flickering
imageViewForeground.setImageDrawable(drawables.get(counter.value()));
}
});
imageViewForeground.startAnimation(fadeInAnimation);
Any ideas how I can overcome this flickering problem?

animation does not start in canvas on android

I'm working on a game that requires drawing to SurfaceView's
Canvas. I'm using SurfaceHolder to obtain Canvas to draw to, and
perform drawing in a separate thread. Everything I draw displays
correctly except for this one animation.
Here is the animation definition (it is in res/drawable/
my_animation.xml:
and here is how I draw it to the Canvas:
AnimationDrawable ad = (AnimationDrawable)getResources().getDrawable(R.drawable.my_animation);
ad.draw(canvas);
ad.start();
but only the first frame ever appears on the screen.
What am I missing?
Thank you
If I get the reference right, you have to assign your AnimationDrawable to an ImageView as the example from http://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html demonstrates:
// Load the ImageView that will host the animation and
// set its background to our AnimationDrawable XML resource.
ImageView img = (ImageView)findViewById(R.id.spinning_wheel_image);
img.setBackgroundResource(R.drawable.spin_animation);
// Get the background, which has been compiled to an AnimationDrawable object.
AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();
// Start the animation (looped playback by default).
frameAnimation.start()
In your case you did not assign your AnimationDrawable to any view so I suppose that's why it does not get updated. So you have to call AnimationDrawable.getFrame(int) manually.
If you are already using a separate thread why don't you involve also the code for your animation? This would render your code more consistent in my opinion.
Although this is an old question, i run into this problem too and figure out a walkaround, so i just post it here in case anyone searching about.
```java
final AnimationDrawable animationDrawable = ...;
final View v = new View(this) {
#Override
protected void onDraw(Canvas canvas) {
animDrawable.draw(canvas);
}
};
animationDrawable.setCallback(new Callback() {
#Override
public void unscheduleDrawable(Drawable who, Runnable what) {
v.removeCallbacks(what);
}
#Overridew
public void scheduleDrawable(Drawable who, Runnable what, long when) {
v.postDelayed(what, when - SystemClock.uptimeMillis());
}
#Override
public void invalidateDrawable(Drawable who) {
v.postInvalidate();
}
});
```
Animated drawables of all kinds (Transition, etc.) need a Callback to schedule redrawals. As zhang demonstrates, it is a simple interface for posting Runnables.
To support animated drawables in a custom view, you need two things:
pass your View to your animated Drawable's setCallback. Even base View implements Drawable.Callback, so there's no need to write your own wrapper.
override verifyDrawable to also return true for your animated Drawable.
As to why anyone would need that - I have just implemented animated drawable support in RecyclerView.ItemDecorations, how cool is that :-)
You are working with Canvas means, you are coding in low level. In low level u have to do everything. working with View (ImageView) means, it is high level.In ImageView already defined in low level on canvas how to deal with AnimationDrawable.
Lars Blumberg's answer is correct but the documentation is incorrect; you also need to take into account this: animation start issue

Categories

Resources