I am using the following project: https://github.com/umano/AndroidSlidingUpPanel
It works very nicely so far, but I have one issue: I want to hide the slidable panel until I press a button, then the panel should be faded in, with an animation; currently the panel is shown when the button is pressed, but without an animation, and I don't know how to implement said animation.
Any ideas would be very much welcome!
I know it's been 4 months since you asked, but I decided to post an answer anyways (so someone else can maybe benefit from it).
Fading in the slideable panel is relatively easy. You just need to start an AlphaAnimation on layout that represents the slideable panel. You will probably need to disable the panel shadow by adding
sothree:shadowHeight="0dp"
to the major layout in your xml.
The more interesting thing is when you want to expand the slideable panel from the bottom of the screen (if panel is anchored at the bottom). In this case, you can use the following code:
import android.view.animation.Animation;
import android.view.animation.Transformation;
import com.sothree.slidinguppanel.SlidingUpPanelLayout;
public class SlidingUpPanelResizeAnimation extends Animation {
private SlidingUpPanelLayout mLayout;
private float mTo;
private float mFrom = 0;
public SlidingUpPanelResizeAnimation(SlidingUpPanelLayout layout, float to, int duration) {
mLayout = layout;
mTo = to;
setDuration(duration);
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float dimension = (mTo - mFrom) * interpolatedTime + mFrom;
mLayout.setPanelHeight((int) dimension);
mLayout.requestLayout();
}
}
And start the animation by:
SlidingUpPanelLayout slidingUpPanelLayout = (SlidingUpPanelLayout) findViewById(R.id.id_of_your_major_layout);
int slideablePanelHeight = 100;
int animationDuration = 800;
SlidingUpPanelResizeAnimation animation = new SlidingUpPanelResizeAnimation(slidingUpPanelLayout, slideablePanelHeight, animationDuration);
mSlidingLayout.startAnimation(animation);
Related
Animation animation = new Animation() {
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
ViewGroup.LayoutParams params = slidingPane.getLayoutParams();
int calculatedHeight = expandedHeight - ((int) (expandedHeight * interpolatedTime));
if (calculatedHeight <= collapsedHeight) {
calculatedHeight = collapsedHeight;
}
params.height = calculatedHeight;
slidingPane.setLayoutParams(params);
slidingPane.requestLayout();
}
#Override
public boolean willChangeBounds() {
return true;
}
};
animation.setDuration(ANIMATION_DURATION);
animation.setAnimationListener(animationListener);
slidingPane.startAnimation(animation);
SlidingPane is a LinearLayout and it has a ListView as a child. ListView contains images in every row.
Now this code is working absolutely fine, but animation is not smooth. If I remove images from listview then it works fine.
I have already tried following things based on the answers on SO on similar questions -
1. Hide the content of sliding pane before animation and then again make them visible on animation end. It helps but behavior looks very odd
2. Set android:animateLayoutChanges="true" in xml, but its not animating anything
Is there anyway to solve this problem?
Instead of manually changing the height on each animation step, you should try to use the more systematic animation, like ValueAnimator, or ObjectAnimator:
slidingPane.animate().scaleY(0f).setInterpolator(new AccelerateDecelerateInterpolator()).setDuration(ANIMATION_DURATION);
You can use pivotY/pivotY on the view to control the anchor point of the scale animation.
Related docs:
https://developer.android.com/reference/android/animation/ValueAnimator.html
https://developer.android.com/reference/android/animation/ObjectAnimator.html
https://developer.android.com/guide/topics/graphics/prop-animation.html
I have a RelativeLayout with a ImageView inside it, it is aligned to the right of the screen with
android:layout_alignParentRight="true"
I then apply an animation to the layout, that will scale it to twice it size (on X-axis), but for some reason the alignment is broken and the layout (and image within it) stretches outside of the screen to the right. I was expecting it to grow to the left since it is aligned to the parent right.
I guess I could apply a translate to -X at the same time, but there are problems with this as well (1. it´s a bit complicated to compute, 2. the fillAfter never seems to work when using an AnimationSet).
Does anyone know how to solve this problem smoothly? :)
Apparently, Androids scaling is doing all sorts of bad stuff, for example it does not scale a 9-patch correct. Here is a custom animation for scaling that will solve the above and is compatible with 9-patch images. I also got some info here for the basics, this is just a rewrite of his solution: How to implement expandable panels in Android?
public class ExpandAnimation extends Animation
{
private final int mStartWidth;
private final int mDeltaWidth;
private View view;
public ExpandAnimation(View view, int startWidth, int endWidth)
{
mStartWidth = startWidth;
mDeltaWidth = endWidth - startWidth;
this.view = view;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t)
{
android.view.ViewGroup.LayoutParams lp = view.getLayoutParams();
lp.width = (int) (mStartWidth + mDeltaWidth * interpolatedTime);
view.setLayoutParams(lp);
view.invalidate();
}
#Override
public boolean willChangeBounds()
{
return true;
}
}
I'm implementing an Animation for one menu in my project.
The animation itself is ok, the menu enters and exit just as I wanted: Slide from left to right and right to left, however...
If the entire view is OUT of the screen, then it NEVER comes back egain! If, at least one pixel is still inside the screen, then it comes back normally.
I belive that Android is disposing the layout, and not caring about it after out of the screen bounds. I tried to place a setVisibility(VISIBLE) but it also didn't worked.
Here is the code:
public class ChwaziMenuAnimation extends Animation{
float posStart = 0;
float posTarget = 100;
int getCurrentPosition(){
RelativeLayout.LayoutParams rootParam =
(RelativeLayout.LayoutParams) rootView.getLayoutParams();
return rootParam.leftMargin;
}
public void setTarget(float target){
// Save current position
posStart = getCurrentPosition();
posTarget = target;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
RelativeLayout.LayoutParams rootParam =
(RelativeLayout.LayoutParams) rootView.getLayoutParams();
// Calculate current position
rootParam.leftMargin = (int) ((posTarget - posStart) * interpolatedTime + posStart);
rootView.setLayoutParams(rootParam);
}
/*
* Since we will be animating the margin, the bounds will always change
*/
public boolean willChangeBounds() {
return true;
};
};
And how I initialize the animation:
public void appear(){
Log.i(TAG, "appear");
menuAnimation.setTarget(0);
menuAnimation.setDuration(750);
rootView.clearAnimation();
rootView.startAnimation(menuAnimation);
}
public void disapear(){
Log.i(TAG, "disapear");
menuAnimation.setTarget(-400);
menuAnimation.setDuration(750);
rootView.startAnimation(menuAnimation);
}
I encountered the same problem, my workaround so far is to extend the view bounds to at least one pixel on the displayable area, and make that part transparent. Ugly, but for me it seems to work.
To make it even more weird: the view did not disappear, when shifted out the right side of the screen, only when shifted out the left side of the screen. But that might be device dependent.
This question already has an answer here:
image is playing an animation and the image is clickable
(1 answer)
Closed 10 years ago.
I've made a simple animation for an image and I set the event OnClick on the image to make a toast. The problem is that I made the image started doing the animation on the onCreate and I made set the image to be clicked and fire the toast but the problem is that the image isn't clickable, but if I press on the original position of the image, the toast is started (the image is not moving with the animation)
thx for your help
this is the animation code in anim folder (translate.xml)
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/linear_interpolator">
<translate
android:fromXDelta="-80%p"
android:toXDelta="80%p"
android:duration="20000"
android:repeatCount="100"
android:repeatMode="restart"
/>
</set>
and this is the Activity Class
package com.example.animatest;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends Activity {
private ImageView image01;
private long aefe;
private ImageView image1;
private ImageView image2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image01 = (ImageView) findViewById(R.id.imageView1);
final Animation animTranslate1 = AnimationUtils.loadAnimation(this,
R.anim.translate);
image01.startAnimation(animTranslate1);
image01.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(MainActivity.this, "hello", Toast.LENGTH_SHORT)
.show();
}
});
}
}
During the entire animation, your view remains at the old location (location when the animation just started). It is just drawn in another spot. You'd have to move your animated view after your animation ends:
Register a listener to your animation.
http://developer.android.com/reference/android/view/animation/Animation.AnimationListener.html
In your onAnimationEnd implementation, modify your Activity's layout so that it resembles the final state/layout of your animation.
Update after your comment:
The only way I see of doing this is by creating your own custom Animation in Java code and implementing your custom Animation's 'protected void applyTransformation(float interpolatedTime, Transformation t)' method. For example, in our app we have an animation that actually moves a View around instead of just drawing it at a different location. E.g. below is an example of an Animation that increases or decreases the actual height of a View:
public class ViewHeightAnimation extends Animation {
private final View view;
private final float diffHeight;
private final int startHeight;
public ViewHeightAnimation(View view, float diffHeight, int startHeight) {
this.view = view;
this.diffHeight = diffHeight;
this.startHeight = startHeight;
setDuration(200);
setInterpolator(new AccelerateDecelerateInterpolator());
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
android.view.ViewGroup.MarginLayoutParams layoutParams = (android.view.ViewGroup.MarginLayoutParams)view.getLayoutParams();
layoutParams.height = Math.round(startHeight + (diffHeight * interpolatedTime));
view.setLayoutParams(layoutParams);
}
#Override
public boolean willChangeBounds() {
return true;
}
}
Your Animation would be different, but would be using the 'getLayoutParams()' and 'setLayoutParams()' as well to modify the View's (ImageView's) position and change layoutParams.topMargin and layoutParams.leftMargin appropriately.
If you are not concerned about Android 2.x or lower, using the ObjectAnimator (3.0 or higher) or ViewPropertyAnimator (3.1 or higher) is a better solution, as was mentioned in other answer earlier.
Let me know if this helps you.
try like this:
final Animation animTranslate1 = AnimationUtils.loadAnimation(this,R.anim.translate);
animTranslate1.setFillAfter(true);
image01.startAnimation(animTranslate1);
If that does not work then you'll have to use the newer Property Animation framework (which was pointed out in the answer to your previous duplicate question)
See here to learn about it
The way you animate your imageView is only move its appearance, so actually your imageView is still at the old position. There's not an easy way to do what you want, with this type animations. You should consider to use ObjectAnimators ...
I would like to partially hide a fragment when a new fragment appears.
I am building on ScienceGuy's code on GitHub, as referenced on Fragment Animation like Gmail Honeycomb App
I start with three fragments. The left most has a weight of 6, the middle one a weight of 4, and the right most a weight of 4. Setting the weightSum to 10 makes the left and middle fragments appear, and the right most is offscreen. This is what I want.
When the user selects an item in the middle fragment, I would then like to transition the left fragment so that two thirds of it moves off the left side of the screen. Because of the weights, I would effectively have 2, 4 , 4. At this point, the right fragment has moved onto the screen completely.
Using ScienceGuy's code, I can get the right fragment to appear when the left fragment scrolls off, but the left fragment completely disappears.
I have tried using the following code:
final float middleFragmentWidth = getMiddleFragment().getView().getWidth();
ObjectAnimator animIn = ObjectAnimator.ofFloat(null, "x",
-middleFragmentWidth/2, 0).setDuration(
trans.getDuration(LayoutTransition.APPEARING));
trans.setAnimator(LayoutTransition.APPEARING, animIn);
ObjectAnimator animOut = ObjectAnimator.ofFloat(null, "x", -middleFragmentWidth,
-middleFragmentWidth/2).setDuration(
trans.getDuration(LayoutTransition.CHANGE_DISAPPEARING));
trans.setAnimator(LayoutTransition.DISAPPEARING, animOut);
I suspect that Android expects that a fragment is completely hidden when one "hides" it. Is there a way to animate fragments so that they are not actually hidden, but partially offscreen?
Alternatively, I could put the three fragments into a HorizontalScrollView, and try animating that. However, I've not done that because the middle and right most fragments contain listviews, and using a listview inside a HorizontalScrollView is to be avoided according to the docs.
I ended up creating a custom view based on LinearLayout which is 150% of the width of the device.
public class AutoSizingLinearLayout extends LinearLayout {
private static final String TAG = AutoSizingLinearLayout.class.getSimpleName();
final int myWidth;
public AutoSizingLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
myWidth = setScaledWidth(context);
}
public AutoSizingLinearLayout(Context context) {
super(context);
myWidth = setScaledWidth(context);
}
private int setScaledWidth(Context context) {
if (this.isInEditMode()){
return 1000;
} else {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
return (int) (1.5 * wm.getDefaultDisplay().getWidth());
}
}
#Override
public android.view.ViewGroup.LayoutParams getLayoutParams() {
android.view.ViewGroup.LayoutParams params = super.getLayoutParams();
params.width = myWidth;
return params;
}
And then I animate it like this.
ObjectAnimator a = ObjectAnimator.ofFloat(linearView,"translationX", -scrollamount).setDuration(900);
a.start();