ConstraintSet 动画中引用视图的宽度为 wrap_content 时视图的平移动画
Posted
技术标签:
【中文标题】ConstraintSet 动画中引用视图的宽度为 wrap_content 时视图的平移动画【英文标题】:Translation animation of view when referenced view's width is wrap_content in ConstraintSet animation 【发布时间】:2020-02-22 10:58:12 【问题描述】:这是xml布局的设计begin.xml
:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_
android:layout_
>
<Button
android:id="@+id/delete"
android:layout_
android:layout_
android:text="@string/delete"
android:layout_margin="0dp"
style="@style/DeleteButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:translationZ="-2dp"
/>
<View
android:id="@+id/top_layer"
android:layout_
android:layout_
android:background="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
/>
<ImageButton
android:id="@+id/bet_slip_remove_item"
android:layout_
android:layout_
app:srcCompat="@drawable/close"
android:background="@drawable/button_white_radius_10"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@id/top_layer"
android:contentDescription="@string/close"
/>
<TextView
android:id="@+id/some_text"
android:layout_
android:layout_
android:text="@string/timeout_error"
app:layout_constraintTop_toTopOf="@id/top_layer"
app:layout_constraintBottom_toBottomOf="@id/top_layer"
app:layout_constraintStart_toStartOf="@id/top_layer"
android:layout_marginStart="8dp"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
看起来像这样:
top_layer
视图后面隐藏着一个Delete
按钮。
通过单击“X”,我希望通过使用 ConstraintSet 动画,top_layer
视图向左移动,其左侧部分位于屏幕之外并显示Delete
按钮,以获得如下效果:
问题在于Delete
按钮的宽度设置为wrap_content
,但是即使它具有固定宽度,我该如何设置xml布局end.xml
,以在最后获得所需的设计图片?
将视图的一部分设置在屏幕之外让我感到困惑。
旁注:我使用top_layer
视图有两个原因:
它隐藏了 DeleteButton
由于所有视图(X、TextView 以及可能应该存在的其他视图)都应该一起向左移动,因此我将它们的约束设置为相对于 top_layer
的尺寸。
【问题讨论】:
【参考方案1】:更新:刚刚意识到您正在通过ConstraintSet使用动画。最简单的做法是设置删除按钮的克隆(至少是一些具有相同宽度的视图),并将其结束约束设置为父布局的开始。这将为您提供一个屏幕外小部件,其起始侧在屏幕外,您希望将其他小部件移动多远。然后,您可以在左侧设置新约束并应用过渡。
这是一个示例应用程序:
MainActivity.java
public class MainActivity extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
public void onClick(View view)
ConstraintLayout layout = findViewById(R.id.layout);
ConstraintSet cs = new ConstraintSet();
cs.clone(layout);
ChangeBounds transition = new ChangeBounds();
transition.setDuration(1000);
TransitionManager.beginDelayedTransition(layout, transition);
cs.connect(R.id.some_text, ConstraintSet.START, R.id.offScreenView, ConstraintSet.START);
cs.connect(R.id.bet_slip_remove_item, ConstraintSet.END, R.id.delete, ConstraintSet.START);
cs.applyTo(layout);
activity_main.xml这有点简化,但它显示了概念。
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/layout"
android:layout_
android:layout_
tools:context=".MainActivity">
<Button
android:id="@+id/offScreenView"
android:layout_
android:layout_
android:layout_margin="0dp"
android:text="@string/delete"
app:layout_constraintEnd_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/delete"
android:layout_
android:layout_
android:layout_margin="0dp"
android:text="@string/delete"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/some_text"
android:layout_
android:layout_
android:background="@android:color/holo_blue_light"
android:gravity="center_vertical"
android:paddingStart="16dp"
android:elevation="7dp"
android:text="@string/timeout_error"
app:layout_constraintBottom_toBottomOf="@+id/delete"
app:layout_constraintEnd_toEndOf="@id/bet_slip_remove_item"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/bet_slip_remove_item"
android:layout_
android:layout_
android:onClick="onClick"
android:elevation="7dp"
app:layout_constraintBottom_toBottomOf="@+id/delete"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/close" />
</androidx.constraintlayout.widget.ConstraintLayout>
带有 translationX 属性的动画也可以:
您可以为需要向左移动的每个元素设置 translationX 属性的动画。您还需要确定“删除”按钮的宽度,以了解向左移动多远。
在应用程序的启动部分添加类似的内容 - onCreate() 用于活动:
// Top level member variables.
private ObjectAnimator slide1Animator;
private ObjectAnimator slide2Animator;
private ObjectAnimator slide3Animator;
findViewById(R.id.top_layer).getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
@Override
public void onGlobalLayout()
View topLayer = findViewById(R.id.top_layer);
View someText = findViewById(R.id.some_text);
View delete = findViewById(R.id.bet_slip_remove_item);
pixToSlide = -findViewById(R.id.delete).getWidth();
slide1Animator = ObjectAnimator.ofFloat(topLayer, "translationX", pixToSlide)
.setDuration(1000);
slide2Animator = ObjectAnimator.ofFloat(someText, "translationX", pixToSlide)
.setDuration(1000);
slide3Animator = ObjectAnimator.ofFloat(delete, "translationX", pixToSlide)
.setDuration(1000);
);
然后,在“x”的点击处理程序中,执行以下操作:
slide1Animator.start();
slide2Animator.start();
slide3Animator.start();
这会将视图移到屏幕左侧,并在下方显示删除按钮。
【讨论】:
以上是关于ConstraintSet 动画中引用视图的宽度为 wrap_content 时视图的平移动画的主要内容,如果未能解决你的问题,请参考以下文章
在 BottomSheetFragment 上重复 ConstraintSet 的过渡动画问题
通过 constraintSet 以编程方式设置约束会导致视图消失
如何在 jetpack compose 中使用 MotionLayout、MotionScene、ConstraintSet?