I'm using a RotateAnimation to rotate an AppCompatButton, used as a toolbar button, and i want to change its background while is rotating.
I didn't find any useful topic so far.
Here's my code :
AppCompatButton mBtn = (AppCompatButton) view.findViewById(R.id.search_btn);
Animation mRotateAnimation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.rotation);
mBtn.setAnimation(mRotateAnimation);
mBtn.startAnimation(mRotateAnimation);
rotation.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="600" />
I want to get a smooth background change between the beginning and the end of animation. Any useful resource link or code would be amazing. Thank you guys!
You should add another ValueAnimation to your view.
AppCompatButton mBtn = (AppCompatButton) view.findViewById(R.id.search_btn);
Animation mRotateAnimation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.rotation);
mBtn.setAnimation(mRotateAnimation);
mBtn.startAnimation(mRotateAnimation);
int colorFrom = getResources().getColor(R.color.red);
int colorTo = getResources().getColor(R.color.blue);
ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
colorAnimation.setDuration(600);
colorAnimation.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animator) {
mBtn.setBackgroundColor((int) animator.getAnimatedValue());
}
});
colorAnimation.start();
Related
In my app, I have a button to show a drop-down menu, inside of that menu we have some options, one of this is "flip A coin",
the purpose of this option is to flip a coin easy animation, that animation appears inside a textView, and show a head-side or a tail-side of a coin instead of the text in the textView.
I have two problems:
The animation doesn't work how I want, it should appear in 1 second a coin instead of the text inside the textView, it stays there and after 2 seconds he disappears, but after the disappearance, the coin image come back inside the textView, it shouldn't reappear.
This is not a real question for a problem but more an optional question like "you know how to do that?". I 'don't know how to create a flip animation with a coin multiple rotations.
XML drop down menu:
<item
android:id="#+id/flipacoin"
android:title="#string/flipACoin" />
<item
android:id="#+id/rolladice"
android:title="#string/rollADice" />
<item
android:id="#+id/imagebackground"
android:title="#string/changeImage" />
JAVA code that calls the animation function:
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()){
case R.id.flipacoin:
flipACoin();
return true;
case R.id.rolladice:
Toast.makeText(this,"TODO roll a dice",Toast.LENGTH_SHORT).show();
return true;
case R.id.imagebackground:
Toast.makeText(this,"TODO image background",Toast.LENGTH_SHORT).show();
return true;
default:
return false;
}
}
JAVA animation function:
public void flipACoin(){
coin.setText(null); //this is for remove the text inside the textView
coin.setBackground(RANDOM.nextFloat() > 0.5f ? getResources().getDrawable(R.drawable.tails) : getResources().getDrawable(R.drawable.heads));
Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator());
fadeIn.setDuration(1000);
Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator());
fadeOut.setStartOffset(2000);
fadeOut.setDuration(1000);
AnimationSet animation = new AnimationSet(false);
animation.addAnimation(fadeIn);
animation.addAnimation(fadeOut);
coin.setAnimation(animation);
}
When You set background at the beginning it just stays after animation. To set back text and background to null You can add Animation listener. Below is sample application which does it:
public class MainActivity extends AppCompatActivity
{
TextView coin;
Random RANDOM;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RANDOM = new Random();
coin = findViewById(R.id.coin);
(findViewById(R.id.click)).setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
flipACoin();
}
});
}
public void flipACoin()
{
coin.setText(null);
coin.setBackground(ResourcesCompat.getDrawable(getResources(),
RANDOM.nextFloat() > 0.5f ? R.drawable.ic_launcher_background : R.drawable.ic_launcher_foreground,
null
));
Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator());
fadeIn.setDuration(1000);
Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator());
fadeOut.setStartOffset(2000);
fadeOut.setDuration(1000);
AnimationSet animation = new AnimationSet(false);
animation.addAnimation(fadeIn);
animation.addAnimation(fadeOut);
// listener, it will execute function when animation starts/ends/repeats
animation.setAnimationListener(new Animation.AnimationListener()
{
#Override
public void onAnimationStart(Animation animation)
{
Log.d("MyTag", "onAnimationStart:");
}
#Override
public void onAnimationEnd(Animation animation) // when animation ends, set text and background to null
{
Log.d("MyTag", "onAnimationEnd:");
coin.setBackground(null);
coin.setText("Default");
}
#Override
public void onAnimationRepeat(Animation animation)
{
Log.d("MyTag", "onAnimationRepeat:");
}
});
coin.setAnimation(animation);
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<Button
android:id="#+id/click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="click"
/>
<TextView
android:id="#+id/coin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Default"
/>
</androidx.appcompat.widget.LinearLayoutCompat>
I am trying to implement a "pairing" animation into my activity but am having trouble getting it to work properly. what I have are several ImageViews that move left to right and back again on an infinite repeat but are staggered out, I believe it is called a caterpiller animation.
I am using an XML Animation with a StartOffset. The problem is that is when the animation repeats, it also repeats the offset. I only want the offset to happen when the animation is first started and not on repeats.
I have tried using ObjectAnimators but they introduce several other problems that make them just not usable and feel like a bodge. I have also tried setting the offset to zero on animation end/repeat but still nothing.
I have been trying to figure this out for a week so some help would be greatly appreciated. Thanks.
Here is the code for my Object animator:
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1250"
android:valueTo="440"
android:fillAfter="false"
android:valueType="floatType"
android:propertyName="translationX"
android:repeatCount="infinite"
android:startOffset="1100"
android:repeatMode="reverse"/>
here is the code for my Animation:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1250"
android:fillAfter="false">
<translate
android:interpolator="#android:anim/linear_interpolator"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:toXDelta="92%p">
</translate>
</set>
The XML of the ImageView I am trying to animate - there are several of these:
<ImageView
android:layout_width="12dp"
android:layout_height="12dp"
android:id="#+id/pairing_circle_four"
android:background="#drawable/small_green_circle"/>
The Java code for running the animations:
mCircleAnimation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.circle_animation);
mFirstStaggeredAnim = AnimatorInflater.loadAnimator(this, R.animator.staggered_animation_300);
mFirstStaggeredAnim.setTarget(mCircleTwo);
mSecondStaggeredAnim = AnimatorInflater.loadAnimator(this, R.animator.staggered_pairing_animation_600);
mSecondStaggeredAnim.setTarget(mCircleThree);
mThirdStaggeredAnim = AnimatorInflater.loadAnimator(this, R.animator.staggered_animation_1100);
mThirdStaggeredAnim.setTarget(mCircleFour);
mFourthStaggeredAnim = AnimatorInflater.loadAnimator(this, R.animator.staggered_animation_1400);
mFourthStaggeredAnim.setTarget(mCircleFive);
mFifthStaggeredAnim = AnimatorInflater.loadAnimator(this, R.animator.staggered_animation_1700);
mFifthStaggeredAnim.setTarget(mCircleSix);
mSixthStaggeredAnim = AnimatorInflater.loadAnimator(this, R.animator.staggered_animation_2000);
mSixthStaggeredAnim.setTarget(mCircleSeven);
fadeInFromBottom.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
mCircleOne.startAnimation(mCircleAnimation);
mFirstStaggeredAnim.start();
mSecondStaggeredAnim.start();
mThirdStaggeredAnim.start();
mFourthStaggeredAnim.start();
mFifthStaggeredAnim.start();
mSixthStaggeredAnim.start();
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
How can I display a message at a specific location in a Google Maps Activity on Android without adding a marker? I just want to display a small pop up animation containing a message at specific coordinates.
Are there any GitHub libraries that can perform this specific task?
You can place any View over MapFragment (or MapView) and animate it as you wish with Animations: animate size, position, transparency etc., use various interpolators and merge several animations into one via AnimatorSet. To get screen position of the View for specific LatLng coordinates you can use Projection.toScreenLocation() method.
For example, for "Hello World" TextView with "popup" animation over the map, you can use code like that:
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="activities.MainActivity">
<fragment class="com.google.android.gms.maps.SupportMapFragment"
android:id="#+id/map_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<TextView
android:id="#+id/popup_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:visibility="invisible"
android:text="Hello World!"/>
</RelativeLayout>
MainActivity.java:
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mGoogleMap;
private SupportMapFragment mMapSupportedFragment;
private TextView mPopUpTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPopUpTextView = (TextView) findViewById(R.id.popup_view);
mMapSupportedFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map_fragment);
mMapSupportedFragment.getMapAsync(MainActivity.this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
mGoogleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng latLng) {
// get screen position for latLng
Projection projection = mGoogleMap.getProjection();
Point origin = projection.toScreenLocation(latLng);
// popup TextView
popUpView(origin, mPopUpTextView, 500);
}
});
}
public void popUpView(final Point origin, final View view, long duration){
view.setX(origin.x);
view.setY(origin.y);
view.setVisibility(View.VISIBLE);
ValueAnimator sizeAnimation = ValueAnimator.ofInt(0, view.getMeasuredHeight());
sizeAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
sizeAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.height = val;
view.setLayoutParams(layoutParams);
}
});
sizeAnimation.setDuration(duration);
ValueAnimator positionAnimation = ValueAnimator.ofInt(0, view.getMeasuredHeight());
positionAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
positionAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
view.setY(origin.y - val);
}
});
positionAnimation.setDuration(duration);
AnimatorSet popUpSet = new AnimatorSet();
popUpSet.play(sizeAnimation).with(positionAnimation);
popUpSet.start();
}
}
Result:
I would suggest you go with marker only.
As marker it self gives some features like animation and all.
You can also customize the marker in different way to show the text and not the image and also you can user the customized text like html text show more decorated text backed by html and css.
This one is simple and great solution as i have also used the same in of my project.
I need to make an ImageView slide from left to right of the screen with a smooth animation (I want the ImageView to be visible during the transition) I tried with the following code:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
camion.animate()
.translationX(width)
.setDuration(2000)
.setInterpolator(new LinearInterpolator())
.setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
//camion.setVisibility(View.GONE);
}
});
The ImageView moves but the animation is laggy and not smooth like I want to.
What am I doing wrong on the code?
Creating this kind of tween animation is simple. Just follow the steps,
Step 1
Create a directory anim inside the res directory and put this as slide.xml
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/linear_interpolator"
android:fillAfter="true">
<translate
android:fromXDelta="0%p"
android:toXDelta="75%p"
android:duration="800" />
</set>
You can obviously customize the animation by changing the two attributes fromXDelta and toXDelta. The %p refers to with respect to the parent which simply means that it will move the image 75% with respect to the parent.
Step 2
// Refer the ImageView like this
imageView = (ImageView) findViewById(R.id.img);
// Load the animation like this
animSlide = AnimationUtils.loadAnimation(getApplicationContext(),
R.anim.slide);
// Start the animation like this
imageView.startAnimation(animSlide);
You can also setInterpolator() and setListeners() if you want to. I haven't shown them here to keep it simple. If you need, just let me know.
NOTE
As you have mentioned repeatedly, that you are experiencing a laggy animation. I have tested this animation on 3 real devices and 2 emulators and the animation was buttery smooth on all of them. Tested on low end devices like Moto E to high end devices like Nexus 5 and Galaxy S6.
If you still have a lag running this code, then the test device must be the reason. The code is perfect.
UPDATE
I just checked on my Moto G running on Lollipop too, the animation is running smoothly. This is a very small and light-weight animation, and should never be laggy. If you are still getting a lag, then it must be the device you are testing, or some other piece of code on that Activity making the UI slow or unresponsive.
Try to check which one is applicable to you,
I have tested on a total of 6 devices now with no lag at all. So, you can be rest assured that your production app will not have any lag, it can be your device which is slow
If you are doing some heavy operations like accessing the file system, database, or any other heavy operation, it must be slowing down the UI thread and you are loosing frames. Try to use AsyncTask for these heavy operations
Try this. It will animate the imageview.
ImageView img_animation = (ImageView) findViewById(R.id.img_animation);
Display display = getWindowManager().getDefaultDisplay();
float width = display.getWidth();
TranslateAnimation animation = new TranslateAnimation(0, width - 50, 0, 0); // new TranslateAnimation(xFrom,xTo, yFrom,yTo)
animation.setDuration(1000); // animation duration
animation.setRepeatCount(5); // animation repeat count
animation.setRepeatMode(2); // repeat animation (left to right, right to
// left )
// animation.setFillAfter(true);
img_animation.startAnimation(animation); // start animation
TranslateAnimation animate = new TranslateAnimation(0, -view.getWidth(), 0, 0);
animate.setDuration(500);
animate.setFillAfter(true);
view.startAnimation(animate);
Hope this works for u
animation.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Animation" >
<ImageView
android:id="#+id/img_animation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginTop="42dp"
android:src="#drawable/emo_im_laughing" />
</RelativeLayout>
Animation.java
import android.os.Bundle;
import android.app.Activity;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
public class Animation extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.);
ImageView img_animation = (ImageView) findViewById(R.id.img_animation);
TranslateAnimation animation = new TranslateAnimation(0.0f, 400.0f,
0.0f, 0.0f);
animation.setDuration(5000);
animation.setRepeatCount(5);
animation.setRepeatMode(2);
animation.setFillAfter(true);
img_animation.startAnimation(animation);
}
}
try the code below
TranslateAnimation animation = new TranslateAnimation(0.0f, 0.0f, 0.0f, 1500.0f); // new TranslateAnimation (float fromXDelta,float toXDelta, float fromYDelta, float toYDelta)
animation.setDuration(2000); // animation duration
animation.setRepeatCount(1); // animation repeat count if u repeat only once set to 1 if u don't repeat set to 0
animation.setFillAfter(false);
your_view .startAnimation(animation);//your_view for mine is imageView
public class MainActivity extends Activity {
int windowwidth;
int windowheight;
private LayoutParams layoutParams;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
windowwidth = getWindowManager().getDefaultDisplay().getWidth();
windowheight = getWindowManager().getDefaultDisplay().getHeight();
final ImageView img = (ImageView) findViewById(R.id.imageView1);
img.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
LayoutParams layoutParams = (LayoutParams) img
.getLayoutParams();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
int x_cord = (int) event.getRawX();
int y_cord = (int) event.getRawY();
if (x_cord > windowwidth) {
x_cord = windowwidth;
}
if (y_cord > windowheight) {
y_cord = windowheight;
}
layoutParams.leftMargin = x_cord - 25;
layoutParams.topMargin = y_cord - 75;
img.setLayoutParams(layoutParams);
break;
default:
break;
}
return true;
}
});
}
}
To Move imageview
from Right to Left Using #Aritra Roy Answer.
Use this code
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/linear_interpolator"
android:fillAfter="true">
<translate
android:fromXDelta="75%p"
android:toXDelta="0%p"
android:duration="100000" />
</set>
Now we have MotionLayout try to use that for very clean and smooth sliding animation.
I have the following xml:
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/accelerate_interpolator">
<translate
android:fromXDelta="0%p"
android:toXDelta="30%p"
android:duration="600">
</translate>
</set>
and this class:
switch_bg.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!isChecked) {
Animation animation = android.view.animation.AnimationUtils
.loadAnimation(AppService.getAppContext(),
com.waze.R.anim.slide_to_right);
animation.setInterpolator(new AccelerateInterpolator());
animation.setFillAfter(true);
boxImage_left.startAnimation(animation);
AlphaAnimation alpha = new AlphaAnimation(1, 0);
alpha.setDuration(1000);
alpha.setInterpolator(new AccelerateInterpolator());
alpha.setFillAfter(true);
vImage_left.startAnimation(alpha);
} else {
Animation animation = android.view.animation.AnimationUtils
.loadAnimation(AppService.getAppContext(),
com.waze.R.anim.slide_to_left);
animation.setInterpolator(new AccelerateInterpolator());
animation.setFillAfter(true);
boxImage_left.startAnimation(animation);
AlphaAnimation alpha = new AlphaAnimation(0, 1);
alpha.setDuration(1000);
alpha.setInterpolator(new AccelerateInterpolator());
alpha.setFillAfter(true);
vImage_left.startAnimation(alpha);
}
TransitionDrawable transition = (TransitionDrawable) switch_bg
.getBackground();
transition.reverseTransition(TRANSITION_TIME);
isChecked = !isChecked;
}
});
}
when I move the box right-to-left it stays there after animation,
but after animation left-to-right it returns to origin position on the left.
How come?
I use alpha.setFillAfter(true); on both cases.
update
strangely if I cancel the setFillAfter for alpha animation,
the sliding transition stays OK at the end. How come? these are two different transition objects.
As I understand it you need only a single tween animation at a time on a view; you should be able to express the alpha animation in the xml too. This would solve your problem; should be reliable across all android versions (I'm not sure your current solution always looks right); and simplify the code.