【问题标题】:UI components not visible in TransitionManager animations在 TransitionManager 动画中不可见的 UI 组件
【发布时间】:2020-05-11 11:57:51
【问题描述】:

这是 Java Android 应用程序中的一个问题,在 MainActivity 中有一个非常简单的自定义可拖动抽屉。

这是它在 Android 10(API 级别 29)模拟器上运行时的行为方式,也是预期的行为。

但问题是,当它在 Android L (API level 21) 模拟器上运行时,它的行为异常如下:

在动画期间,UI 组件不可见。但是当应用程序进入后台并返回时,它们就会变得可见。

应用的实现细节:

为了检测滑动/拖动触摸手势,使用了GestureDetectorCompat。 当检测到投掷手势时,将启动自定义抽屉打开动画。 动画使用ConstraintSetConstraintLayoutTransitionManager实现。

这是触摸手势检测和TransitionManager动画的实现。

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private boolean mIsDrawerOpened;
    private ConstraintLayout mRootConstraintLayout;
    private final ConstraintSet mDrawerClosedConstraintSet = new ConstraintSet();
    private final ConstraintSet mDrawerOpenedConstraintSet = new ConstraintSet();
    private GestureDetectorCompat mGestureDetector;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_drawer_closed);

        // Drawer is initially closed
        mIsDrawerOpened = false;

        mRootConstraintLayout = findViewById(R.id.rootConstraintLayout);

        mDrawerClosedConstraintSet.clone(this, R.layout.activity_main_drawer_closed);
        mDrawerOpenedConstraintSet.clone(this, R.layout.activity_main_drawer_opened);

        mGestureDetector = new GestureDetectorCompat(
                getApplicationContext(),
                new GestureDetector.SimpleOnGestureListener() {

                    @Override
                    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

                        // Drag / Fling gesture detected

                        // TODO: Recongnize unwanted drag / fling gestures and ignore them.

                        TransitionManager.beginDelayedTransition(mRootConstraintLayout);

                        // Drawer is closed?
                        if(!mIsDrawerOpened) {
                            // Open the drawer
                            mDrawerOpenedConstraintSet.applyTo(mRootConstraintLayout);
                            mIsDrawerOpened = true;
                        }

                        return true;
                    }

                    @Override
                    public boolean onSingleTapUp(MotionEvent e) {

                        // Single tap detected

                        // TODO: If user has tapped on the drawer, do not close it.

                        TransitionManager.beginDelayedTransition(mRootConstraintLayout);

                        // Drawer is opened?
                        if(mIsDrawerOpened) {
                            // Close the drawer
                            mDrawerClosedConstraintSet.applyTo(mRootConstraintLayout);
                            mIsDrawerOpened = false;
                        }

                        return true;
                    }

                    @Override
                    public boolean onDown(MotionEvent e) {
                        return true;
                    }
                }
        );
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mGestureDetector.onTouchEvent(event);
        return super.onTouchEvent(event);
    }
}

这是关闭抽屉的布局 XML。

res/layout/activity_main_drawer_closed.xml

<ConstraintLayout
    android:id="@+id/rootConstraintLayout">

    <ConstraintLayout
        android:id="@+id/drawerConstraintLayout"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        <!-- Constraint start (left) of drawer to end (right) of parent (drawer is outside the parent) -->
        app:layout_constraintStart_toEndOf="parent"
        ... >

        <Button
            android:id="@+id/button1"
            android:text="1"
            ... />

        <Button
            android:id="@+id/button2"
            android:text="2"
            ... />

    </ConstraintLayout>

    <ImageView
        android:id="@+id/notch"
        android:src="@drawable/drawer_notch"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@id/drawerConstraintLayout"
        ... />

</ConstraintLayout>

这是打开的抽屉的布局 XML。

res/layout/activity_main_drawer_opened.xml

<ConstraintLayout
    android:id="@+id/rootConstraintLayout">

    <ConstraintLayout
        android:id="@+id/drawerConstraintLayout"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        <!-- Constraint end (right) of drawer to end (right) of parent (drawer is inside the parent) -->
        app:layout_constraintEnd_toEndOf="parent"
        ... >

        <Button
            android:id="@+id/button1"
            android:text="1"
            ... />

        <Button
            android:id="@+id/button2"
            android:text="2"
            ... />

    </ConstraintLayout>

    <ImageView
        android:id="@+id/notch"
        android:src="@drawable/drawer_notch"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@id/drawerConstraintLayout"
        ... />

</ConstraintLayout>

这两种布局的约束集被用作动画的开始和结束关键帧。

最低 SDK 版本设置为 API 级别 19。

build.gradle

android {
    defaultConfig {
        minSdkVersion 19
        ...
    }
    ...
}

完整实现见this GitHub gist

【问题讨论】:

  • 我创建了这个简单的自定义可拖动抽屉作为对StackOverflow question 的回答。提问者在我的回答中指出了this 问题,我找不到解决方法。所以带着这个问题,我向社区寻求帮助。

标签: android android-constraintlayout android-transitions


【解决方案1】:

要按预期工作,您需要将android:clipChildren="false" 添加到您的根ViewGroup 在您的情况下是ConstaintLayout 在您的布局activity_main_drawer_closed.xml 中。当然,这种解决方案仅适用于您的视图位于视口之外的情况。

我不知道为什么这种行为因 Android 版本而异。理论上,从 Android Marshmallow 开始,当您启动场景转换时,根视图会被 TransitionManager 失效并被重绘。

【讨论】:

  • 成功了!你太棒了!如果你能推荐任何我们可以阅读的资源,以了解TransitionManager 的内部运作或一般的 Android 转换,请在此处发表评论。非常感谢。
  • 很遗憾,我不知道这样的资源。当我以 Android 开发人员的身份影响这些问题时,我在谷歌上回答,没有什么特别的。当然,我使用官方文档作为任何研究的起点。是的,我理解,有时很难找到问题的答案。
  • 感谢您的cmets,感谢您回答问题并解决问题。
  • 感谢@Lakindu 的帮助!!! НиколайГольцев 也谢谢...干得好...
猜你喜欢
  • 1970-01-01
  • 2023-04-01
  • 2021-05-31
  • 2019-03-14
  • 2016-09-08
  • 2018-03-12
  • 2020-08-10
  • 2013-04-20
  • 2017-07-27
相关资源
最近更新 更多