Android - LayoutChange Animation for resize a View - android

I have a LinearLayout that contains some views...
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:id="#+id/carSelectLayout"
android:orientation="vertical"
android:weightSum="100"
android:background="#C9C9C9">
<LinearLayout
android:id="#+id/LogoFragment"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="25"
android:orientation="vertical" />
<LinearLayout
android:id="#+id/CarCategoryFragment"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="50"
android:orientation="vertical"/>
</LinearLayout>
Is there any way to change a view weight with animation? Somthing like LayoutChanges Animation...
Edited:
LayoutChanges Animation only works for add, remove or change visibilty of a view!!!

You can use ValueAnimator and then add update listener where you change your layout parameters programaticly.
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int value = (Integer) valueAnimator.getAnimatedValue();
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(0, 100);
lp.weight = value;
animatedView.setLayoutParams(lp);
}
});
mAnimator.start();

You may want to check how to customize layout changes animation by taking a look at http://developer.android.com/reference/android/animation/LayoutTransition.html and the method http://developer.android.com/reference/android/animation/LayoutTransition.html#setAnimator(int, android.animation.Animator)

Related

Flickers while layout visible/gone

Is there any way to hide a view without flickering its above view?
I am trying to hide a View below MapView. Once I set its visibility to GONE, MapView flickers. As I have to add more markers dynamically, couldn't able to keep MapView and bottomView in FrameLayout, since the bottomView will hide those markers in small size screens.
Layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true">
<com.myapp.widgets.MapPlacePicker
android:id="#+id/lay_fr_map_inc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/options_layout" />
<LinearLayout
android:id="#+id/options_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:animateLayoutChanges="true"
android:background="#FFFFFF"
android:orientation="vertical"
android:visibility="visible">
<com.myapp.widgets.FontTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="10dp"
android:text="Please select a location!!"
android:textAppearance="#android:style/TextAppearance.Small" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.aigestudio.wheelpicker.WheelPicker
android:id="#+id/main_option_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="0.5"
app:wheel_atmospheric="true"
app:wheel_curved="false"
app:wheel_item_space="15dp"
app:wheel_item_text_color="#ffafafaf"
app:wheel_item_text_size="12dp"
app:wheel_selected_item_text_color="#color/colorPrimary"
app:wheel_visible_item_count="3" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
Output:
I have also tried TranslationAnimation, but no luck. Its showing more gray space than before.
int fromY = (visibility == View.GONE) ? 0 : optionLayout.getHeight();
int toY = (visibility == View.GONE) ? optionLayout.getHeight() : 0;
if (visibility == View.VISIBLE) {
optionLayout.setVisibility(visibility);
}
TranslateAnimation animate = new TranslateAnimation(
0, // fromXDelta
0, // toXDelta
fromY, // fromYDelta
toY); // toYDelta
animate.setDuration(1000);
animate.setInterpolator(new AccelerateDecelerateInterpolator());
//animate.setFillAfter(false);
animate.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
if (visibility == View.GONE)
optionLayout.setVisibility(visibility);
optionLayout.clearAnimation();
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
optionLayout.startAnimation(animate);
I don't see any flickering in that animation; if you want to avoid the vertical resizing behavior of lay_fr_map_inc then you can just remove this attribute:
android:layout_above="#+id/options_layout"
...and maybe make the height match_parent. Then, lay_fr_map_inc will stay full height, but the bottom portion will be hidden by options_layout when it appears (instead of scooting upwards).
Don't forget to change the map padding when you do this, so you don't obscure the Google logo (which is a violation of the rules): setPadding()

Android animate view does not resize other view

I have an issue on Android and can't understand why. I have the following layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/Container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/background_primary">
<RelativeLayout
android:id="#+id/RecyclerViewContainer"
android:layout_below="#+id/UpdatesBanner"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/RecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:scrollbars="none"
android:clipToPadding="false"
android:splitMotionEvents="false"
android:requiresFadingEdge="none"
android:overScrollMode="never" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_red_dark" />
</RelativeLayout>
<Droid.UIElements.UIBanner
android:id="#+id/UpdatesBanner"
android:layout_width="match_parent"
android:layout_height="130dp"
android:layout_alignParentTop="true"
android:background="#android:color/holo_green_dark" />
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
UIBanner is a custom view that content 2 buttons. One of them is binded on a Hide function which will animate the view.
public void Hide()
{
ObjectAnimator animation = ObjectAnimator.OfFloat(this, "TranslationY", TranslationY, TranslationY - Height);
animation.Start();
}
This works but the view under the banner keep the same size and does not expand. If i only make a visibility gone on the banner then it works but no animation performed.
Following the states before and after animation:
Found a solution, don't know if it is the best way to achieve this bu well i have to animate the second view too. Following the code:
ObjectAnimator bannerAnimation = ObjectAnimator.OfFloat(banner, "TranslationY", banner.TranslationY, banner.TranslationY - banner.Height);
ObjectAnimator viewAnimation = ObjectAnimator.OfFloat(recycler, "ScaleY", recycler.ScaleY, recycler.ScaleY - banner.Height);
AnimatorSet set = new AnimatorSet();
set.PlayTogether(bannerAnimation, viewAnimation);
set.Start();
Best solution is ValueAinmator
ValueAnimator viewAnim = ValueAnimator.OfInt(view.MeasuredHeight, viewHeight);
viewAnim.AddUpdateListener(new UpdateListener(view));
AnimatorSet set = new AnimatorSet();
set.AnimationEnd += (sender, e) => EndAnim();
set.Play(viewAnim);
set.Start();
And the listener
class UpdateListener : Java.Lang.Object, IAnimatorUpdateListener
{
Android.Views.View view;
public UpdateListener(Android.Views.View pView)
{
view = pView;
}
public void OnAnimationUpdate(ValueAnimator animation)
{
int value = (int)animation.AnimatedValue;
ViewGroup.LayoutParams layoutParams = view.LayoutParameters;
layoutParams.Height = value;
view.LayoutParameters = layoutParams;
}
}

