Is there any way to animate a cropping of an ImageView?
Say for example, the ImageView is 720 x 480. I want to chop off the bottom rows of pixels with an animation until the ImageView is completely gone. I have only been able to move the image up when the onclicklistener is enabled, and make it transparent, which is ok, but not what the designer asked for.
ValueAnimator anim = ValueAnimator.ofInt(myImageView.getMeasuredHeight(), 0);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = myImageView.getLayoutParams();
layoutParams.height = val;
myImageView.setLayoutParams(layoutParams);
}
});
anim.setDuration(1000);
anim.start();
I got code from here and just changed it to height: ObjectAnimator animate LinearLayout width
Assuming you only want to chop off the height, using ObjectAnimator will work out to create such a custom cropped-height animation,
First of all you need to specify getHeight() and setHeight() methods and then create a custom animation with ObjectAnimator.
public float getHeight() { ... }
public void setHeight(float h) { ... }
ObjectAnimator heightAnim= ObjectAnimator.ofFloat(yourImageView, "height", heightBegin, heightEnd);
Related
I'm trying to create an animation that expands a View from top to bottom.
Like this:
I can't use a ScaleAnimation with pivotY set to 0 because this stretches the Nine-Patch like a normal Bitmap. I need to modify the height of my View.
My current solution: (test is the View reference)
ValueAnimator anim = ValueAnimator.ofInt(test.getMeasuredHeight(), 800);
anim.setInterpolator(new FastOutSlowInInterpolator());
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
ViewGroup.LayoutParams params = test.getLayoutParams();
params.height = (int) animation.getAnimatedValue();
test.setLayoutParams(params);
}
});
anim.setDuration(250).start();
This works perfectly, but it expands the view to both sides:
Does anyone know a way to create such animation? Any help is appreciated.
A solution is to keep your implementation but limit the expansion to bottom by having an element above that won't let your view grow up:
Example:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
...
android:layout_height="100dp"/> //assuming your view starts 100dps from top
<YourView
...
.../>
</LinearLayout>
Since your container is a LinearLayout and the first View(FrameLayout) is 100dp height and above the view you wish to expand, it won't expand it's Height up because it can't overlap an element of the same hierarchy, so it will expand down
It also works if you use RelativeLayout by adding android:below="#id/framelayout_id" to YourView which will also guarantee that YourView doesn't expand up
Add an extra variable that holds initial position on Y axis.
expands top
public void expandTop(final View test) {
final float bottomAnchor = test.getY() + test.getHeight();
final ValueAnimator anim = ValueAnimator.ofInt(test.getMeasuredHeight(), 800);
anim.setInterpolator(new FastOutSlowInInterpolator());
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
ViewGroup.LayoutParams params = test.getLayoutParams();
params.height = (int) animation.getAnimatedValue();
test.setY(bottomAnchor - (int) animation.getAnimatedValue());
test.setLayoutParams(params);
}
});
anim.setDuration(2500).start();
}
expandBottom
public void expandBottom(final View test) {
final float topAnchor = test.getY();
final ValueAnimator anim = ValueAnimator.ofInt(test.getMeasuredHeight(), 800);
anim.setInterpolator(new FastOutSlowInInterpolator());
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
ViewGroup.LayoutParams params = test.getLayoutParams();
params.height = (int) animation.getAnimatedValue();
test.setY(topAnchor);
test.setLayoutParams(params);
}
});
anim.setDuration(2500).start();
}
Is there any way to rotate image like Handel down and up in one animation
like this animation is here what i want like 3d view..
Try this.
ObjectAnimator animation = ObjectAnimator.ofFloat(yourImageView, "rotationX", 0.0f, 90f);
animation.setDuration(1000);
animation.setRepeatCount(ObjectAnimator.INFINITE);
animation.setRepeatMode(ObjectAnimator.REVERSE);
animation.setInterpolator(new AccelerateDecelerateInterpolator());
animation.start();
The answer is simple, you have to set the pivot of the view so that on rotating you can rotate view by axis. (In your case, this code will keep the view bottom same and animate the top of the view like you showed in the video)
According to the image if the levers bottom box is 25percentage of the image height, then you have to calculate the axis of the image to rotate for 25%.
View v = findViewById(R.id.animate_view);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
int percentageHeightOfBox = 25;
int height = v.getMeasuredHeight();
v.setPivotX(v.getMeasuredWidth() / 2);
v.setPivotY(height - ((height * percentageHeightOfBox) / 100));
ValueAnimator animator = ValueAnimator.ofFloat(0.0f, 90f);
animator.setDuration(1000);
animator.setRepeatCount(ObjectAnimator.INFINITE);
animator.setRepeatMode(ObjectAnimator.REVERSE);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float rotate = Float.parseFloat(animation.getAnimatedValue().toString());
v.setRotationX(rotate);
}
});
animator.start();
}
});
I'm trying to change the X and Y scales of a Matrix object in conjunction with the changing shape of an ImageView to make it seem like the ImageView is merely a mask.
So in order to do that, I would change the scale of the ImageView's Matrix to reciprocate the changing scale of the ImageView itself.
So far, I'm using a single ValueAnimator to change the X scale of the Matrix and it worked:
final ValueAnimator xScaleIterationMatrix = ValueAnimator.ofFloat((1/xScaleSrcToDst)*initMatDstVals[0], initMatDstVals[0]);
final Matrix mat = initMatrixDst;
xScaleIterationMatrix.setDuration(animDurationCommon);
xScaleIterationMatrix.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mat.setScale((float)xScaleIterationMatrix.getAnimatedValue(), initMatDstVals[4]);
toReplace.interfaceImageView().setImageMatrix(mat);
}
});
xScaleIterationMatrix.start();
But that's just one ValueAnimator, and only one property (scaleX) of the Matrix.
I was thinking of using 2 ValueAnimators (to change the scaleX and scaleY [while setting the matrix in the latter]) to do that, but I wish for something simpler.
Can I use an ObjectAnimator for this task?
EDIT: The sample code for the 2 ValueAnimators proposal:
final ValueAnimator xScaleIterationMatrix = ValueAnimator.ofFloat(xScaleSrcToDst * initMatSrcVals[0], initMatSrcVals[0]);
xScaleIterationMatrix.setDuration(animDurationCommon);
xScaleIterationMatrix.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
resultXScale = (float)xScaleIterationMatrix.getAnimatedValue();
}
});
xScaleIterationMatrix.start();
final ValueAnimator yScaleIterationMatrix = ValueAnimator.ofFloat(yScaleSrcToDst * initMatSrcVals[4], initMatSrcVals[4]);
yScaleIterationMatrix.setDuration(animDurationCommon);
yScaleIterationMatrix.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
resultYScale = (float)yScaleIterationMatrix.getAnimatedValue();
mat.setScale(resultXScale, resultYScale);
source.interfaceImageView().setImageMatrix(mat);
}
});
yScaleIterationMatrix.start();
I want to change the size of the itemView of RecyclerView in the 'animateMoveImpl()' method for my ItemAnimator, but it did not work.
I have tried the scale animation, it works fine, but not enough.
What I want to achieve is to change the 'width' property, so the image shown in the itemView will adapt to the change. The scale animation just make the image stretched.
Is it possible to animate the width change of itemView in ItemAnimator?
Thanks~
Update:
The code is like follows.
ValueAnimator anim = ValueAnimator.ofFloat(1f, 0.5f);
anim.setDuration(1000);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float tmp = DEFAULT_WIDTH * (float)animation.getAnimatedValue();
animButton.setWidth((int)tmp);
animButton.requestLayout();
}
});
anim.start();
Note that it works for normal view. But it does not work int the 'animateMoveImpl()' for ItemAnimator.
In my Android app I want to hide/show a Toolbar in an animation and adjust the FrameLayout below it so that it always fills up the whole screen. I do that by animating the top margin of the FrameLayout according to the display status of the Toolbar:
public void toggleToolbars(final boolean show) {
mToolbarHidden = !show;
final Toolbar tt = getBaseActivity().getToolbar();
final FrameLayout cv = getBaseActivity().getContentView();
int translation = show ? 0 : -tt.getHeight();
ValueAnimator animator = ValueAnimator.ofFloat(ViewHelper.getTranslationY(tt), translation).setDuration(200);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float translationY = (float) animation.getAnimatedValue();
ViewHelper.setTranslationY(tt, translationY);
FrameLayout.LayoutParams clp = (FrameLayout.LayoutParams) cv.getLayoutParams();
clp.topMargin = tt.getHeight() + (int) translationY;
cv.setLayoutParams(clp);
}
});
animator.start();
}
This works fine, except for a flickering in the animation. I assume that using setLayoutParams is a costly method. requestLayout() is equally slow. How can I make this animation smoother? Can I reduce the frame rate somehow?
Note, that for certain reasons I cannot use setTranslationY and the built-in animations of CoordinatorLayout.