I used the following code to fade in only the Button Text. but it gives fadein for whole Button.
Animation animationFadeIn = AnimationUtils.loadAnimation(this, R.anim.fade_in);
//register btn listener
m_btn_register.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
m_btn_register.startAnimation(animationFadeIn);
}
});
fade_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/linear_interpolator">
<alpha
android:fromAlpha="0.1"
android:toAlpha="1.0"
android:duration="2000"
/>
</set>
what is the correct way to acheive this?
Note : Having custom spans for button does not work on lollipop and above. So have this
<Button
android:textAllCaps="false"
My CustomSpan
public class CustomSpan extends CharacterStyle implements UpdateAppearance {
private int alpha;
public int getAlpha() {
return alpha;
}
public void setAlpha(int alpha) {
this.alpha = alpha;
}
public CustomSpan() {
}
#Override
public void updateDrawState(TextPaint paint) {
paint.setAlpha(alpha);
}
}
Custom Property
private static final Property<CustomSpan, Integer> FADE_INT_PROPERTY
= new Property<CustomSpan, Integer>(Integer.class, "FADE_INT_PROPERTY") {
#Override
public void set(CustomSpan span, Integer value) {
span.setAlpha(value);
}
#Override
public Integer get(CustomSpan object) {
return object.getAlpha();
}
};
Then
String text = button.getText().toString();
final CustomSpan span = new CustomSpan();
final SpannableString spannableString = new SpannableString(text);
int start = 0;
int end = text.length();
spannableString.setSpan(span, start, end, 0);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ObjectAnimator objectAnimator = ObjectAnimator.ofInt(
span, FADE_INT_PROPERTY, 0, 255);
objectAnimator.setEvaluator(new IntEvaluator());
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
button.setText(spannableString);
}
});
objectAnimator.setDuration(10000);
objectAnimator.start();
}
});
Gif
Change your code to this way
<?xml version="1.0" encoding="UTF-8" ?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale android:duration="#android:integer/config_shortAnimTime"
android:pivotX="50.0%"
android:pivotY="50.0%"
android:fromXScale="1.0"
android:toXScale="0.9"
android:fromYScale="1.0"
android:toYScale="0.9"/>
<alpha android:duration="#android:integer/config_shortAnimTime"
android:fromAlpha="1.0"
android:toAlpha="0.7"/>
</set>
and one more thing declare Animation gloabal.
I don't think there is a solution using animation API because it works on the view and doesn't take care of the content of it.
So, I think you should create container view for the button and add your button background for the new container.
then set the button background to be transparent.
After that make the animation for the button only.
Related
I'm trying to make an effect on two images, as if it were a flip card annimation. Image 1 = "botaoiniciar" and Image 2 = "botaosair". At the moment when I click on the initial, it turns the second, but then it gets stuck on the second image and I would like it to come back. I am using the following code. I thank you for your attention.
final ImageView botaoiniciar = (ImageView) findViewById(R.id.botaoiniciar);
botaoiniciar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final ObjectAnimator oa1 = ObjectAnimator.ofFloat(botaoiniciar, "scaleX", 1f, 0f);
final ObjectAnimator oa2 = ObjectAnimator.ofFloat(botaoiniciar, "scaleX", 0f, 1f);
oa1.setInterpolator(new DecelerateInterpolator());
oa2.setInterpolator(new AccelerateDecelerateInterpolator());
oa1.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
botaoiniciar.setImageResource(R.drawable.botaosair);
oa2.start();
}
});
oa1.start();
}
});
You need to keep animators and change them when card flips. A Boolean can keeps the fliping state. Here is my example:
public class MyFragment extends Fragment {
#OnClick(R.id.frmMain) //onclick for container of two sides
public void onClick() {
flipCard(); //call method that flips card base on current "mIsBackVisible" state
}
#BindView(R.id.card_front)
FrameLayout mCardFront;
#BindView(R.id.card_back)
FrameLayout mCardBack;
AnimatorSet animFront;
AnimatorSet animBack;
private boolean mIsBackVisible = false; //keeping card flip state
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.myLauyout, container, false);
ButterKnife.bind(this, root);
//important part is this two lines + onclick for container
loadAnimations(); //initialize animations
changeCameraDistance(); //optimize card appearance (optional)
return root;
}
private void changeCameraDistance() {
int distance = 8000;
float scale = getResources().getDisplayMetrics().density * distance;
mCardFront.setCameraDistance(scale);
mCardBack.setCameraDistance(scale);
}
private void loadAnimations() {
animBack = (AnimatorSet) AnimatorInflater.loadAnimator(getContext(), R.animator.flip_back);
animFront = (AnimatorSet) AnimatorInflater.loadAnimator(getContext(), R.animator.flip_front);
}
public void flipCard() {
if (!mIsBackVisible) {
animBack.setTarget(mCardFront);
animFront.setTarget(mCardBack);
animBack.start();
animFront.start();
mIsBackVisible = true;
} else {
animBack.setTarget(mCardBack);
animFront.setTarget(mCardFront);
animBack.start();
animFront.start();
mIsBackVisible = false;
}
}
}
and here is my animator in res/animator/flip_front.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:valueFrom="-180"
android:valueTo="0"
android:propertyName="rotationY"
android:repeatMode="reverse"
android:duration="#integer/anim_length" />
<objectAnimator
android:valueFrom="0.0"
android:valueTo="1.0"
android:propertyName="alpha"
android:startOffset="#integer/anim_length_half"
android:duration="0" />
</set>
res/animator/flip_back.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:valueFrom="0"
android:valueTo="180"
android:propertyName="rotationY"
android:duration="#integer/anim_length" />
<objectAnimator
android:valueFrom="1.0"
android:valueTo="0.0"
android:propertyName="alpha"
android:startOffset="#integer/anim_length_half"
android:duration="0" />
</set>
If have any question, just comment. ;)
I want creat aniamtion rotation before it rotaion from 0 to -30 and after from -30 to 0 so I created two file animation
xoay.xml
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="-30"
android:pivotX="50%"
android:duration="6000"
android:repeatCount="infinite"
android:fillAfter="true" />
xoay2.xml
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="-30"
android:toDegrees="0"
android:pivotX="50%"
android:duration="6000"
android:repeatCount="infinite"
android:fillAfter="true" />
and in activity I start animation with code
final RotateAnimation rotate= (RotateAnimation) AnimationUtils.loadAnimation(this,R.anim.xoay);
final RotateAnimation rotate2= (RotateAnimation) AnimationUtils.loadAnimation(this,R.anim.xoay_2);
and when I set
myView.startAnimation(rotate); or myView.startAnimation(rotate2);
it run. Now I want when myView finish animation xoay.xml it will run xoay2.xml and when xoay2.xml finish it run xoay.xml...
I tried with code :
AnimationSet s = new AnimationSet(false);
s.addAnimation(rotate);
s.addAnimation(rotate2);
myView.startAnimation(s)
but it not run.
How I can do it? Thank you very much !
You can achieve that with RotateAnimation
Animation an = new RotateAnimation(0.0f, 30.0f);
// Set the animation's parameters
an.setDuration(6000); // duration in ms
an.setRepeatCount(-1); // -1 = infinite repeated
an.setRepeatMode(Animation.REVERSE); // reverses each repeat
an.setFillAfter(true); // keep rotation after animation
// Aply animation to image view
myView.setAnimation(an);
I will create for you Just copy it and apply on your project
Step-1: Create Animation xml files
rotate_1.xml
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="0"
android:duration="1200" />
rotate_2.xml
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="360"
android:toDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="0"
android:duration="1200" />
activity_main.xml
<TextView
android:id="#+id/tvDemo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:background="#color/colorAccent"
android:layout_gravity="center"
/>
MainActivity.java
TextView tvDemo;
boolean isFirstTime;
RotateAnimation rotate;
RotateAnimation rotate2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvDemo = (TextView) findViewById(R.id.tvDemo);
rotate = (RotateAnimation) AnimationUtils.loadAnimation(this, R.anim.rotate_up);
rotate2 = (RotateAnimation) AnimationUtils.loadAnimation(this, R.anim.rotate_down);
tvDemo.startAnimation(rotate);
rotate.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
tvDemo.startAnimation(rotate2);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
rotate2.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
tvDemo.startAnimation(rotate);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
isFirstTime = false;
tvDemo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
isFirstTime = true;
}
});
}
I Hope this code will work for you
Thank you
Better you user Animators instead
AccelerateInterpolator ACCELERATE_INTERPOLATOR = new AccelerateInterpolator();
AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator rotationAnim = ObjectAnimator.ofFloat(((StoryHolder) holder).ivLike, "rotation", 0f, -30f);
rotationAnim.setRepeatCount(ValueAnimator.INFINITE);
rotationAnim.setDuration(300);
rotationAnim.setInterpolator(ACCELERATE_INTERPOLATOR);
ObjectAnimator rotationAnim2 = ObjectAnimator.ofFloat(((StoryHolder) holder).ivLike, "rotation", 0f, -30f);
rotationAnim2.setRepeatCount(ValueAnimator.INFINITE);
rotationAnim2.setDuration(300);
rotationAnim2.setInterpolator(ACCELERATE_INTERPOLATOR);
animatorSet.play(rotationAnim).before(rotationAnim2);
animatorSet.start();
//ROTATION
ObjectAnimator.ofFloat(yourView, View.ROTATION, 0f, 180f).setDuration(300).start();
//ROTATION Back
ObjectAnimator.ofFloat(yourView, View.ROTATION, 180f, 0F ).setDuration(300).start();
I'm having a trouble with animations in android. I have my animation_char.xml:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:duration="300"
android:fromAlpha="0.0"
android:interpolator="#android:anim/accelerate_interpolator"
android:toAlpha="1.0"/>
</set>
That is ok, but in my MainActivity I want to start an animation one after one. So I created a method to make it more easy and just change the ImageView
public void animation(ImageView imageView){
animation = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.animation_char);
imageView.startAnimation(animation);
}
And for make consecutives animations, I'm trying to use AnimatorSet. But as I read AnimatorSet works with Animator, not with Animation. So my question is:
is there a way to load an animation in a animator?? Or should I use another way in order to achieve what I want to do? Thanks in advance!
EDIT
I changed my method and now Im trying with this but the problem is that all the images appear at the same time, how can I add some delay between animations?
public void animation() {
animation= AnimationUtils.loadAnimation(getApplicationContext(),R.anim.animation_char);
w.startAnimation(animation);
a.startAnimation(animation);
r.startAnimation(animation);
}
Actually I've answered on this question here. You should start your second animation in onAnimationEnd of AnimationListener of first animations. The same for second one.
You should use AnimationSet class instead of AnimatorSet.
For instance
AnimationSet as = new AnimationSet(true);
as.setFillEnabled(true);
as.setInterpolator(new BounceInterpolator());
as.addAnimation(firstAnim);
as.addAnimation(secondAnim);
as.setDuration(1000);
imageView.startAnimation(as);
I put this here maybe it helps someone...
I did something like this. I have 3 images that I want to fall one after the other.
note1 = findViewById(R.id.note1);
note1.setVisibility(View.INVISIBLE);
note2 = findViewById(R.id.note2);
note2.setVisibility(View.INVISIBLE);
note3 = findViewById(R.id.note3);
note3.setVisibility(View.INVISIBLE);
Setting visibility so that they are not shown initially
And then create 3 animations
Animation slideDown = AnimationUtils.loadAnimation(this, R.anim.slide_down);
note1.startAnimation(slideDown);
final Animation slideDown2 = AnimationUtils.loadAnimation(SplashScreen.this, R.anim.slide_down);
final Animation slideDown3 = AnimationUtils.loadAnimation(SplashScreen.this, R.anim.slide_down);
Next step is to add the event listeners that #Divers added:
slideDown.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
note1.setVisibility(View.VISIBLE);
note2.startAnimation(slideDown2);
slideDown2.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
note3.startAnimation(slideDown3);
note2.setVisibility(View.VISIBLE);
slideDown3.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
note3.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
And that's all
My animation xml is something like
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="800"
android:fromXDelta="0%"
android:fromYDelta="-50%p"
/>
<alpha
android:duration="500"
android:fromAlpha="0.1"
android:toAlpha="1.0"
/>
</set>
If you use Kotlin, you can use this way:
doOnEnd {startDelay = 1000L
start() }
Where repeatCount = 1
look at this example:
val animations = arrayOf(-140f).map { translation ->
ObjectAnimator.ofFloat(binding.viewYatch, "translationX", translation).apply {
//Update
duration = 800
repeatCount = 1
repeatMode = ObjectAnimator.RESTART
doOnEnd {
startDelay = 1000L
start()
}
}
}
val set = AnimatorSet()
set.playTogether(animations)
set.start()
Hi am doing one app here i need to apply rotate,move scale animation to my imageview..i tried using below code rotate and scale animation working well but in scale animation image is not scaling in where translate animation stoped that postion its coming back to original postion there its scaling..but i need to scale image where my image stoped using translate animation..where i did mistake any one suggest me thanks
public class MainActivity extends Activity {
ImageView i1;
TranslateAnimation moveLefttoRight1;
Animation logoMoveAnimation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
i1=(ImageView)findViewById(R.id.img);
final Animation myRotation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.rotate1);
i1.startAnimation(myRotation);
moveLefttoRight1 = new TranslateAnimation(0, 0, 0, 200);
moveLefttoRight1.setDuration(2000);
moveLefttoRight1.setFillAfter(true);
myRotation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
i1.startAnimation(moveLefttoRight1);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
logoMoveAnimation = AnimationUtils.loadAnimation(this, R.anim.sacle);
moveLefttoRight1.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
i1.startAnimation(logoMoveAnimation);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
}
scale.xml:
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="0.5"
android:toXScale="2.0"
android:fromYScale="0.5"
android:toYScale="2.0"
android:pivotX="0%"
android:pivotY="100%"
android:startOffset="0"
android:duration="1000"
android:fillAfter="true" />
rotate.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<rotate android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="0"
android:duration="3000"/>
</set>
u may try
after translation has finished
img.setTranslation(value);
value = the position where image should be after translation
I have only one ImageView in my layout and I am changing its resource when a gasture event detected. I just want to show an animation while changing resource of ImageView. Can I use ViewFlipper with one ImageView?
For a single imageview you can use this helper function:
public static void ImageViewAnimatedChange(Context c, final ImageView v, final Bitmap new_image) {
final Animation anim_out = AnimationUtils.loadAnimation(c, android.R.anim.fade_out);
final Animation anim_in = AnimationUtils.loadAnimation(c, android.R.anim.fade_in);
anim_out.setAnimationListener(new AnimationListener()
{
#Override public void onAnimationStart(Animation animation) {}
#Override public void onAnimationRepeat(Animation animation) {}
#Override public void onAnimationEnd(Animation animation)
{
v.setImageBitmap(new_image);
anim_in.setAnimationListener(new AnimationListener() {
#Override public void onAnimationStart(Animation animation) {}
#Override public void onAnimationRepeat(Animation animation) {}
#Override public void onAnimationEnd(Animation animation) {}
});
v.startAnimation(anim_in);
}
});
v.startAnimation(anim_out);
}
Here's an example using ImageSwitcher like #Konstantin Burov suggested:
Add this ImageSwitcher element to your xml layout:
<ImageSwitcher
android:id="#+id/slide_trans_imageswitcher"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ImageSwitcher>
Create in and out animations in res/anim/:
Out animation:
//left_to_right_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<translate android:fromXDelta="0%" android:toXDelta="100%"
android:fromYDelta="0%" android:toYDelta="0%"
android:duration="700"/>
</set>
And in animation:
//left_to_right_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<translate android:fromXDelta="-100%" android:toXDelta="0%"
android:fromYDelta="0%" android:toYDelta="0%"
android:duration="700"/>
</set>
Initialize them in your code:
Animation in = AnimationUtils.loadAnimation(this, R.anim.left_to_right_in);
Animation out = AnimationUtils.loadAnimation(this, R.anim.left_to_right_out);
Initialize your ImageSwitcher:
private ImageSwitcher imageSwitcher;
imageSwitcher = (ImageSwitcher)findViewById(R.id.slide_trans_imageswitcher);
Attach the animations to it:
imageSwitcher.setInAnimation(in);
imageSwitcher.setOutAnimation(out);
Now everytime you set an image resource for imageSwitcher, it will switch in a slide animation.
For example we can change the image every X seconds:
private int animationCounter = 1;
private Handler imageSwitcherHandler;
imageSwitcherHandler = new Handler(Looper.getMainLooper());
imageSwitcherHandler.post(new Runnable() {
#Override
public void run() {
switch (animationCounter++) {
case 1:
imageSwitcher.setImageResource(R.drawable.image1);
break;
case 2:
imageSwitcher.setImageResource(R.drawable.image2);
break;
case 3:
imageSwitcher.setImageResource(R.drawable.image3);
break;
}
animationCounter %= 4;
if(animationCounter == 0 ) animationCounter = 1;
imageSwitcherHandler.postDelayed(this, 3000);
}
});
I found another way to animate it using transition drawable(I took idea from here)
public static void setImageDrawableWithAnimation(ImageView imageView,
Drawable drawable,
int duration) {
Drawable currentDrawable = imageView.getDrawable();
if (currentDrawable == null) {
imageView.setImageDrawable(drawable);
return;
}
TransitionDrawable transitionDrawable = new TransitionDrawable(new Drawable[] {
currentDrawable,
drawable
});
imageView.setImageDrawable(transitionDrawable);
transitionDrawable.startTransition(duration);
}
Analogous kotlin extension function:
fun ImageView.setImageDrawableWithAnimation(drawable: Drawable, duration: Int = 300) {
val currentDrawable = getDrawable()
if (currentDrawable == null) {
setImageDrawable(drawable)
return
}
val transitionDrawable = TransitionDrawable(arrayOf(
currentDrawable,
drawable
))
setImageDrawable(transitionDrawable)
transitionDrawable.startTransition(duration)
}
If your drawables contains transparent parts, this flag could be useful to prevent old drawable visibility:
transitionDrawable.setCrossFadeEnabled(true);
Consider using Rotate3dAnimation available in the API demo app.
View > Animation > 3D transition
You can also check this question on SO