将视图从一个布局动画到另一个布局
Posted
技术标签:
【中文标题】将视图从一个布局动画到另一个布局【英文标题】:Animate a view from one Layout to other Layout 【发布时间】:2016-09-30 16:22:48 【问题描述】:查看附件图片以便于解释。
翻译动画有效,但它在同一视图内进行动画处理。 我希望视图从一种布局飞出到另一种布局。
我在这里的另一个答案中尝试了这个。 (相同布局的动画)
public class Animations
public Animation fromAtoB(float fromX, float fromY, float toX, float toY, int speed)
Animation fromAtoB = new TranslateAnimation(
Animation.ABSOLUTE, //from xType
fromX,
Animation.ABSOLUTE, //to xType
toX,
Animation.ABSOLUTE, //from yType
fromY,
Animation.ABSOLUTE, //to yType
toY
);
fromAtoB.setDuration(speed);
fromAtoB.setInterpolator(new AnticipateOvershootInterpolator(1.0f));
return fromAtoB;
【问题讨论】:
我不确定,但你可以尝试使用场景developer.android.com/training/transitions/index.html?hl=ru 【参考方案1】:我最近使用 Animators 制作了类似类型的动画。通常,视图不会在其父级边界之外显示自己,视图将被其父级边界切割。这就是为什么,诀窍是将一个新视图 (shuttleView) 放置在您想要设置动画的原始视图 (fromView) 之上,对齐它们,并将shuttleView 缩放/平移动画到目标视图 (toView)。
此解决方案同时支持缩放和平移,示例如下:https://www.dropbox.com/s/iom95o93076h52f/device-2016-06-03-111557.mp4?dl=0
代码如下:
activity_main.xml
<LinearLayout
android:layout_
android:layout_
android:layout_alignParentTop="true"
android:background="@android:color/holo_blue_dark">
<TextView
android:id="@+id/itemTo"
android:layout_
android:layout_
android:layout_margin="10dp"
android:background="@android:color/holo_blue_bright"
android:text="to"/>
</LinearLayout>
<LinearLayout
android:layout_
android:layout_
android:layout_alignParentBottom="true"
android:background="@android:color/holo_blue_dark">
<TextView
android:layout_
android:layout_
android:layout_margin="10dp"
android:background="@android:color/holo_blue_bright" />
<TextView
android:id="@+id/itemFrom"
android:layout_
android:layout_
android:layout_margin="10dp"
android:text="from"
android:background="@android:color/holo_blue_bright" />
<TextView
android:layout_
android:layout_
android:layout_margin="10dp"
android:background="@android:color/holo_blue_bright" />
</LinearLayout>
<View
android:id="@+id/shuttle"
android:layout_
android:layout_
android:background="@android:color/holo_blue_bright"/>
活动类:
public class MainActivity extends AppCompatActivity
public static final int ANIMATION_SPEED = 3000;
private RelativeLayout rootView;
private View fromView, toView, shuttleView;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rootView = (RelativeLayout) findViewById(R.id.rootView);
fromView = findViewById(R.id.itemFrom);
toView = findViewById(R.id.itemTo);
shuttleView = findViewById(R.id.shuttle);
fromView.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
Rect fromRect = new Rect();
Rect toRect = new Rect();
fromView.getGlobalVisibleRect(fromRect);
toView.getGlobalVisibleRect(toRect);
AnimatorSet animatorSet = getViewToViewScalingAnimator(rootView, shuttleView, fromRect, toRect, ANIMATION_SPEED, 0);
animatorSet.addListener(new Animator.AnimatorListener()
@Override
public void onAnimationStart(Animator animation)
shuttleView.setVisibility(View.VISIBLE);
fromView.setVisibility(View.INVISIBLE);
@Override
public void onAnimationEnd(Animator animation)
shuttleView.setVisibility(View.GONE);
fromView.setVisibility(View.VISIBLE);
@Override
public void onAnimationCancel(Animator animation)
@Override
public void onAnimationRepeat(Animator animation)
);
animatorSet.start();
);
public static AnimatorSet getViewToViewScalingAnimator(final RelativeLayout parentView,
final View viewToAnimate,
final Rect fromViewRect,
final Rect toViewRect,
final long duration,
final long startDelay)
// get all coordinates at once
final Rect parentViewRect = new Rect(), viewToAnimateRect = new Rect();
parentView.getGlobalVisibleRect(parentViewRect);
viewToAnimate.getGlobalVisibleRect(viewToAnimateRect);
viewToAnimate.setScaleX(1f);
viewToAnimate.setScaleY(1f);
// rescaling of the object on X-axis
final ValueAnimator valueAnimatorWidth = ValueAnimator.ofInt(fromViewRect.width(), toViewRect.width());
valueAnimatorWidth.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
@Override
public void onAnimationUpdate(ValueAnimator animation)
// Get animated width value update
int newWidth = (int) valueAnimatorWidth.getAnimatedValue();
// Get and update LayoutParams of the animated view
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) viewToAnimate.getLayoutParams();
lp.width = newWidth;
viewToAnimate.setLayoutParams(lp);
);
// rescaling of the object on Y-axis
final ValueAnimator valueAnimatorHeight = ValueAnimator.ofInt(fromViewRect.height(), toViewRect.height());
valueAnimatorHeight.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
@Override
public void onAnimationUpdate(ValueAnimator animation)
// Get animated width value update
int newHeight = (int) valueAnimatorHeight.getAnimatedValue();
// Get and update LayoutParams of the animated view
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) viewToAnimate.getLayoutParams();
lp.height = newHeight;
viewToAnimate.setLayoutParams(lp);
);
// moving of the object on X-axis
ObjectAnimator translateAnimatorX = ObjectAnimator.ofFloat(viewToAnimate, "X", fromViewRect.left - parentViewRect.left, toViewRect.left - parentViewRect.left);
// moving of the object on Y-axis
ObjectAnimator translateAnimatorY = ObjectAnimator.ofFloat(viewToAnimate, "Y", fromViewRect.top - parentViewRect.top, toViewRect.top - parentViewRect.top);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setInterpolator(new DecelerateInterpolator(1f));
animatorSet.setDuration(duration); // can be decoupled for each animator separately
animatorSet.setStartDelay(startDelay); // can be decoupled for each animator separately
animatorSet.playTogether(valueAnimatorWidth, valueAnimatorHeight, translateAnimatorX, translateAnimatorY);
return animatorSet;
您可以根据在 animatorSet 监听器中动画的不同阶段出现和消失的内容进行大量自定义。希望对您有所帮助。
【讨论】:
谢谢。看起来很有希望。要去试试 :) 赏金很快就会得到你的 有效!但是如果目标布局为空,则必须进行这样的小改动不起作用。所以必须在目标布局中以编程方式添加虚拟视图。非常感谢【参考方案2】:如果有人正在寻找更简单的解决方案,您可以使用转换框架: https://developer.android.com/training/transitions/index.html
为了动画从一个父视图到另一个父视图的转换,有一个特殊的转换 ChangeTransform: https://developer.android.com/reference/android/transition/ChangeTransform.html
还有一个小例子:
animatedView = View.inflate(ActivityMain.this, R.layout.item, firstParent);
animatedView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
Transition move = new ChangeTransform()
.addTarget(animatedView)
.setDuration(2000));
TransitionManager.beginDelayedTransition(rootParent, move);
firstParent.removeView(animatedView);
animatedView.setPadding(2,2,2,2);
animatedView.setElevation(4);
secondParent.addView(animatedView, 0);
【讨论】:
以上是关于将视图从一个布局动画到另一个布局的主要内容,如果未能解决你的问题,请参考以下文章
使用NSView.layoutSubtreeIfNeeded()动画自动布局约束不适用于macOS High Sierra