Bladeren bron

feat(navigation): 实现基础导航功能

- 新增 NavigationHelper、NavigationManager 和 AppManager 类
- 实现 navigate 和 pop 方法
- 添加 MainActivity 和 BuzActivity 作为导航示例
- 更新 App.tsx,添加导航按钮
- 新增互联网医院模块作为导航目标
xuqm 1 week geleden
bovenliggende
commit
da6c39d068

+ 19 - 18
android/app/src/main/AndroidManifest.xml

@@ -3,24 +3,25 @@
     <uses-permission android:name="android.permission.INTERNET" />
 
     <application
-      android:name=".MainApplication"
-      android:label="@string/app_name"
-      android:icon="@mipmap/ic_launcher"
-      android:roundIcon="@mipmap/ic_launcher_round"
-      android:allowBackup="false"
-      android:theme="@style/AppTheme"
-      android:supportsRtl="true">
-      <activity
-        android:name=".MainActivity"
+        android:name=".MainApplication"
+        android:allowBackup="false"
+        android:icon="@mipmap/ic_launcher"
         android:label="@string/app_name"
-        android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
-        android:launchMode="singleTask"
-        android:windowSoftInputMode="adjustResize"
-        android:exported="true">
-        <intent-filter>
-            <action android:name="android.intent.action.MAIN" />
-            <category android:name="android.intent.category.LAUNCHER" />
-        </intent-filter>
-      </activity>
+        android:roundIcon="@mipmap/ic_launcher_round"
+        android:supportsRtl="true"
+        android:theme="@style/AppTheme">
+        <activity
+            android:name=".MainActivity"
+            android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
+            android:exported="true"
+            android:label="@string/app_name"
+            android:launchMode="singleTask"
+            android:windowSoftInputMode="adjustResize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity android:name="com.trust.ywx.BuzActivity" />
     </application>
 </manifest>

+ 31 - 0
android/app/src/main/java/com/trust/ywx/AppManager.kt

@@ -0,0 +1,31 @@
+package com.trust.ywx
+
+import android.app.Activity
+import java.util.Stack
+
+object AppManager {
+    private val activityStack: Stack<Activity> = Stack()
+    fun addActivity(activity: Activity) {
+        activityStack.add(activity)
+    }
+
+    fun removeActivity(activity: Activity) {
+        activityStack.remove(activity)
+    }
+
+    fun finishActivity(activity: Activity?) {
+        if (activity != null) {
+            removeActivity(activity)
+            activity.finish()
+        } else {
+            lastActivity()?.apply {
+                removeActivity(this)
+                this.finish()
+            }
+        }
+    }
+
+    fun lastActivity(): Activity? {
+        return activityStack.lastElement()
+    }
+}

+ 34 - 0
android/app/src/main/java/com/trust/ywx/BuzActivity.kt

@@ -0,0 +1,34 @@
+package com.trust.ywx
+
+import android.os.Bundle
+import com.facebook.react.ReactActivity
+import com.trust.ywx.specs.navigation.NavigationHelper
+import com.facebook.react.ReactActivityDelegate
+import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
+import com.facebook.react.defaults.DefaultReactActivityDelegate
+
+class BuzActivity : ReactActivity() {
+
+    /**
+     * Returns the name of the main component registered from JavaScript. This is used to schedule
+     * rendering of the component.
+     */
+    override fun getMainComponentName(): String = NavigationHelper.routerName
+
+    /**
+     * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
+     * which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
+     */
+    override fun createReactActivityDelegate(): ReactActivityDelegate =
+        DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        AppManager.addActivity(this)
+    }
+
+    override fun onDestroy() {
+        AppManager.removeActivity(this)
+        super.onDestroy()
+    }
+}

+ 11 - 19
android/app/src/main/java/com/trust/ywx/MainActivity.kt

@@ -1,22 +1,14 @@
 package com.trust.ywx
 
-import com.facebook.react.ReactActivity
-import com.facebook.react.ReactActivityDelegate
-import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
-import com.facebook.react.defaults.DefaultReactActivityDelegate
-
-class MainActivity : ReactActivity() {
-
-  /**
-   * Returns the name of the main component registered from JavaScript. This is used to schedule
-   * rendering of the component.
-   */
-  override fun getMainComponentName(): String = "app"
-
-  /**
-   * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate]
-   * which allows you to enable New Architecture with a single boolean flags [fabricEnabled]
-   */
-  override fun createReactActivityDelegate(): ReactActivityDelegate =
-      DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
+import android.content.Intent
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import com.trust.ywx.specs.navigation.NavigationHelper
+
+class MainActivity : AppCompatActivity() {
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        NavigationHelper.routerName = "app"
+        startActivity(Intent(this, BuzActivity::class.java))
+    }
 }

+ 23 - 0
android/app/src/main/java/com/trust/ywx/specs/NavigationManager.kt

@@ -0,0 +1,23 @@
+package com.trust.ywx.specs
+
+
+import android.content.Intent
+import com.facebook.react.bridge.ReactApplicationContext
+import com.trust.ywx.AppManager
+import com.trust.ywx.BuzActivity
+import com.trust.ywx.specs.NativeNavigationManagerSpec
+import com.trust.ywx.specs.navigation.NavigationHelper
+
+class NavigationManager(reactContext: ReactApplicationContext) :
+    NativeNavigationManagerSpec(reactContext) {
+    override fun navigate(name: String) {
+        NavigationHelper.routerName = name
+        AppManager.lastActivity()
+            ?.startActivity(Intent(AppManager.lastActivity(), BuzActivity::class.java))
+    }
+
+    override fun pop(name: String?) {
+
+    }
+
+}

+ 5 - 0
android/app/src/main/java/com/trust/ywx/specs/navigation/NavigationHelper.kt

@@ -0,0 +1,5 @@
+package com.trust.ywx.specs.navigation
+
+object NavigationHelper {
+    var routerName: String = "app"
+}

+ 6 - 0
android/app/src/main/res/layout/activity_main.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+</LinearLayout>

+ 2 - 3
package.json

@@ -14,14 +14,13 @@
     "build-android-hospital": "react-native bundle --platform android --dev false --entry-file src/hospital/hospital.ts --bundle-output ./bundle/hospital.android.bundle --assets-dest ./bundle   --config metro.main.config.js  --minify true --reset-cache"
   },
   "codegenConfig": {
-    "name": "SpecsManager",
+    "name": "SpecManager",
     "type": "modules",
-    "jsSrcsDir": "./src/specs",
+    "jsSrcsDir": "specs",
     "android": {
       "javaPackageName": "com.trust.ywx.specs"
     }
   },
-
   "dependencies": {
     "@react-native-async-storage/async-storage": "^2.2.0",
     "@react-native/new-app-screen": "0.80.1",

+ 0 - 0
src/specs/SpecsManager.ts → specs/NativeNavigationManager.ts


+ 1 - 0
specs/README.md

@@ -0,0 +1 @@
+# 文件名必须`Native`开头

+ 15 - 3
src/app/App.tsx

@@ -5,8 +5,14 @@
  * @format
  */
 
-import { NewAppScreen } from '@react-native/new-app-screen';
-import { StatusBar, StyleSheet, useColorScheme, View } from 'react-native';
+import {
+  Button,
+  StatusBar,
+  StyleSheet,
+  useColorScheme,
+  View,
+} from 'react-native';
+import { pushByName } from '../common/NavigationHelper.ts';
 
 function App() {
   const isDarkMode = useColorScheme() === 'dark';
@@ -14,7 +20,13 @@ function App() {
   return (
     <View style={styles.container}>
       <StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
-      <NewAppScreen templateFileName="App.tsx" />
+      <View style={{ height: 100 }} />
+      <Button
+        title={'进入互联网医院'}
+        onPress={() => {
+          pushByName('hospital', {});
+        }}
+      />
     </View>
   );
 }

+ 7 - 2
src/common/NavigationHelper.ts

@@ -1,10 +1,10 @@
 import { storageApp } from './StorageHelper.ts';
-import NavigationManager from '../specs/SpecsManager.ts';
+import NavigationManager from '../../specs/NativeNavigationManager.ts';
 
 export const pushByName = (name: string, params: any) => {
   storageApp
     .save({
-      key: 'MessageActivity',
+      key: `MessageActivity_${name}`,
       data: params,
       expires: 1000 * 3600,
     })
@@ -12,3 +12,8 @@ export const pushByName = (name: string, params: any) => {
       NavigationManager.navigate(name);
     });
 };
+export const pop = (name: string) => {
+  storageApp.remove({ key: `MessageActivity_${name}` }).finally(() => {
+    NavigationManager.pop(name);
+  });
+};

+ 1 - 0
src/common/common.ts

@@ -1,2 +1,3 @@
 import  'react';
 import  'react-native';
+import  './NavigationHelper';

+ 41 - 0
src/hospital/Hospital.tsx

@@ -0,0 +1,41 @@
+/**
+ * Sample React Native App
+ * https://github.com/facebook/react-native
+ *
+ * @format
+ */
+
+import {
+  Button,
+  StatusBar,
+  StyleSheet,
+  useColorScheme,
+  View,
+} from 'react-native';
+import { pop } from '../common/NavigationHelper.ts';
+
+function Hospital() {
+  const isDarkMode = useColorScheme() === 'dark';
+
+  return (
+    <View style={styles.container}>
+      <StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
+      <View style={{ height: 100 }} />
+      <View>互联网医院</View>
+      <Button
+        title={'返回'}
+        onPress={() => {
+          pop('hospital');
+        }}
+      />
+    </View>
+  );
+}
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+  },
+});
+
+export default Hospital;

+ 4 - 0
src/hospital/hospital.ts

@@ -0,0 +1,4 @@
+import { AppRegistry } from 'react-native';
+import Hospital from './Hospital.tsx';
+
+AppRegistry.registerComponent('hospital', () => Hospital);