I want to create timer progress bar for 1 minute. I've used following code but it is starting from 60 to 0 whereas using same procedure I've to start from 0 to 60.
public static void animateTimerProgress(int currentTimeDuration, final int maxTimeDuration, boolean withStartDelay, final DonutProgress timeOutProgressView, Runnable endAction) {
final int duration = currentTimeDuration < 0 ? 1 : currentTimeDuration;
timeOutProgressView.setMax(maxTimeDuration);
timeOutProgressView.setProgress(duration);
timeOutProgressView.animate()
.setDuration(duration * SECOND_IN_MILLIS)
.setInterpolator(new LinearInterpolator())
.setStartDelay(withStartDelay ? TIMEOUT_START_DELAY : 0)
.setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int progress = 1 + (int) ((1f - valueAnimator.getAnimatedFraction()) * (duration - 1f));
timeOutProgressView.setProgress(progress);
}
})
.withEndAction(endAction)
.start();
}
Any help would be appreciated.
you can use ValueAnimator like this
ValueAnimator animator = ValueAnimator.ofInt(0, 60);
animator.setDuration(duration * SECOND_IN_MILLIS);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
timeOutProgressView.setProgress((int) animation.getAnimatedValue());
}
});
animator.start();
On Kotlin, you can use 2 extension functions to help with that, incrementing 1 by 1 on progress. In this way, you can have a smoother animation:
/**
* ProgressBar Extensions
*/
fun ProgressBar.setBigMax(max: Int) {
this.max = max * 1000
}
fun ProgressBar.animateTo(progressTo: Int, startDelay: Long) {
val animation = ObjectAnimator.ofInt(
this,
"progress",
this.progress,
progressTo * 1000
)
animation.duration = 500
animation.interpolator = DecelerateInterpolator()
animation.startDelay = startDelay
animation.start()
}
How to use it:
progress.setBigMax(10)
progress.animateTo(10, 100)
Use following code to get your progress
int progress = 1 + (int) (valueAnimator.getAnimatedFraction() * (duration - 1f));
valueAnimator.getAnimatedFraction() gives the fraction value of your animation. You need to multiply by the max progress/duration to get current value of progress.
make a class
public class Anim {
public static void fadeOutProgressLayout(Activity act, final ViewGroup progressLayout) {
act.runOnUiThread(new Runnable() {
#Override
public void run() {
Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator());
fadeOut.setDuration(300);
fadeOut.setAnimationListener(new Animation.AnimationListener()
{
public void onAnimationEnd(Animation animation)
{
progressLayout.setVisibility(View.GONE);
}
public void onAnimationRepeat(Animation animation) {}
public void onAnimationStart(Animation animation) {}
});
progressLayout.startAnimation(fadeOut);
}
});
}
}
and write this line where ever you want the progress to go
Anim.fadeOutProgressLayout(GamblingVideosActivity.this, progressLayout);
Related
am creating login and signup in same page with circle reveal animation ,switch the view using a floating action button, it very lag when switching one view to another view,
Login page Contain two relative layout and a floating action button
one view for login and other for signup
when floating action button click view will switch to another ie login to signup and vise versa.. i achieved but it is too lag how can i make it smooth
in tab(big screen) it works very smoothly(am creating two layout one for mobile and other for tab)
can anyone help me.. this is my code..
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void viewMenu() {
if (!isOpen) {
// int x = layoutContent.getRight();
// int y = layoutContent.getBottom();
int x = Math.round(fab.getX() + fab.getWidth() / 2);
int y = Math.round(fab.getY() - fab.getHeight());
int startRadius = 0;
int endRadius = (int) Math.hypot(layoutMain.getWidth(), layoutMain.getHeight());
fab.setBackgroundTintList(ColorStateList.valueOf(ResourcesCompat.getColor(getResources(),android.R.color.white,null)));
fab.setImageResource(R.drawable.ic_cross);
Animator anim = ViewAnimationUtils.createCircularReveal(layoutButtons, x, y, startRadius, endRadius);
anim.setInterpolator(new AccelerateDecelerateInterpolator());
layoutButtons.setVisibility(View.VISIBLE);
anim.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animator) {
// fst_view.setVisibility(View.GONE);
}
#Override
public void onAnimationEnd(Animator animator) {
}
#Override
public void onAnimationCancel(Animator animator) {
}
#Override
public void onAnimationRepeat(Animator animator) {
}
});
anim.start();
isOpen = true;
} else {
// int x = layoutButtons.getRight();
// int y = layoutButtons.getBottom();
int x = Math.round(fab.getX() + fab.getWidth() / 2);
int y = Math.round(fab.getY() + fab.getHeight()/2) - toolbar.getHeight();
int startRadius = Math.max(layoutContent.getWidth(), layoutContent.getHeight());
int endRadius = 0;
fab.setBackgroundTintList(ColorStateList.valueOf(ResourcesCompat.getColor(getResources(),R.color.colorAccent,null)));
fab.setImageResource(R.drawable.ic_menu_camera);
// fst_view.setVisibility(View.VISIBLE);
Animator anim = ViewAnimationUtils.createCircularReveal(layoutButtons, x, y, startRadius, endRadius);
anim.setInterpolator(new AccelerateDecelerateInterpolator());
anim.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animator) {
}
#Override
public void onAnimationEnd(Animator animator) {
layoutButtons.setVisibility(View.GONE);
}
#Override
public void onAnimationCancel(Animator animator) {
}
#Override
public void onAnimationRepeat(Animator animator) {
}
});
anim.start();
isOpen = false;
}
}
As far as I can see, you could use FastOutLinearInInterpolator() instead of AccelerateDecelerateInterpolator(), and add anim.setDuration() with animation duration you want.
And set layoutButtons.setVisibility() to View.INVISIBLE like described here in the bottom of the article.
Furthermore, you can rid of from Math.round() when you calculate view x, y coordinates.
It worked great for my case.
Here is my example code
I'm trying to make an animation of an imageview that revolves around a circle shape.
Here is the currrent code who works but without repeating the animation with different values:
public void runAnimation(){
ImageView worldView=findViewById(R.id.imageView);
int radius=worldView.getHeight()*30/70;
int centerx = worldView.getLeft()+radius;
int centery = worldView.getTop()+radius;
//List<Animator> myList = new ArrayList<>();
for (int i=0;i<360;i++) {
/*---I calculate the points of the circle---*/
int angle= (int) ((i * 2 * Math.PI) / 360);
int x= (int) (centerx+(radius*Math.cos(angle)));
int y= (int) (centery+(radius*Math.sin(angle)));
/*---Here carView is the ImageView that need to turn around the worldView---*/
ObjectAnimator animatorX =ObjectAnimator.ofFloat(carView, "x",x);
ObjectAnimator animatorY =ObjectAnimator.ofFloat(carView, "y",y);
ObjectAnimator animatorR =ObjectAnimator.ofFloat(carView, "rotation", i);
animatorX.setDuration(500);
animatorY.setDuration(500);
animatorR.setDuration(500);
AnimatorSet animatorSet=new AnimatorSet();
animatorSet.playTogether(animatorX,animatorY,animatorR);
animatorSet.start();
//myList.add(animatorSet);
}
//AnimatorSet animatorSet=new AnimatorSet();
//animatorSet.playSequentially(myList);
}
The commentary ("//") are here to illustrate what I want to create.
Thank in advance for your help.
You can add a listener to each AnimatorSet by using addListener(Animator.AnimatorListener listener).
for (int i=0;i<360;i++) {
// ...skipped some lines here...
AnimatorSet animatorSet=new AnimatorSet();
animatorSet.playTogether(animatorX,animatorY,animatorR);
myList.add(animatorSet);
animatorSet.addListener(myListener);
}
where myListener is defined as follows:
private Animator.AnimatorListener myListener = new Animator.AnimatorListener(){
#Override
public void onAnimationStart(Animator animation){
// no op
}
#Override
public void onAnimationRepeat(Animator animation){
// no op
}
#Override
public void onAnimationCancel(Animator animation){
// no op
}
#Override
public void onAnimationEnd(Animator animation){
startNextAnimation();
}
};
In addition to that, you need some variable private int counter; to iterate over the list.
Before starting the first animation, you set it to zero:
counter = 0;
myList.get(0).start();
To start the next animation (if there is one left):
private void startNextAnimation(){
counter++;
if(counter == myList.size()){
return;
}
myList.get(counter).start();
}
So what i am trying to achieve is user would open to first page of the view pager, and the view pager would bounce to half of the second page and bounce back to the fist page indicating that there are more pages to scroll to. I was wondering on how i could implement this?
You can use fakeDragBy method to achieve this effect:
viewPager.beginFakeDrag();
viewPager.fakeDragBy(offset); //offset in pixels.
viewPager.endFakeDrag();
EDIT:
I have made method for this:
private int animFactor;
private ValueAnimator animator = new ValueAnimator();
private void animateViewPager(final ViewPager pager, final int offset, final int delay) {
if (!animator.isRunning()) {
animator.removeAllUpdateListeners();
animator.removeAllListeners();
//Set animation
animator.setIntValues(0, -offset);
animator.setDuration(delay);
animator.setRepeatCount(1);
animator.setRepeatMode(ValueAnimator.RESTART);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = animFactor * (Integer) animation.getAnimatedValue();
if (!pager.isFakeDragging()) {
pager.beginFakeDrag();
}
pager.fakeDragBy(value);
}
});
animator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationStart(Animator animation) {
animFactor = 1;
}
#Override
public void onAnimationEnd(Animator animation) {
pager.endFakeDrag();
}
#Override
public void onAnimationRepeat(Animator animation) {
animFactor = -1;
}
});
animator.start();
}
}
Example of usage:
animateViewPager(pager, 10, 1000);
Edit2: ValueAnimator is class for Api level 11. Also set pager adapter before calling this method.
Adding a note to #Yuraj's answer. Call the method in onWindowFocusChanged when hasFocus==true as follows to avoid indexOutOfBoundsException:
#Override
public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
if(hasFocus)
{
Handler handler = new Handler();
final Runnable r = new Runnable()
{
public void run()
{
if(mViewPager.getCurrentItem() == 0)
{
Context context = Activity_main.this;
String filename="Init";
SharedPreferences stats;
stats = context.getSharedPreferences(filename, 0);
int appOpen = stats.getInt("appOpen", 0);
if(appOpen <= 5)
{
animateViewPager(mViewPager, 10, 300);
appOpen += 1;
SharedPreferences.Editor editor = stats.edit();
editor.putInt("appOpen", appOpen);
editor.commit();
}
}
}
};
handler.postDelayed(r, WAIT_VIEWPAGER_NUDGE);
}
}
Thank you Yuvraj! It worked with a simple modification. If anybody is getting "Invalid index 0, size is 0" error, here's a simple fix for it. If you call animateViewPager() method in onCreate() you might get this error, "Invalid index 0, size is 0". I believe viewpager.beginFakeDrag(); is being called before viewPager items / childs are initialized. So, call animateViewPager() with a delay like so:
new Handler().postDelayed(() -> animateViewPager(viewPager, 10, 1000), 500);
500 is the delay in milisecond
I am Trying to animate 3 images one after the other using value animator but i am not able to decide how to call the three handlers after regular intervals..Suppose there are 3 images and i m making three handlers for animating them.But i am able to bring the three images at a time but not one after the other at regular intervals.Please Help
This is my UpdateListener which i am calling from my handler
public void startAnimation_image(final ImageView aniView) {
animator = ValueAnimator.ofFloat(0, .8f);
animator.setDuration(Constants.ANIM_DURATION);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
int Low = 10;
int High = width-150;
int R = (int) ((Math.random() * (High - Low)) + Low);
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = ((Float) (animation.getAnimatedValue())).floatValue();
aniView.setTranslationX(R);
Log.e("mscale",150*mScale +"");
Log.e("value is", value+"");
aniView.setTranslationY((mDisplaySize.bottom + (150*mScale))*value);
x_point = aniView.getTranslationX();
y_point = aniView.getTranslationY();
}
});
animator.addListener(new AnimatorListener() {
#Override
public void onAnimationStart(Animator arg0) {
}
#Override
public void onAnimationRepeat(Animator arg0) {
}
#Override
public void onAnimationEnd(Animator arg0) {
startAnimation();
}
#Override
public void onAnimationCancel(Animator arg0) {
}
});
animator.start();
}
This is one of my handler
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//int viewId = new Random().nextInt(STARS.length);
id = getApplicationContext().getResources().getIdentifier(STARS[0], "drawable",
getApplicationContext().getPackageName());
inflate = LayoutInflater.from(StarsActivity2.this);
img[0].setVisibility(ImageView.VISIBLE);
img[0].setImageResource(id);
mAllImageViews.add(img[0]);
LayoutParams animationLayout = (LayoutParams) img[0].getLayoutParams();
img[0].setLayoutParams(animationLayout);
Log.e("mHandler",img[0]+ "");
startAnimation_image(img[0]);
}
};
There are similaarly three handlers and three update listeners.. Please help...
You can delay an animation by offset ms by calling
animation.setStartOffset(offset);
So for three images with duration ANIM_DURATION, you can use the following values to start them sequentially (probably by passing them as a parameter to startAnimation_image())
// note: this is for illustrative purposes. You should put this in a loop
int firstOffset = 0 * ANIM_DURATION; // starts immediately
int secondOffset = 1 * ANIM_DURATION; // starts after the first animation is finished
int thirdOffset = 2 * ANIM_DURATION; // starts after the second animation is finished
// ... and so on.
If I create a RotateAnimation based on certain duration and degree parameters, but I want to call the same animation with different duration and degree parameters, how do I do that?
RotateAnimation animation = new RotateAnimation(fromDegrees, toDegrees, width, height/2);
animation.setInterpolator(new LinearInterpolator());
animation.setDuration(animationDuration);
animation.setFillAfter(true);
animation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
activityTimeOrRepeat.setText(task.getDurationTitle());
activityTimeOrRepeat.setTextColor(textColor);
activityDescription.setText(task.getTitle());
activityDescription.setTextColor(textColor);
timeLeftForThisActivity.setTextColor(textColor);
currentTimerIndex[0] = index;
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
timeLeftForThisActivity.setText("00:00");
CountDownTimer currentTimer = timers[index];
currentTimer.cancel();
if (index == taskSize - 1) {
overallTimer[0].cancel();
startButton.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.done_button_master));
startButton.setTag(context.getString(R.string.wtrDoneButtonTag));
elapsedTimeDynamic.setText(String.format("%02d:%02d", (totalActivityTime / 1000) / 60, (totalActivityTime / 1000) % 60));
}
else {
RotateAnimation nextAnimation = animations[index + 1];
CountDownTimer nextTimer = timers[index + 1];
nextTimer.start();
workoutWidget.startAnimation(nextAnimation);
}
}
});
How do I call this same animation, but with different duration and degree parameters?