UI组件在TransitionManager动画中不可见 [英] UI components not visible in TransitionManager animations

查看:89
本文介绍了UI组件在TransitionManager动画中不可见的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This is an issue in a Java Android application with a very simple custom draggable drawer in MainActivity.

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

This is how it behaves when it runs on Android 10 (API level 29) emulator, and it is the expected behavior.

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

But the problem is, when it runs on Android L (API level 21) emulator, it behaves unexpectedly as follows :

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

During the animation, UI components are not visible. But when app goes to background and comes back, they become visible.

应用的实现细节:

要检测挥动/拖动触摸手势,请使用GestureDetectorCompat. 当检测到甩动手势时,将启动自定义抽屉打开动画. 动画是使用ConstraintSetConstraintLayoutTransitionManager来实现的.

To detect fling / drag touch gesture, GestureDetectorCompat was used. When a fling gesture is detected, the custom drawer open animation is being initiated. Animation is implemented using ConstraintSet, ConstraintLayout and TransitionManager.

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

This is the implementation of touch gesture detections and TransitionManager animations.

MainActivity.java

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.

This is the layout XML of closed drawer.

res/layout/activity_main_drawer_closed.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.

This is the layout XML of opened drawer.

res/layout/activity_main_drawer_opened.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>

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

ConstraintSets from those 2 layouts are taken as start and end key-frames for animations.

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

Min SDK version is set to API level 19.

build.gradle

build.gradle

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

完整实现可在此GitHub要点中找到.

推荐答案

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

To do this works as expected you need to add android:clipChildren="false" to your root ViewGroup in your case is ConstaintLayout in your layout activity_main_drawer_closed.xml. Of course such solution applicable only when your view is outside of the viewport.

我不知道为什么这种行为在Android版本中会有所不同.从理论上讲,从Android棉花糖开始,场景切换时,根视图因TransitionManager无效而被重画.

I don't know why this behaviour differ through versions of Android. In theory, from Android Marshmallow, when you start scene transition root view became invalidated by TransitionManager and being redraw.

这篇关于UI组件在TransitionManager动画中不可见的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