| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 6d61ffc commit 06ea22d
14 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -17,7 +17,7 @@ PythonNative maps Python directly to native platform APIs. Conceptually, it is c | |||
| 17 | 17 | ||
| 18 | 18 | ## iOS flow (Rubicon-ObjC) | |
| 19 | 19 | ||
| 20 | - - The iOS template (Swift + PythonKit) boots Python and calls your bootstrap(native_instance) with the UIViewController pointer. | ||
| 20 | + - The iOS template (Swift + PythonKit) boots Python and instantiates your `MainPage` with the current `UIViewController` pointer. | ||
| 21 | 21 | - In Python, Rubicon wraps the pointer; you then interact with UIKit classes directly. | |
| 22 | 22 | ||
| 23 | 23 | ```python | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -18,7 +18,7 @@ This scaffolds: | |||
| 18 | 18 | - `requirements.txt` | |
| 19 | 19 | - `.gitignore` | |
| 20 | 20 | ||
| 21 | - A minimal `app/main_page.py` looks like: | ||
| 21 | + A minimal `app/main_page.py` looks like (no bootstrap needed): | ||
| 22 | 22 | ||
| 23 | 23 | ```python | |
| 24 | 24 | import pythonnative as pn | |
@@ -36,13 +36,6 @@ class MainPage(pn.Page): | |||
| 36 | 36 | button.set_on_click(lambda: print("Button clicked")) | |
| 37 | 37 | stack.add_view(button) | |
| 38 | 38 | self.set_root_view(stack) | |
| 39 | - | ||
| 40 | - | ||
| 41 | - def bootstrap(native_instance): | ||
| 42 | - """Entry point called by the host app (Activity or ViewController).""" | ||
| 43 | - page = MainPage(native_instance) | ||
| 44 | - page.on_create() | ||
| 45 | - return page | ||
| 46 | 39 | ``` | |
| 47 | 40 | ||
| 48 | 41 | ## Run on a platform | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,55 @@ | |||
| 1 | + # Navigation | ||
| 2 | + | ||
| 3 | + This guide shows how to navigate between pages and handle lifecycle events. | ||
| 4 | + | ||
| 5 | + ## Push / Pop | ||
| 6 | + | ||
| 7 | + Use `push` and `pop` on your `Page` to change screens. You can pass a dotted path string or a class reference. | ||
| 8 | + | ||
| 9 | + ```python | ||
| 10 | + import pythonnative as pn | ||
| 11 | + | ||
| 12 | + class MainPage(pn.Page): | ||
| 13 | + def on_create(self): | ||
| 14 | + stack = pn.StackView() | ||
| 15 | + btn = pn.Button("Go next") | ||
| 16 | + btn.set_on_click(lambda: self.push("app.second_page.SecondPage", args={"message": "Hello"})) | ||
| 17 | + stack.add_view(btn) | ||
| 18 | + self.set_root_view(stack) | ||
| 19 | + ``` | ||
| 20 | + | ||
| 21 | + On the target page: | ||
| 22 | + | ||
| 23 | + ```python | ||
| 24 | + class SecondPage(pn.Page): | ||
| 25 | + def on_create(self): | ||
| 26 | + args = self.get_args() | ||
| 27 | + message = args.get("message", "Second") | ||
| 28 | + stack = pn.StackView() | ||
| 29 | + stack.add_view(pn.Label(message)) | ||
| 30 | + back = pn.Button("Back") | ||
| 31 | + back.set_on_click(lambda: self.pop()) | ||
| 32 | + stack.add_view(back) | ||
| 33 | + self.set_root_view(stack) | ||
| 34 | + ``` | ||
| 35 | + | ||
| 36 | + ## Lifecycle | ||
| 37 | + | ||
| 38 | + PythonNative forwards lifecycle events from the host: | ||
| 39 | + | ||
| 40 | + - `on_create` | ||
| 41 | + - `on_start` | ||
| 42 | + - `on_resume` | ||
| 43 | + - `on_pause` | ||
| 44 | + - `on_stop` | ||
| 45 | + - `on_destroy` | ||
| 46 | + - `on_restart` (Android only) | ||
| 47 | + - `on_save_instance_state` | ||
| 48 | + - `on_restore_instance_state` | ||
| 49 | + | ||
| 50 | + Android forwards Activity lifecycle via the template `MainActivity` and `PageActivity`. iOS forwards `viewWillAppear`/`viewWillDisappear` via an internal registry. | ||
| 51 | + | ||
| 52 | + ## Notes | ||
| 53 | + | ||
| 54 | + - On Android, `push` launches a template `PageActivity` and passes `PY_PAGE_PATH` and optional JSON args. | ||
| 55 | + - On iOS, `push` uses the root `UINavigationController` to push a new `ViewController` and passes page info via KVC. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -22,8 +22,20 @@ def on_create(self): | |||
| 22 | 22 | except Exception: | |
| 23 | 23 | pass | |
| 24 | 24 | stack.add_view(pn.Label("Hello from PythonNative Demo!")) | |
| 25 | - button = pn.Button("Tap me") | ||
| 26 | - button.set_on_click(lambda: print("Demo button clicked")) | ||
| 25 | + button = pn.Button("Go to Second Page") | ||
| 26 | + | ||
| 27 | + def on_next(): | ||
| 28 | + # Visual confirmation that tap worked (iOS only) | ||
| 29 | + try: | ||
| 30 | + if UIColor is not None: | ||
| 31 | + button.native_instance.setBackgroundColor_(UIColor.systemGreenColor()) | ||
| 32 | + button.native_instance.setTitleColor_forState_(UIColor.whiteColor(), 0) | ||
| 33 | + except Exception: | ||
| 34 | + pass | ||
| 35 | + # Demonstrate passing args | ||
| 36 | + self.push("app.second_page.SecondPage", args={"message": "Greetings from MainPage"}) | ||
| 37 | + | ||
| 38 | + button.set_on_click(on_next) | ||
| 27 | 39 | # Make the button visually obvious | |
| 28 | 40 | try: | |
| 29 | 41 | if UIColor is not None: | |
@@ -57,9 +69,3 @@ def on_save_instance_state(self): | |||
| 57 | 69 | ||
| 58 | 70 | def on_restore_instance_state(self): | |
| 59 | 71 | super().on_restore_instance_state() | |
| 60 | - | ||
| 61 | - | ||
| 62 | - def bootstrap(native_instance): | ||
| 63 | - page = MainPage(native_instance) | ||
| 64 | - page.on_create() | ||
| 65 | - return page | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -8,8 +8,13 @@ def __init__(self, native_instance): | |||
| 8 | 8 | def on_create(self): | |
| 9 | 9 | super().on_create() | |
| 10 | 10 | stack_view = pn.StackView() | |
| 11 | - label = pn.Label("Second page!") | ||
| 12 | - stack_view.add_view(label) | ||
| 11 | + # Read args passed from MainPage | ||
| 12 | + args = self.get_args() | ||
| 13 | + message = args.get("message", "Second page!") | ||
| 14 | + stack_view.add_view(pn.Label(message)) | ||
| 15 | + back_btn = pn.Button("Back") | ||
| 16 | + back_btn.set_on_click(lambda: self.pop()) | ||
| 17 | + stack_view.add_view(back_btn) | ||
| 13 | 18 | self.set_root_view(stack_view) | |
| 14 | 19 | ||
| 15 | 20 | def on_start(self): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -23,6 +23,7 @@ nav: | |||
| 23 | 23 | - Guides: | |
| 24 | 24 | - Android: guides/android.md | |
| 25 | 25 | - iOS: guides/ios.md | |
| 26 | + - Navigation: guides/navigation.md | ||
| 26 | 27 | - API Reference: | |
| 27 | 28 | - Package: api/pythonnative.md | |
| 28 | 29 | - Meta: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -41,7 +41,7 @@ def init_project(args: argparse.Namespace) -> None: | |||
| 41 | 41 | ||
| 42 | 42 | os.makedirs(app_dir, exist_ok=True) | |
| 43 | 43 | ||
| 44 | - # Minimal hello world app scaffold | ||
| 44 | + # Minimal hello world app scaffold (no bootstrap function; host instantiates Page directly) | ||
| 45 | 45 | main_page_py = os.path.join(app_dir, "main_page.py") | |
| 46 | 46 | if not os.path.exists(main_page_py) or args.force: | |
| 47 | 47 | with open(main_page_py, "w", encoding="utf-8") as f: | |
@@ -61,13 +61,6 @@ def on_create(self): | |||
| 61 | 61 | button.set_on_click(lambda: print("Button clicked")) | |
| 62 | 62 | stack.add_view(button) | |
| 63 | 63 | self.set_root_view(stack) | |
| 64 | - | ||
| 65 | - | ||
| 66 | - def bootstrap(native_instance): | ||
| 67 | - '''Entry point called by the host app (Android Activity or iOS ViewController).''' | ||
| 68 | - page = MainPage(native_instance) | ||
| 69 | - page.on_create() | ||
| 70 | - return page | ||
| 71 | 64 | """ | |
| 72 | 65 | ) | |
| 73 | 66 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments