如何在将 Android 应用程序置于后台之前更改视图?

kit*_*une 5 android android-recents react-native react-native-android

我有一个带有两个视图的应用程序,只有当应用程序处于活动状态(前台)时才必须显示蓝色视图,而当应用程序置于后台时(例如在 Android 上的硬件方形按钮上计时),必须显示绿色视图。

在此处输入图片说明

下图显示了当我将应用程序置于后台状态时当前得到的结果:

在此处输入图片说明

以下是当 App 置于后台时我想做的事情(在 iOS 上工作,在 Android 上不太好):

在此处输入图片说明

这就是实现。

请暂时忽略 iOS 的组件与 Android 的组件几乎相同,除了 View 的样式。我正在用不同的组件进行其他测试,目前我可以让它们保持这样。两个组件(iOS / Android)的区别在于样式,因为在iOS中是zIndex有效的,而在Android中我必须使用elevation重叠视图。

const showSecurityScreenFromAppState = appState =>
    ['background', 'inactive'].includes(appState);

const withSecurityScreenIOS = Wrapped => {
    return class WithSecurityScreen extends React.Component {
        constructor(props) {
            super(props);
        }

        state = {
            showSecurityScreen: showSecurityScreenFromAppState(AppState.currentState),
        };

        componentDidMount() {
            AppState.addEventListener('change', this.onChangeAppState);
        }

        componentWillUnmount() {
            AppState.removeEventListener('change', this.onChangeAppState);
        }

        onChangeAppState = nextAppState => {
            const showSecurityScreen = showSecurityScreenFromAppState(nextAppState);

            this.setState({showSecurityScreen});
        };

        //this.state.showSecurityScreen
        render() {
            return (
                <>
                    <View style={[styles.container, {zIndex: this.state.showSecurityScreen ? 1 : -1}]}>
                        <View style={{flex: 1, backgroundColor: globalStyles.colors.customerGreen}}>
                            <View style={styles.upperView}>
                                <Text style={styles.upperViewText}>MyApp</Text>
                            </View>
                        </View>
                    </View>
                    <Wrapped {...this.props}/>
                </>
            );
        }
    };
};

const withSecurityScreenAndroid = Wrapped => {
    return class WithSecurityScreen extends React.Component {
        constructor(props) {
            super(props);
        }

        state = {
            showSecurityScreen: showSecurityScreenFromAppState(AppState.currentState),
        };

        componentDidMount() {
            AppState.addEventListener('change', this.onChangeAppState);
        }

        componentWillUnmount() {
            AppState.removeEventListener('change', this.onChangeAppState);
        }

        onChangeAppState = nextAppState => {
            const showSecurityScreen = showSecurityScreenFromAppState(nextAppState);

            this.setState({showSecurityScreen});
        };

        //this.state.showSecurityScreen
        render() {
            return (
                <>
                    <View style={[styles.container, {elevation: this.state.showSecurityScreen ? 1 : -1}]}>
                        <View style={{flex: 1, backgroundColor: globalStyles.colors.customerGreen}}>
                            <View style={styles.upperView}>
                                <Text style={styles.upperViewText}>MyApp</Text>
                            </View>
                        </View>
                    </View>
                    <Wrapped {...this.props}/>
                </>
            );
        }
    };
};

export const withSecurityScreen =
    Platform.OS === 'ios' ? withSecurityScreenIOS : withSecurityScreenAndroid;
Run Code Online (Sandbox Code Playgroud)

代码没有问题,它在iOS上运行得很好,但在Android上有时可以,有时不可以。我怀疑原因是Android操作系统,当按下方形按钮时,它会截取当前视图的屏幕截图并将其用作应用程序的背景图像。然而,有时层(海拔)的变化会比 Android 屏幕截图更快,因此我可以在背景中看到绿屏,因为 Android 将其用作图像。

有没有办法同步这些操作?也就是说:我可以确保当我按下方形按钮时,Android 等待视图更改然后让它在后台运行吗?

注意:我已经测试了应用程序在前台时高程的功能,只需反转elevation它在后台或前台时的值,我保证它elevation可以正常工作。

注意:在下面的动画中,当后台任务中的视图为白色时,是失败的。当 View 在背景中变成绿色时,就成功了。为什么是随机的?

在此处输入图片说明


更新 1

我现在意识到这个问题可能设置得很糟糕。

首先,我使用了错误的术语来指代应用程序的后台状态,我在 Android 中所说的视图称为最近的应用程序(或任务视图)。然后,其次,在最近的应用程序(任务视图)中,Android 做了什么,按下方形或圆形按钮后,当前视图的屏幕截图,然后显示任务视图,用作我的应用程序的图像,他刚刚做的屏幕截图. 这个问题很烦人,因为(如上面的 GIF 所示)有时屏幕截图是在更改视图后完成的。有时(并且经常)屏幕截图发生在视图更改之前(绿色的)。

这就是为什么有时在任务视图中我看到蓝屏,有时看到绿屏。比方说,这几乎是一个竞争问题。我的方法可能不合适,我应该另找一个。是否可以为我的应用手动更改任务视图中使用的图像?

Fat*_*mir 0

我有同样的问题...我尝试了我找到的所有方法,但没有成功。最终,我采用了使用活动生命周期来更改窗口标志的本机解决方案。

@Override
protected void onPause() {
    super.onPause();
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
}

@Override
protected void onResume() {
    super.onResume();
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
Run Code Online (Sandbox Code Playgroud)