I tried to implement createCircularReveal() in FloatingButton. But the animation is too fast. How to increase the duration of the Animation. I tried setDuration(milli-seconds), But its not working.
I follow developer.android.com, Defining Custom Animations
Here my code:
int cx = (fabBtn.getLeft() + fabBtn.getRight()) / 2;
int cy = (fabBtn.getTop() + fabBtn.getBottom()) / 2;
int finalRadius = Math.max(fabBtn.getWidth(), fabBtn.getHeight());
Animator anim = ViewAnimationUtils.createCircularReveal(fabBtn, cx, cy, 2, finalRadius);
anim.setDuration(2000);
fabBtn.setVisibility(View.VISIBLE);
anim.start();
I am also facing the issue as I mentioned and I am able to resolve this issue by getting cx and cy the center position for image view (In your case I think it is button).
So get cx and cy using this:
int cx = (fabBtn.getWidth()) / 2;
int cy = (fabBtn.getHeight()) / 2;
Instead of this::
int cx = (fabBtn.getLeft() + fabBtn.getRight()) / 2;
int cy = (fabBtn.getTop() + fabBtn.getBottom()) / 2;
You might be calling getWidth() and getHeight() too soon.
So you'll have to use a getViewTreeObserver()
Be sure to add a duration to anim.setDuration(time) and set the initial visibility of the view to INVISIBLE
Here the code:
public void checker() {
myView.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
int finalHeight = myView.getMeasuredHeight();
int finalWidth = myView.getMeasuredWidth();
// Do your work here
myView.getViewTreeObserver().removeOnPreDrawListener(this);
cx = finalHeight / 2;
cy = finalWidth / 2;
finalRadius = Math.max(finalHeight, finalWidth);
anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
myView.setVisibility(View.VISIBLE);
anim.setDuration(3000);
anim.start();
return true;
}
});
}
I thought I had the same problem, but it seems that, for some reason, a duration of just 2000 milliseconds is not enough for the animation to show. When I set the duration to 3000, I saw a beautiful circle animation.
A small delay of 1 second also helped
// get the center for the clipping circle
int cx = myView.getWidth() / 2;
int cy = myView.getHeight() / 2;
// get the final radius for the clipping circle
int finalRadius = Math.max(myView.getWidth(), myView.getHeight());
// create the animator for this view (the start radius is zero)
Animator anim = ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
anim.setStartDelay(1000);
// make the view visible when the animation starts
anim.addListener(new AnimatorListenerAdapter()
{
#Override
public void onAnimationStart(Animator animation)
{
super.onAnimationStart(animation);
myView.setVisibility(View.VISIBLE);
}
});
// start the animation
anim.start();
Related
I know how to use CircularReveal to reveal a view, so I'm looking for a way to do something like "CircularHide". In other words, I want to invisible a view by a circular animation (increasing radius) after making it visible. How can I do that?
I've written this to reveal:
private void startCircularReveal() {
RelativeLayout changeableLayout = findViewById(R.id.layoutChangeable);
int centerX = (likeButton.getRight() + likeButton.getLeft()) / 2;
int centerY = (likeButton.getBottom() + likeButton.getTop()) / 2;
float endRadius = (float) Math.hypot(changeableLayout.getWidth(), changeableLayout.getHeight());
changeableLayout.setVisibility(View.VISIBLE);
Animator revealAnimator = ViewAnimationUtils.createCircularReveal(changeableLayout,
centerX, centerY, 0, endRadius);
revealAnimator.setDuration(200).start();
}
I can't combine two TranslateAnimations, but if i run each animation separatly I have the expected results (works fine). My only problem is when trying to combine both TranslateAnimations in one AnimationSet, in this case no animation is rendered, and after the 4000 ms the image is rendered on top left of the parent view.
This is how I am trying to run both animations in a set:
private void animateView(int width, int height, View view) {
AnimationSet animationSet = new AnimationSet(true);
int startX1 = -(width / 2);
int startY1 = getView().getHeight();
int endX1 = getView().getWidth() / 3;
int endY1 = getView().getHeight() - (getView().getHeight() / 3);
int endX2 = getView().getWidth() - width / 2;
int endY2 = 0;
TranslateAnimation anim1 = new TranslateAnimation(startX1, endX1, startY1, endY1);
anim1.setDuration(2000);
animationSet.addAnimation(anim1);
TranslateAnimation anim2 = new TranslateAnimation(endX1, endX2, endY1, endY2);
anim2.setDuration(2000);
anim2.setStartOffset(2000);
animationSet.addAnimation(anim2);
view.startAnimation(animationSet);
}
I am trying to modify a little this library: https://github.com/Shinelw/ColorArcProgressBar
And this is what i've done so far, without the purple circle indicator:
arc progress bar
My question is: how can i animate the purple circle along with the progress(as shown in the image)?
Inside ColorArcProgressBar class that extends View, at onDraw method, this is how the progress is draw: canvas.drawArc(bgRect, startAngle, currentAngle, false, progressPaint);
and the animation is
private void setAnimation(float last, float current, int length) {
progressAnimator = ValueAnimator.ofFloat(last, current);
progressAnimator.setDuration(length);
progressAnimator.setTarget(currentAngle);
progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
currentAngle = (float) animation.getAnimatedValue();
curValues = currentAngle / k;
}
});
progressAnimator.start();
}
I managed to position the purple bitmat at the start of the progress like this:
canvas.drawBitmap(mIcon,bgRect.left+mIcon.getWidth()/2 +30, bgRect.bottom - 40 +mIcon.getHeight()/2 , null);
Now, how can I animate it along the arc like the progress?
Didn't try this out, if it's not right it's close...
// since currentAngle is a "sweep" angle, the
// final angle should be current + start
float thetaD = startAngle + currentAngle;
if (thetaD > 360F) {
thetaD -= 360F;
}
// convert degrees to radians
float theta = (float) Math.toRadians(thetaD);
// polar to Cartesian coordinates
float x = (float) (Math.cos(theta) * bgRect.width() / 2) + bgRect.centerX();
float y = (float) (Math.sin(theta) * bgRect.height() / 2) + bgRect.centerY();
canvas.drawBitmap(mIcon, x - mIcon.getWidth()/2, y - mIcon.getHeight()/2 , null);
It helped that your bitmap is circular, so we didn't have to rotate that...
How to implement this animation using curvedmotion because documentation does not have a good example.
https://www.google.com/design/spec/animation/meaningful-transitions.html#meaningful-transitions-hierarchical-timing
As you can see, the path is basically a quarter of an oval. The parametric equation of an oval is like this:
x = a * cos(t)
y = b * cos(t)
See http://www.mathopenref.com/coordparamellipse.html
You have three parameters. Two of them (a, b) are the width and the height of the bounding box of your quarter-oval. The third one can be taken from animation interpolator. To get the right quarter, you need a value from range [PI*3/2, PI*2].
final View fab;
final int startX = fab.getTranslationX(),startY = fab.getTranslationY();
final int endX = 100,endY = 0;
ValueAnimator animator = ValueAnimator.ofFloat((float)(Math.PI*3/2),(float)(Math.PI*2));
animator.setInterpolator(new DecelerateInterpolator());
animator.setDuration(500);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float t = (float) valueAnimator.getAnimatedValue();
float a = endX-startX;
float b = endY-startY;
fab.setTranslationX((float) (a*Math.cos(t)));
fab.setTranslationY((float) (b*Math.sin(t)));
}
});
animator.start();
I wants to swipe the ViewPager. I used following code for page swipe. But unfortunately is not working.
Solo solo = new Solo(getInstrumentation(), getActivity());
int screenHeight = activityUtils.getCurrentActivity().getWindowManager().getDefaultDisplay()
.getHeight();
int screenWidth = activityUtils.getCurrentActivity(false).getWindowManager().getDefaultDisplay()
.getWidth();
float x = screenWidth / 3.0f * 2.0f;
float y = screenHeight / 3.0f * 2.0f;
Try: 1
solo.swipe(x, 0, y, y, 40);
Try: 2
if (side == Side.LEFT)
drag(0, x, y, y, 40);
else if (side == Side.RIGHT)
drag(x, 0, y, y, 40);
Try: 3
Following method working but it's moving only single page and also it's moving very slowly.
solo1.scrollToSide(Solo.RIGHT);
Is there any option for fast swipe? Which one is best? Kindly share your ideas.
My code with Robotium 5.1
for (int count = 0; count < noOfPages; count++)
solo.swipeToRight(count);
Methods for view pager swipes
private void swipeToLeft(int stepCount) {
Display display = solo.getCurrentActivity().getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
float xStart = width - 10 ;
float xEnd = 10;
solo.drag(xStart, xEnd, height / 2, height / 2, stepCount);
}
private void swipeToRight(int stepCount) {
Display display = solo.getCurrentActivity().getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
float xStart = 10 ;
float xEnd = width - 10;
solo.drag(xStart, xEnd, height / 2, height / 2, stepCount);
}
solo.scrollToSide(Solo.RIGHT);
This implementation is also fast enough...
This issue has been fixed in Robotium 5.1. You can download it from here:
https://code.google.com/p/robotium/wiki/Downloads?tm=2
Well the code in the robotium repo for scroll to side is:
public void scrollToSide(int side) {
switch (side){
case RIGHT: scroller.scrollToSide(Scroller.Side.RIGHT, 0.70F); break;
case LEFT: scroller.scrollToSide(Scroller.Side.LEFT, 0.70F); break;
}
}
#SuppressWarnings("deprecation")
public void scrollToSide(Side side, float scrollPosition) {
int screenHeight = activityUtils.getCurrentActivity().getWindowManager().getDefaultDisplay()
.getHeight();
int screenWidth = activityUtils.getCurrentActivity(false).getWindowManager().getDefaultDisplay()
.getWidth();
float x = screenWidth * scrollPosition;
float y = screenHeight / 2.0f;
if (side == Side.LEFT)
drag(0, x, y, y, 40);
else if (side == Side.RIGHT)
drag(x, 0, y, y, 40);
}
public void drag(float fromX, float toX, float fromY, float toY,
int stepCount) {
dialogUtils.hideSoftKeyboard(null, false, true);
scroller.drag(fromX, toX, fromY, toY, stepCount);
}
So it looks like you must be close, my guess is the numbers you have used in your drag call are not able to make the view pager work. I would suggest trying th enumbers used by robotium EXCEPT for the last paramater which if you change should make the swipe happen quicker as this number is the ampount of events required to complete the swipe. You may need to experiment with the number.