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();
Related
I have an odd error/side effect happening with my Android app I am doing right now for a school project.
The end goal is supposed to be a view that gets revealed after pressing a button at the top of the screen. It is initially placed invisibly and toggled after that.
However, for some reason the root view it gets attached to is also having its visibility toggled, which so happens to be the main layout of the fragment it is in. So effectively, the initial setVisibility() call is causing my entire fragment to disappear.
Any reason why?
EDIT: Giving the layout a FrameLayout to be attached to fixes the problem. However, the question still remains: what is causing this behaviour?
Code:
#Override
public void onStart() {
super.onStart();
//prep timeselector view for transitions
dashboardContainer = this.getView().findViewById(R.id.dashboardContainer);
vgTimeSelector = getLayoutInflater().inflate(R.layout.viewgroup_timeselector,dashboardContainer);
vgTimeSelector.setVisibility(View.INVISIBLE);
//add timeselector popup
bellButton = this.getView().findViewById(R.id.notificationButton);
bellButton.setOnClickListener(togglerListener);
}
private void toggleTimeSwitcherView () {
//this is all animation stuff for timeselector
int x = vgTimeSelector.getRight();
int y = vgTimeSelector.getTop();
int endRadius = (int) Math.hypot(vgTimeSelector.getWidth(),vgTimeSelector.getHeight());
if (vgTimeSelector.getVisibility() == View.INVISIBLE) {
vgTimeSelector.setVisibility(View.VISIBLE);
Animator animator = ViewAnimationUtils.createCircularReveal(vgTimeSelector, x, y, 0, endRadius);
animator.start();
}
else {
Animator animator = ViewAnimationUtils.createCircularReveal(vgTimeSelector, x, y, endRadius, 0);
animator.start();
vgTimeSelector.setVisibility(View.INVISIBLE);
}
}
XML:
Fragment Layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DashboardFragment"
android:id="#+id/dashboardContainer">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/notificationButton"
android:layout_alignParentRight="true"
android:layout_margin="16dp"
android:text="Bell"/>
...
</RelativeLayout>
Child View:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:background="#color/darkGrey"
android:id="#+id/timeselector"
android:animateLayoutChanges="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:text="Notify me later"
android:id="#+id/notifyTV"
android:textSize="24sp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:layout_below="#id/notifyTV">
<TimePicker
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:timePickerMode="spinner" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="N"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Y"/>
</LinearLayout>
</RelativeLayout>
You are toggling the visibility of the entire dashboardContainer.
I believe this dashboardContainer.setVisibility(View.VISIBLE);
should be replaced with vgTimeSelector.setVisibility(View.VISIBLE) and
dashboardContainer.setVisibility(View.INVISIBLE); with vgTimeSelector.setVisibility(View.INVISIBLE)
//this is all animation stuff for timeselector
int x = vgTimeSelector.getRight();
int y = vgTimeSelector.getTop();
int endRadius = (int) Math.hypot(vgTimeSelector.getWidth(),vgTimeSelector.getHeight());
if (vgTimeSelector.getVisibility() == View.INVISIBLE) {
dashboardContainer.setVisibility(View.VISIBLE);
Animator animator = ViewAnimationUtils.createCircularReveal(vgTimeSelector, x, y, 0, endRadius);
animator.start();
}
else {
Animator animator = ViewAnimationUtils.createCircularReveal(vgTimeSelector, x, y, endRadius, 0);
animator.start();
dashboardContainer.setVisibility(View.INVISIBLE);
}
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;
}
}
I'm trying to animate my RecyclerView item when its clicked by making a rectangle grow from zero width to 100% (MATCH_PARENT) and become the background of the item.
However I can't see the animation working. I mean, the initial background is white, but the rectangle is gray, so the clicked item would become gray. But this is not happening.
Here's the item xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="0dp"
android:focusable="true"
android:clickable="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="72dp"
android:orientation="horizontal">
<View
android:id="#+id/colored_bar"
android:layout_width="3dp"
android:layout_height="match_parent"
android:background="#drawable/colored_bar_bg1"></View>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="#+id/option_background_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="#e0e0e0"></View>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="16dp"
android:paddingTop="16dp">
<ImageView
android:id="#+id/icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="13dp"
app:srcCompat="#drawable/ic_lock" />
<TextView
android:id="#+id/card_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toEndOf="#+id/icon"
android:layout_toRightOf="#+id/icon"
android:paddingBottom="16dp"
android:paddingLeft="8dp"
android:textColor="?android:attr/textColorPrimary"
android:textSize="16sp"
tools:text="#string/option_title_label" />
<TextView
android:id="#+id/card_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/card_title"
android:layout_toEndOf="#+id/icon"
android:layout_toRightOf="#+id/icon"
android:paddingLeft="8dp"
android:textSize="14sp"
tools:text="#string/option_description_label" />
</RelativeLayout>
</FrameLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
And the code to make the animation:
public class OptionListItemHolder extends RecyclerView.ViewHolder {
private TextView cardTitle;
private TextView cardSubtitle;
private ImageView icon;
private View coloredBar;
private View optionBackground;
public OptionListItemHolder(View v) {
super(v);
cardTitle = (TextView)v.findViewById(R.id.card_title);
cardSubtitle = (TextView)v.findViewById(R.id.card_subtitle);
icon = (ImageView)v.findViewById(R.id.icon);
coloredBar = v.findViewById(R.id.colored_bar);
optionBackground = v.findViewById(R.id.option_background_container);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ObjectAnimator animation = ObjectAnimator.ofInt(optionBackground, "width", 0, view.getWidth());
animation.setDuration(600);
animation.setInterpolator(new DecelerateInterpolator());
animation.start();
}
});
}
}
Why it is not working?
I've found that using a ValueAnimator instead works
ValueAnimator widthAnimator = ValueAnimator.ofInt(view.getWidth(), newWidth);
widthAnimator.setDuration(500);
widthAnimator.setInterpolator(new DecelerateInterpolator());
widthAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
view.getLayoutParams().width = (int) animation.getAnimatedValue();
view.requestLayout();
}
});
widthAnimator.start();
If the view's width needs to match the parent, you can get the width of the parent by
int parentWidth = ((View)view.getParent()).getMeasuredWidth();
I would like to make an animation similar to what we can find in the Play Store: https://www.youtube.com/watch?v=B5hBViIzw5Y
I already know how to have shared element between activities and how to make circular reveal, but I'm struggling to do everything in order!
Here is where I am so far, the effect is not so bad, but after the circular reveal (to hide the item) there is a little time before it starts the intent.
My item :
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/card_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardUseCompatPadding="true"
card_view:cardCornerRadius="2dp">
<RelativeLayout
android:id="#+id/secondary_back"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#color/colorPrimary"
android:visibility="gone">
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="200dp"
android:visibility="visible">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true">
<de.hdodenhof.circleimageview.CircleImageView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/shared_element"
android:transitionName="shared"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="#drawable/shared_color"
android:visibility="gone"/>
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:id="#+id/primary_back"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#drawable/ripple_background_rounded">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="16dp">
<de.hdodenhof.circleimageview.CircleImageView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_image"
android:layout_width="85dp"
android:layout_height="85dp"
app:civ_border_width="3dp"
app:civ_border_color="#color/colorPrimary"/>
</LinearLayout>
<TextView
android:id="#+id/card_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:textColor="#android:color/black"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:paddingTop="24dp"
android:paddingBottom="24dp"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
and my function to launch everything :
private void launchAnimation(View v, final int position) {
// previously visible view
final View myView = v.findViewById(R.id.primary_back);
final View background = v.findViewById(R.id.secondary_back);
// my shared element
final CircleImageView sharedElement = (CircleImageView) v.findViewById(R.id.shared_element);
// get the center for the clipping circle
int cx = myView.getWidth() / 2;
int cy = myView.getHeight() / 2;
// get the initial radius for the clipping circle
float initialRadius = (float) Math.hypot(cx, cy);
// create the animation (the final radius is zero)
final Animator anim =
ViewAnimationUtils.createCircularReveal(background, cx, cy, initialRadius, 0);
// fade in background
final Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator()); //add this
fadeIn.setDuration(200);
final Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator()); //and this
fadeOut.setDuration(200);
// make the view invisible when the animation is done
anim.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
}
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
background.setVisibility(View.GONE);
Intent intent = new Intent(context, ResultActivity.class);
// Pass data object in the bundle and populate details activity.
intent.putExtra(ResultActivity.EXTRA_POSITION, position);
ActivityOptionsCompat options = ActivityOptionsCompat.
makeSceneTransitionAnimation(activity, sharedElement, "shared");
activity.startActivity(intent, options.toBundle());
}
});
background.setVisibility(View.VISIBLE);
background.startAnimation(fadeIn);
myView.startAnimation(fadeOut);
fadeIn.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
anim.start();
}
#Override
public void onAnimationEnd(Animation animation) {
myView.setVisibility(View.GONE);
sharedElement.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
If someone knows how to simplify this animation that would be so helpful. Thanks a lot.
For everyone who might want to make this kind of animation, I found an article about this exact transition.
At the end of this article there is the project archive who helped me a lot to make it work.
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)