I try to do a menu with a hide button. When I press the hide button, i do objectAnimator= ObjectAnimator.ofFloat(myLayout, "translationY"... to move the layout up.
My problem is when I move all the layout up, it didn't grow, it only move up with his fixed size. I don't know how to refresh the size of the layout to match_parent so my 2nd layout will take all the place.
Thanks
Kick off example:
ObjectAnimator anim = ObjectAnimator.ofFloat(myLayout, "translationY"...);
anim.addListener(new AnimatorListener() {
#Override
public void onAnimationEnd(Animator animation) {
((RelativeLayout.LayoutParams) view.getLayoutParams).width = ViewGroup.LayoutParams.MATCH_PARENT;
}
});
I think you can't achive this effect using only translation. Translating object still keep its bounds in layout (you can see it when you turn on Developer options -> Show layout bounds on your device). It's just drawing in a different place.
I don't know what you exactly want to do, so if that tip is not enough, try to give more details. For now I can only propose animating one of your views' height.
Related
It's easy to add layout transitions with this attribute:
android:animateLayoutChanges="true"
However, the animation you get does not create a pleasing user experience. When elements are added to the layout (I'm using a simple vertical LinearLayout) or change from gone to visible there's a 2-stage process that I think is rather annoying. First, room is prepared for the new element (everything else is pushed down). Then when there's enough room, the new view fades into existence. Likewise, when a view is removed or changes from visible to gone, first it fades out, then the room claimed by it gradually shrinks to zero.
I would really like a way to change the animation to what I really think is the natural way to do it: When adding a view its height gradually changes from zero to its full size, so that first you see just the top, without ever changing the alpha. When removing a view its height gradually changes to its full size to zero, so that near the end of the animation you see just the top, without ever changing the alpha.
How can I accomplish this in Android? (Note: the user can tap on several buttons together and cause several elements to appear / disappear in quick succession, before the animation for the other views ended - or even make something appear while it's still appearing).
Another question that this is perhaps not the place to ask: why isn't this the default?
(And if it's possible, can a slightly different behavior be specified in which first just the bottom of the view appears, rather than the top, like the new view slides down from under the one above it?)
You have to write your own animator and set it.
Code:
final ViewGroup profileParent = (ViewGroup) view.findViewById(R.id.profileParent);
LayoutTransition transition = new LayoutTransition();
Animator appearingAnimation = ObjectAnimator.ofFloat(null, "translationY", 600/*profileParent.getHeight()*/, 0);
appearingAnimation.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
view.setTranslationY(0f);
}
});
Animator disappearingAnimation = ObjectAnimator.ofFloat(null, "translationY", 0, 600/*profileParent.getHeight()*/);
appearingAnimation.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
view.setTranslationY(0f);
}
});
transition.setAnimator(LayoutTransition.APPEARING, appearingAnimation);
transition.setDuration(LayoutTransition.APPEARING, 300);
transition.setStartDelay(LayoutTransition.APPEARING, 0);
transition.setAnimator(LayoutTransition.DISAPPEARING, disappearingAnimation);
transition.setDuration(LayoutTransition.DISAPPEARING, 300);
transition.setStartDelay(LayoutTransition.DISAPPEARING, 0);
profileParent.setLayoutTransition(transition);
I'm trying to make a really simple slide up list view, which is displayed when a user clicks on a button at the bottom of the screen. Here's how it should look:
And a complete implementation in HTML/JS http://jsbin.com/utAQOVA/1/edit
I've tried to use RelativeLayout to position the list just below the button, and put that whole thing into a wrapper and then animate that up/down (same as in the JSBin above).
The problem is that the bottom part which isn't visible in the beginning is somehow clipped, even if I slide it up. Evern if I initially show a portion of the list as the screenshow below shows, the bottom part gets clipped when it moves up and only the part that was initially visible is displayed.
What would be a proper approach to do this kind of animation?
Here's a relevant portion of the layout
Edit: after a brief discussion (in the comments of the accepted answer) I've solved this by removing the wrapping LinearLayout around the part that is animated and I simply changed height of the ListView, which pushes the button up.
The problem you have might come form how ListView does its own layout, basically it fits itself to the size available on screen and paints that part and since you create the ListView without Height or very small height that the size it keeps. You can solve this with two approaches:
Replaces the ListView with a simple LinearLayout - filled with all
you list items, I would do this if you don't have many items on the
list - then the advantages of a ListView over a simple LinearLayout
is negligible.
Use a ValueAnimator and update the position & height property of the
ListView while animating.
Adapted from a post I mentioned in the comments a ValueAnimator should look like this:
ValueAnimator va = ValueAnimator.ofInt(0, height);
va.setDuration(700);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
v.getLayoutParams().height = value.intValue();
v.setTranslationY(-value.intValue());
v.requestLayout();
}
});
I'm not sure if using setTranslationY is the right way for this question or maybe you should use a negative marginTop value (depends on the layout)
The animation you're looking for would look like this.-
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="#android:integer/config_longAnimTime"
android:fromYDelta="100%p"
android:toYDelta="0" />
You can run it storing it an animation xml resource, and doing.-
Animation anim = AnimationUtils.loadAnimation(this, R.anim.animId);
yourView.startAnimation(anim);
Can someone please explain to a noob the correct way to animate a View so its touch area and image actually move together?!
I have read lots of posts and questions and tutorials, but none explains what moves the layout and what moves the image such that I can animate a view and then leave it at its new position.
This is an example method I'm working with, trying lots of different combinations to no success. The view is in the parent RelativeLayout. It's a touchable menu of icons, and is animated with an xml resource on a click to slide off screen leaving just a little tab showing, where it needs to stay until clicked again.
public void RetractTools (View v){
final ImageView finalImage1 = (ImageView) findViewById(R.id.paintsView);
Animation slideout = AnimationUtils.loadAnimation(this, R.anim.slideout_tools);
slideout.setFillAfter(true);
slideout.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationEnd(Animation animation) {
finalImage1.setEnabled(true);
optionMenu.showing = false;
optionMenu.inMotion = false;
finalImage1.layout(1258, 668, 1697, 752);
finalImage1.setRight(1280);
finalImage1.invalidate();
}
#Override
public void onAnimationRepeat(Animation arg0) {
}
#Override
public void onAnimationStart(Animation arg0) {
finalImage1.setEnabled(false);
}
});
optionMenu.inMotion = true;
v.startAnimation(slideout);
}// End RetractMenu
No matter what I try, I encounter problems. setFillAfter does nothing when set in the xml file. Set programmatically, it leaves the image in the right place but the touch controls remain where the menu was. I have tried setLeft and setRight which apparently only move the image, not the view position, and all sorts of different layout options, and fill and no fill and invalidating and not, but can't solve it. I clearly don't undersatnd the underlying mechanics needed to position and render a view! :D
Thanks.
EDIT : Solution
For anyone having similar issues, this is how I have found to work with relative layouts. You create a LayoutParams object with the specified size, and then you can assign it positions. eg.
final RelativeLayout.LayoutParams position = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
position.leftMargin = 440;
Then assign that to your view
myView.setLayoutParams(position);
So in summary, you use a LayoutParams object as an interface to your view's position, rather than accessing the view's coordinates directly as I assumed.
What you have is basically fine, with two flaws:
You are using setFillAfter(), which is not especially useful
You are calling layout() and setRight() and stuff, which is not especially effective
Instead, in onAnimationEnd(), you need to modify the LayoutParams of the View to reflect the new position you want the widget to be in. The size and position of a widget is dictated by the layout rules it negotiates with its container. Initially, those are set via your layout XML resource. By modifying the LayoutParams at runtime, you are changing what those rules are.
What those LayoutParams are (LinearLayout.LayoutParams, RelativeLayout.LayoutParams, etc.) and what values you should specify in them, we cannot tell you, because we don't know what you are doing.
Say I have a "main screen" Layout which has to move up, to reveal a "history bar".
if ( HistoryBar == false )
{
HistoryBar = true;
TranslateAnimation MainScreenPullUp = new TranslateAnimation(0, 0, 0, -200 );
MainScreenPullUp.setDuration(350);
MainScreenPullUp.setFillAfter(true);
LinLayMain.startAnimation(MainScreenPullUp);
}
Right now I am doing it like that. But the problem is, that while the main screen layout itself moves up, all the button places keep the same, i.e. the button picture moves, but the click-spot remains in place. Any ideas how to fix that?
I tried useing an animationListener, instead setFillAfter(true) , which would TanslateY the main screen layout, once the animation stops, but it makes the layout jump and flicker. Are there any other ways?
edit:
Thanks, Vineet.
Got it working with:
ObjectAnimator pullUp = ObjectAnimator.ofFloat(LinLayMain, "translationY", 0f, -200f);
pullUp.setDuration(350);
pullUp.start();
I faced the same problem. From 3.0 android has property animation. Below 3.0 I tackled this issue with the help of view's method offsetLeftAndRight (int offset) and offsetTopAndBottom (int offset). You can refer this link for more details.
For Property animation refer this link.
I have an activity that is a blank screen except for one ImageView object that has it's gravity set to center. Then in my res\anim directory, I animate that image, basically moving it from the bottom of the screen to the center (rising up), using . What I'm trying to figure out is how to have the activity load with a blank screen, not showing the ImageView until after the animation finishes with the image centered. What happens right now is the screen shows with the image already in the center, then the animation takes over and moves it from bottom to top. How Can I make the animation happen first, before showing the ImageView?
EDIT...Please see new/related question below:
OK, the .setVisibilty works (thanks for the help), but it's led me to another problem. In my xml layout file for this activity, I only have 2 objects, a TextView at the top of the screen (using LinearLayout) and then an ImageView that is set to:
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center">
<ImageView android:id="#+id/Image01"
android:src="#drawable/image_01"
android:layout_height="150dp"
android:layout_width="200dp"
android:paddingTop="10px"
>
</ImageView>
</LinearLayout>
This puts the image dead center of the screen. What I want the animation to do is have the image rise from the bottom of the screen to the center. The problem is that even if I have the .setVisibility to INVISIBLE in the onCreate, then set to VISIBLE after I start the animation, it still flashes the image in the dead center of the screen (for about half a second), then immediately drops to the bottom and rises back up to center. This looks sloppy. How can I make the image never show until appears at bottom then rise to the center? I beg for specifics, as I'm just getting feet wet with java and xml.
Final EDIT...
Never mind, this only seems to happen in the emulator. It works fine on the phone.
Thanks for all your help everyone.
Make sure that your image is invisible when the activity starts, by setting the android:visibility attribute to invisible, or by using setVisibility() in onCreate().
Then start the animation and call setVisibility(View.VISIBLE) in one go:
image.startAnimation(...);
image.setVisibility(View.VISIBLE);
I think you want to look at theImageView.setVisibility(View.INVISIBLE).
And you can get information on what your animation is doing (if it's done) with an AnimationListener.
The AnimationListener will have something like this:
AnimationListener a_to_b = new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
// Do something
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
// Do something
}
};
and you set it by:
Animation ani = AnimationUtils.loadAnimation(this, R.anim.ani);
ani.setAnimationListener(a_to_b);
Hope this helps