I'm new to android and I don't know a lot about android animation .
I've a viewflipper and I want to animate between images inside it .
This is the code :
runnable = new Runnable() {
public void run() {
handler.postDelayed(runnable, 3000);
imageViewFlipper.setInAnimation(fadeIn);
imageViewFlipper.setOutAnimation(fadeOut);
imageViewFlipper.showNext();
}
};
handler = new Handler();
handler.postDelayed(runnable, 500);
}
The 2 animated file are not good , they animate very badly .
I just need a code to fade out the front image and fade in the next image and do the same for all images inside it.
Could anyone help me out ?
thank you
Simple using Kotlin.
First, set the animations:
private fun setAnimations() {
// in anim
val inAnim = AlphaAnimation(0f, 1f)
inAnim.duration = 600
flipperView.inAnimation = inAnim
// out anim
val outAnim = AlphaAnimation(1f, 0f)
outAnim.duration = 600
flipperView.outAnimation = outAnim
}
And to flip (between two views) just call this function:
fun onSendClick(view: View) {
viewFlipper.displayedChild = if(flipperView.displayedChild == 0) 1 else 0
}
Related
I have an activity with 3 views (buttonViews) in a vertical linear layout. I am generating (inflating) these views dynamically. I want to apply an animation such that, on activity start, the first buttons slide in -> 100 ms delay -> second button slide in -> 100 ms delay -> Third button slide in.
Attempt
I tried implementing it in this way:
private void setMainButtons() {
ArrayList<String> dashboardTitles = DashboardUtils.getDashboardTitles();
ArrayList<Integer> dashboardIcons = DashboardUtils.getDashboardIcons();
final ViewGroup root = findViewById(R.id.button_container);
for (int i = 0; i < (dashboardTitles.size() < dashboardIcons.size() ? dashboardTitles.size() : dashboardIcons.size()); i++){
final View buttonView = DashboardButtonInflater.getDashboardButton(root, dashboardTitles.get(i), dashboardIcons.get(i), this);
if (buttonView == null) continue;
buttonView.setOnClickListener(this);
root.addView(buttonView);
animateBottomToTop(buttonView, (long) (i*50)); // Calling method to animate buttonView
}
}
//The function that adds animation to buttonView, with a delay.
private void animateBottomToTop(final View buttonView,long delay) {
AnimationSet animationSet = new AnimationSet(false);
animationSet.addAnimation(bottomToTop);
animationSet.addAnimation(fadeIn);
animationSet.setStartOffset(delay);
buttonView.setAnimation(animationSet);
}
Result:
The above method waits for the total delay of all the views and at the end, aminates all the views together. I can guess the culprit here is the thread. The dealy is actually stopping the UI thread from doing any animation. I could be wrong though.
I also tried running the animation code inside
new Thread(new Runnable(){...}).run()
but that didn't work either.
Expectations:
Can somebody help me achieve the one-by-one animation on buttonView? Thank you.
Animations are statefull objects, you should not use the same instance multiple times simultaneously. In your case the bottomToTop and fadeIn animations are shared between the animation sets. When the set starts (initialize() is called) it will set the start offset of its children.
For example the method could look like :
//The function that adds animation to buttonView, with a delay.
private void animateBottomToTop(final View buttonView,long delay) {
AnimationSet animationSet = new AnimationSet(false);
// create new instances of the animations each time
animationSet.addAnimation(createBottomToTop());
animationSet.addAnimation(createFadeIn());
animationSet.setStartOffset(delay);
buttonView.setAnimation(animationSet);
}
The problem might be easily solved with Transitions API. Having declared a root layout with this xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
Then inside activity:
class MainActivity : AppCompatActivity() {
lateinit var content: LinearLayout
private var counter = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
content = findViewById(R.id.content_frame)
// wait this view to be laid out and only then start adding and animating views
content.post { addNextChild() }
}
private fun addNextChild() {
// terminal condition
if (counter >= 3) return
++counter
val button = createButton()
val slide = Slide()
slide.duration = 500
slide.startDelay = 100
slide.addListener(object : TransitionListenerAdapter() {
override fun onTransitionEnd(transition: Transition) {
addNextChild()
}
})
TransitionManager.beginDelayedTransition(content, slide)
content.addView(button)
}
private fun createButton(): Button {
val button = Button(this)
button.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
button.text = "button"
return button
}
}
This chunk of code will result in following output:
You can adjust animation and delay times respectively.
If you want following behavior:
Then you can use following code:
class MainActivity : AppCompatActivity() {
lateinit var content: LinearLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
content = findViewById(R.id.content_frame)
content.post { addChildren() }
}
private fun addChildren() {
val button1 = createButton()
val button2 = createButton()
val button3 = createButton()
val slide1 = Slide()
slide1.duration = 500
slide1.addTarget(button1)
val slide2 = Slide()
slide2.duration = 500
slide2.startDelay = 150
slide2.addTarget(button2)
val slide3 = Slide()
slide3.duration = 500
slide3.startDelay = 300
slide3.addTarget(button3)
val set = TransitionSet()
set.addTransition(slide1)
set.addTransition(slide2)
set.addTransition(slide3)
TransitionManager.beginDelayedTransition(content, set)
content.addView(button1)
content.addView(button2)
content.addView(button3)
}
private fun createButton(): Button {
val button = Button(this)
button.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
button.text = "button"
return button
}
}
Create method, which will accept Any number of Animation to invoke one after another. Just as example.
private void playOneAfterAnother(#NonNull Queue<Animation> anims) {
final Animation next = anims.poll();
/* You can set any other paramters,
like delay, for each next Playing view, if any of course */
next.addListener(new AnimationListener() {
#Override
public void onAnimationEnd(Animator a) {
if (!anim.isEmpty()) {
playOneAfterAnother(anims);
}
}
#Override
public void onAnimationStart(Animator a) {
}
#Override
public void onAnimationCancel(Animator a) {
}
#Override
public void onAnimationRepeat(Animator a) {
}
});
next.play();
}
Or with delay for animations, it's easy too.
private void playOneAfterAnother(#NonNull Queue<Animation> anims,
long offsetBetween, int nextIndex) {
final Animation next = anims.poll();
/* You can set any other paramters,
like delay, for each next Playing view, if any of course */
next.setStartOffset(offsetBetween * nextIndex);
next.play();
if (!anim.isEmpty()) {
playOneAfterAnother(anims,
offsetBetween, nextIndex +1);
}
}
Probably, what you need to use is AnimatorSet instead of AnimationSet. The AnimatorSet API allows you to choreograph animations in two ways:
1. PlaySequentially
2. PlayTogether
using the apis:
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playSequentially(anim1, anim2, anim3, ...);
animatorSet.playTogether(anim1, anim2, anim3, ...);
You can further add delays to your animation using
animatorSet.setStartDelay();
Visit the complete API docs here https://developer.android.com/reference/android/animation/AnimatorSet
Hope this helps!
I Use This Code And its work correctly
Hope to help you
// first put your views in an array with name arrayViews
final int[] time = {0};
for (int i = 0; i < arrayViews.size(); i++) {
Animation zoom = AnimationUtils.loadAnimation(this, R.anim.fade_in);
zoom.setDuration(250);
zoom.setStartOffset(time[0] += 250);
arrayViews.get(i).startAnimation(zoom);
arrayViews.get(i).setVisibility(View.VISIBLE);
}
I have an imageview with 5 backgrounds to choose from. I want to fade image2 out and set image5 as background with fade in effect. This should keep changing randomly. The problem is, how do i do this efficiently?
this is how i give fade in and fade out effects using system animations-
fade out
Animation out = AnimationUtils.makeOutAnimation(this, true);
viewToAnimate.startAnimation(out);
viewToAnimate.setVisibility(View.INVISIBLE);
fade in
Animation in = AnimationUtils.loadAnimation(this, android.R.anim.fade_in);
viewToAnimate.startAnimation(in);
viewToAnimate.setVisibility(View.VISIBLE);
this is how i change my background-
search_engine_identifier.setImageResource(R.drawable.ic_yahoo);
Create two in xml you can get from here then load them like this.
ImageView myImageView = (ImageView) findViewById(R.id.imageView2);
Animation myFadeInAnimation = AnimationUtils.loadAnimation(Splash.this, R.anim.fadein)
Animation myFadeOutAnimation = AnimationUtils.loadAnimation(Splash.this, R.anim.fadeout);
int value = 0; // Global Type
btnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(value%2 == 0){
doFadeOutAnimation();
}else{
doFadeInAnimation();
}
value ++;
}
});
Another way to do this is by using one of Android's View Animator classes, such as ObjectAnimator. Here's what I'm doing:
1) Add the drawable ID's of the images you want to use into an int array.
2) Create ObjectAnimators for the fadeIn and fadeOut animations. You can set the duration of the fade in and fade out to whatever you want.
3) Add an AnimatorListener to the fadeOut ObjectAnimator so that when it finishes, it will set the new image (which is chosen randomly by selecting a random number from the images array) and then it will fade back in with the new image, using the fadeIn ObjectAnimator.
4) Create a runnable and in it's run method, start the fadeOut animation.
5) Call handler.postDelayed on the runnable and use that to decide how long you want each image to stay before fading out.
6) At the end of your Runnable's run method, call handler.postDelayed again so the images will continue to fade in and out, but you should make sure that you have some kind of conditional statement so that you can stop the animation when you need to, which is why I used the boolean "running" so I can set it to false when I need to stop the handler from looping.
ImageView mImageView = (ImageView) findViewById(R.id.imageView);
boolean running = true;
final int[] images = {R.drawable.image1, R.drawable.image2, R.drawable.image3,
R.drawable.image4, R.drawable.image5};
final Random random = new Random();
final Handler handler = new Handler();
final ObjectAnimator fadeIn = ObjectAnimator.ofFloat(mImageView, "alpha", 0f, 1f);
fadeIn.setDuration(1000);
final ObjectAnimator fadeOut = ObjectAnimator.ofFloat(mImageView, "alpha", 1f, 0f);
fadeOut.setDuration(1000);
fadeOut.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
int rand = random.nextInt(images.length);
mImageView.setImageResource(images[rand]);
fadeIn.start();
}
#Override
public void onAnimationCancel(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
});
Runnable runnable = new Runnable() {
#Override
public void run() {
fadeOut.start();
if (running) {
handler.postDelayed(this, 5000);
}
}
};
handler.postDelayed(runnable, 5000);
}
This will continuously loop through your selected images (randomly) with fade in/ fade out animations. You can add a few checks to make sure the same image doesn't appear twice in a row, etc.
Hi I try to animate list of Views in layout to be scale_up but each of them must have wait for 100 millisecond after last view start it's animation.
I try to set delay for them:
for (View view: views) {
AnimatorSet animator = (AnimatorSet)AnimatorInflater.loadAnimator(context, R.animator.edit_text_open);
animator.setStartDelay(counter++ * 100);
Log.e("counter number:", "" + counter);
animator.setTarget(view);
animator.start();
}
but it's not work all View animate together.
and one more thing is there any good recurse about material design animations I try to make animation like shows in every where with material design I just don't know how they do it.
Initializing AnimatorSet
AnimatorSet animator = (AnimatorSet)AnimatorInflater.loadAnimator(context, R.animator.edit_text_open);
Using Timer will get the task done
Timer t = new Timer();
int count = 0;
t.scheduleAtFixedRate(new TimerTask() {
// Do stuff
animator.setTarget(views.get(count));
animator.start();
count++;
if (count >= views.size()) //assuming views as List<View>
t.cancel();
}, 0, 100);
Hope, that helps. Happy Coding!!!
As #Stack Overflowerrr say in last answer there is the code:
t.scheduleAtFixedRate(new TimerTask() {
// Do stuff
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
AnimatorSet animator = (AnimatorSet)AnimatorInflater.loadAnimator(MainActivity.this, R.animator.edit_text_open);
animator.setTarget(views.get(count));
animator.start();
Log.e("counter", "" + count);
}
});
count++;
if (count + 1 >= views.size()) //assuming views as List<View>
t.cancel();
}
}, 0, 500);
and I declare these two as global:
int count = 0;
Timer t = new Timer();
again many thans Stack Overflowerrr.
I want to change position of layout and after 75ms return it to first position to make a movement and that is my code:
for(int i = 0; i < l1.getChildCount(); i++) {
linear = (LinearLayout) findViewById(l1.getChildAt(i).getId());
LayoutParams params = new LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);
params.bottomMargin = 10;
linear.setLayoutParams(params);
SystemClock.sleep(75);
}
The problem is the app is stop for 750ms and don't do anything. I tried invalidate() , refreshDrawableState(), requestLayout(), postInvalidate(), and try to call onResume(), onRestart(), onPause() .
Maybe you need:
linear.invalidate();
linear.requestLayout();
after making the layout changes.
EDIT:
Run the code on a different thread:
new Thread() {
#Override
public void run() {
<your code here>
}
}.start();
And whenever you need to update the UI from that thread use:
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
<code to change UI>
}
});
After several hours of testing, I found the solution about updating a view if you made operation with these views like adding children, visibility, rotation, etc.
We need to force update the view with the below methods.
linearSliderDots.post {
// here linearSliderDots is a linear layout &
// I made add & remove view option on runtime
linearSliderDots.invalidate()
linearSliderDots.requestLayout()
}
You should try using an ValueAnimator (Or object animator), the below code is in kotlin but same logic would be applied for java:
val childCount = someView.childCount
val animators = mutableListOf<ValueAnimator>()
for (i in 0..childCount) {
val child = (someView.getChildAt(i))
val animator = ValueAnimator.ofInt(0, 75)
animator.addUpdateListener {
val curValue = it.animatedValue as Int
(child.layoutParams as ViewGroup.MarginLayoutParams).bottomMargin = curValue
child.requestLayout()
}
animator.duration = 75
animator.startDelay = 75L * i
animators.add(animator)
}
animators.forEach { animator ->
animator.start()
}
Basically you create a bunch of animators that have start delay proportionate to the number of children, so as soon as one animation ends, the new one starts
ActivityName.this.runOnUiThread(new Runnable() {
#Override
public void run() {
<code to change UI>
}
});
I would like to animate some images.
Could someone tell me why this first piece of code does not work, but the second one does work ?
And if I have to use the second one, how do I STOP the animation into the runnable ?
EDIT : the first code works on android 4.x, but not on 2.2 (both simulator and device)
code 1 (into "onCreate()" ):
ImageView boule = (ImageView)findViewById(R.id.boule);
boule.setImageBitmap(null);
boule.setBackgroundResource(R.anim.anime);
AnimationDrawable animation = (AnimationDrawable)boule.getBackground();
animation.start();
// does not animate anything...
code 2 (also into "onCreate()" ) :
ImageView boule = (ImageView)findViewById(R.id.boule);
boule.setImageBitmap(null);
boule.setBackgroundResource( R.anim.anime );
final AnimationDrawable animation = (AnimationDrawable) boule.getBackground();
boule.post(new Runnable() {
public void run() {
if ( animation != null ) animation.start();
}
});
// OK, it works, but how do I stop this ?
You can try this.. this code works properly
BitmapDrawable frame1 = (BitmapDrawable)getResources().getDrawable(R.drawable.jth);
BitmapDrawable frame2 = (BitmapDrawable)getResources().getDrawable(R.drawable.jthj);
int duration = 10;
final AnimationDrawable ad = new AnimationDrawable();
ad.setOneShot(false);
ad.addFrame(frame1, duration);
ad.addFrame(frame2, duration);
iv.setBackgroundDrawable(ad);
ad.setVisible(true, true);
Put ad.start(); in button onClickListener and ad.stop(); for stop animantion