LayoutTransition height to 0 causes view to dissappear instantly without animating

Given a view that is always aligned parent bottom, initially with a height of 0, I want to animate it so it slide up to it's height of WRAP_CONTENT. I'm using layout transition to achieve this:
viewGroup.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
Where viewGroup is a parent of viewToAnimate and has animateLayoutChange=true
And the logic is:
val params = viewToAnimate.layoutParams
if (expand && params.height == 0) {
params.height = ViewGroup.LayoutParams.WRAP_CONTENT
viewToAnimate.layoutParams = params
} else if (collapse && params.height != 0) {
params.height = 0
viewToAnimate.layoutParams = params
}
This works great when the view is expanded; the view slides up from the bottom to its height nicely. However, when the height is set to 0, the view simply disappears and doesn't slide in. viewToAnimate is a relative layout with some TextViews, nothing complicated. Any suggestions would be appreciated.
Video showing effect (notice the text not sliding down, just disappearing): https://www.dropbox.com/s/1pq7yh0bqx8ghif/2017_10_06_23_17_11.mp4?dl=0
View to animate:
<RelativeLayout>
..some other stuff...
<RelativeLayout
android:id="#+id/viewToAnimate"
android:layout_width="match_parent"
android:layout_height="0dp"
android:gravity="center"
android:layout_alignParentBottom="true"
android:background="#color/white">
<TextView
android:id="#+id/sampleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sample Text"
android:textSize="50sp"/>
</RelativeLayout>
</RelativeLayout>
Keep viewToAnimate layout height as "wrap_content" and the textView height as "0dp".. see example below.
<RelativeLayout
android:animateLayoutChanges="true"
android:id="#+id/viewToAnimate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_alignParentBottom="true"
android:background="#android:color/white">
<TextView
android:id="#+id/sampleText"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:text="Sample Text"
android:textSize="50sp"/>
</RelativeLayout>
final RelativeLayout viewToAnimate = (RelativeLayout) findViewById(R.id.viewToAnimate);
viewToAnimate.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
TextView sampleTV = (TextView)findViewById(R.id.sampleText);
ViewGroup.LayoutParams params = sampleTV.getLayoutParams();
if (params.height == 0) {
params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
}else {
params.height = 0;
}
sampleTV.setLayoutParams(params);
Try and let me know.
What I do to animate a view in and out of view is if the view is meant to be off screen i set the Visibility attribute to "Invisible" and then when it is to animate into view I set it to "Visible" when animation starts and when it is to animate off screen I set it to "Invisible" when the animation ends.
So instead of changing height set visibility.
if (expand) {
viewToAnimate.setVisibility(View.VISIBLE);
} else if (collapse) {
viewToAnimate.setVisibility(View.INVISIBLE);
}
to set visibility in xml use:
android:visibility="invisible"
Hope this helps.
CLARIFICATION:
I'm using custom animations and AnimationUtils.loadAnimation to get Animation than using setAnimationListener to set the visibility on the layout/view what is to be animated.
example:
Animation animation = AnimationUtils.loadAnimation(this, R.anim.custom_animation_in_or_out_of_view);
animation.setAnimationListener(new Animation.AnimationListener(){
#Override public void onAnimationStart(Animation animation) {
//should always be visible on animation starting
viewToAnimate.setVisibility(View.INVISIBLE);
}
#Override public void onAnimationRepeat(Animation animation) {}
#Override
public void onAnimationEnd(Animation animation) {
//set your viewToAnimate to the corresponding visibility...
}
});
viewToAnimate.startAnimation(animation);
custom animation xml for sliding into view:
<?xml version="1.0" encoding="utf-8"?>
<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromYDelta="0%p"
android:toYDelta="100%p"
android:duration="1000" />
and sliding out of view, just switch the values of 'fromYDelta' and 'toYDelta'.
Try to use object animator like
TextView sampleTV = (TextView) findViewById(R.id.sampleText);
//initially translate the view to bottom
sampleTV.setTranslationY(sampleTV.getHeight());
// for sliding up
sampleTV.animate().translationY(0).setDuration(100).setInterpolator(new AccelerateDecelerateInterpolator()).start();
// for sliding down
sampleTV.animate().translationY(sampleTV.getHeight()).setDuration(100).setInterpolator(new AccelerateDecelerateInterpolator()).start();
Just add this into your XML and it will takes the work.
android:animateLayoutChanges="true"
like that
<RelativeLayout>
..some other stuff...
<RelativeLayout
android:id="#+id/viewToAnimate"
android:layout_width="match_parent"
android:layout_height="0dp"
*******android:animateLayoutChanges="true"********
android:gravity="center"
android:layout_alignParentBottom="true"
android:background="#color/white">
<TextView
android:id="#+id/sampleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sample Text"
android:textSize="50sp"/>
</RelativeLayout>
</RelativeLayout>

