React Native 如何更改视图之前,Android应用程序被置于后台?

6qqygrtg  于 2023-02-24  发布在  React
关注(0)|答案(2)|浏览(146)

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

下图是我将App置于后台状态时,目前得到的结果:

下面一个是我想做的应用程序放在后台时(在iOS上的作品,在Android上不那么好):

这就是实现。
请暂时忽略iOS的组件几乎与Android的组件相同,除了视图的风格。我正在使用不同的组件进行其他测试,目前我可以保持它们这样。两个组件之间的差异(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;

代码没有问题,在iOS上运行得非常好,但是在Android上时有时无,我怀疑原因是Android OS,按下方形按钮时,会截图当前视图,并将其作为App的背景图像,不过有时候,碰巧层(海拔)的变化比Android屏幕截图更快,因此我可以看到背景中的绿色屏幕,因为Android将其用作图像。
是否有同步这些操作的方法?即:我可以确保当我按下方形按钮时,Android会等待视图更改,然后让它在后台运行吗?
注:我已经测试了应用程序在前台时的高程功能,当它在后台或前台时,只需反转elevation的值,我保证elevation工作正常。
注意:在下面的动画中,当后台任务的视图为白色时,表示失败。当后台任务的视图变为绿色时,表示成功。为什么是随机的?

更新1

我现在意识到问题可能出得不好。
首先,我使用了不正确的术语来指代应用程序的后台状态,我在Android中提到的视图被称为最近的应用程序(或任务视图)。其次,在最近的应用程序中(任务视图)Android做什么,按下方形或圆形按钮后,当前视图的屏幕截图,然后显示任务视图,用作我的应用程序的图像,他刚刚做的截图。这个问题相当烦人,因为(如上面的GIF所示)有时截图是在视图更改之后做的。有时相反(而且经常)截图发生在视图更改之前(绿色的那个)。
这就是为什么有时在任务视图中我看到蓝屏,有时看到绿色屏。这几乎是一个竞争问题,让我们说。我的方法可能不适合,我应该找到另一个。是否可以手动更改我的应用程序在任务视图中使用的图像?

9gm1akwq

9gm1akwq1#

你可以这样尝试:

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

        this.setState({showSecurityScreen});
    };
sauutmhj

sauutmhj2#

我也有同样的问题......我尝试了所有找到的方法,但都不起作用。最后,我选择了一个使用活动生命周期来更改窗口标志的本地解决方案。

@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);
}

相关问题