Scale animation - How to stop child view animation

I have a layout(parent view) and a textview(child view) inside this layout. Applying scale animation on parent view but when scale animation is applied to parent view its child view also scales.Is there any way to stop child from animation ? Including the code
Layout File
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.tfg.social.MainActivity$PlaceholderFragment" >
<FrameLayout
android:id="#+id/top_layout"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_gravity="center"
android:background="#ffff00"
android:orientation="horizontal" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_gravity="center"
android:text="Top Layout"
android:background="#000000"
android:adjustViewBounds="true"
android:textAppearance="?android:attr/textAppearanceMedium" />
</FrameLayout>
Animation method
protected void expandLayout(View view) {
ObjectAnimator scaleUpY = ObjectAnimator.ofFloat(view, "scaleY", 5f);
scaleUpY.setDuration(1000);
AnimatorSet scaleAnimation = new AnimatorSet();
scaleAnimation.play(scaleUpY);
scaleAnimation.start();
}
Try this out -
ValueAnimator valueAnimator = ObjectAnimator.ofInt(start, end);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
LayoutParams layoutParams = (LayoutParams) getLayoutParams();
layoutParams.height = val;
setLayoutParams(layoutParams);
}
});
valueAnimator.setDuration(300);
valueAnimator.start();

Scrollview not resizing

I am using pinch zoom to just horizontaly zoom my custom view. It works fine, but the outside scroll view is not resizing with its content, and there are ugly blank space arround the view.
My Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<AbsoluteLayout
android:id="#+id/wrapper"
android:layout_width="wrap_content"
android:layout_height="0px"
android:layout_weight="1">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:fillViewport="true"
android:id="#+id/scrollview">
<Auda.WaveFormView
android:id="#+id/waveform"
android:layout_height="fill_parent"
android:layout_width="2000dp"
android:layout_weight="1" />
</HorizontalScrollView>
</AbsoluteLayout>
<LinearLayout
style="#style/ToolbarBackground"
android:layout_width="fill_parent"
android:layout_height="62dip"
android:gravity="center">
<ImageButton
android:id="#+id/play"
android:layout_width="71dip"
android:layout_height="52dip"
android:layout_marginTop="6dip"
android:layout_marginBottom="6dip"
style="#android:style/MediaButton"
android:src="#android:drawable/ic_media_play" />
</LinearLayout>
My zooming code
ScaleAnimation scaleAnimation = new ScaleAnimation(1f / prevScale, 1f / mScale, 1, 1, 0, 0);
scaleAnimation.Duration = 0;
scaleAnimation.FillAfter = true;
this.view.StartAnimation (scaleAnimation);
Although your view is now (for example) drawn on half of the screen, it is really still occupying the full screen. You can verify this by adding a ClickListener to the view and trying to press the blank area you marked.
To solve this, you can add an AnimationListener to your ScaleAnimation. In the onAnimationEnd, simply update the LayoutParams of your Auda.WaveFormView. For example:
ScaleAnimation scaleAnimation = new ScaleAnimation(1f / prevScale, 1f / mScale, 1, 1, 0, 0);
scaleAnimation.Duration = 0;
scaleAnimation.FillAfter = true;
this.view.StartAnimation (scaleAnimation);
//after your are done with your animation
//set the animation listener
scaleAnimation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationEnd(Animation animation) {
//this might not be the right logic
//especially that you are using scales relative to prevScale
this.view.getLayoutParams().width = v.getWidth() / mScale;
}
#Override
public void onAnimationStart(Animation animation) {}
#Override
public void onAnimationRepeat(Animation animation) {}
});
Try to change the layout width to fill_parent instead of wrap content

Categories

Resources