pythonnative 0.13.1__py3-none-any.whl → 0.14.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pythonnative/__init__.py CHANGED
@@ -41,7 +41,7 @@ Example:
41
41
  ```
42
42
  """
43
43
 
44
- __version__ = "0.13.1"
44
+ __version__ = "0.14.0"
45
45
 
46
46
  from .alerts import Alert
47
47
  from .animated import Animated, AnimatedValue
@@ -1116,10 +1116,41 @@ class TabBarHandler(AndroidViewHandler):
1116
1116
  menu.clear()
1117
1117
  for i, item in enumerate(items):
1118
1118
  title = item.get("title", item.get("name", ""))
1119
- menu.add(0, i, i, str(title))
1119
+ menu_item = menu.add(0, i, i, str(title))
1120
+ res_id = self._resolve_icon(item.get("icon"))
1121
+ if res_id:
1122
+ try:
1123
+ menu_item.setIcon(res_id)
1124
+ except Exception:
1125
+ pass
1120
1126
  except Exception:
1121
1127
  pass
1122
1128
 
1129
+ def _resolve_icon(self, icon: Any) -> int:
1130
+ """Resolve a tab icon spec to an `android.R.drawable.*` res id.
1131
+
1132
+ Accepts a bare string (treated as the drawable's field name on
1133
+ ``android.R.drawable``) or a dict of the form
1134
+ ``{"ios": "...", "android": "ic_menu_home"}``. Returns ``0``
1135
+ when the icon can't be resolved, which the caller treats as
1136
+ "no icon".
1137
+ """
1138
+ if icon is None:
1139
+ return 0
1140
+ name: Any = None
1141
+ if isinstance(icon, str):
1142
+ name = icon
1143
+ elif isinstance(icon, dict):
1144
+ name = icon.get("android")
1145
+ if not name:
1146
+ return 0
1147
+ try:
1148
+ RDrawable = jclass("android.R$drawable")
1149
+ res_id = getattr(RDrawable, str(name), 0)
1150
+ return int(res_id) if res_id else 0
1151
+ except Exception:
1152
+ return 0
1153
+
1123
1154
  def _set_active(self, bnv: Any, active: Any, items: list) -> None:
1124
1155
  if active and items:
1125
1156
  for i, item in enumerate(items):
@@ -2345,13 +2345,38 @@ class TabBarHandler(IOSViewHandler):
2345
2345
 
2346
2346
  def _set_bar_items(self, tab_bar: Any, items: list) -> None:
2347
2347
  UITabBarItem = ObjCClass("UITabBarItem")
2348
+ UIImage = ObjCClass("UIImage")
2348
2349
  bar_items = []
2349
2350
  for i, item in enumerate(items):
2350
2351
  title = item.get("title", item.get("name", ""))
2351
- bar_item = UITabBarItem.alloc().initWithTitle_image_tag_(str(title), None, i)
2352
+ image = self._resolve_icon(UIImage, item.get("icon"))
2353
+ bar_item = UITabBarItem.alloc().initWithTitle_image_tag_(str(title), image, i)
2352
2354
  bar_items.append(bar_item)
2353
2355
  tab_bar.setItems_animated_(bar_items, False)
2354
2356
 
2357
+ def _resolve_icon(self, UIImage: Any, icon: Any) -> Any:
2358
+ """Resolve a tab icon spec to a UIImage, or return None.
2359
+
2360
+ Accepts a bare string (treated as an SF Symbol name) or a dict
2361
+ of the form ``{"ios": "house.fill", "android": "..."}``. SF
2362
+ Symbols are looked up via ``UIImage.systemImageNamed:``; names
2363
+ that don't resolve produce a text-only tab.
2364
+ """
2365
+ if icon is None:
2366
+ return None
2367
+ name: Any = None
2368
+ if isinstance(icon, str):
2369
+ name = icon
2370
+ elif isinstance(icon, dict):
2371
+ name = icon.get("ios")
2372
+ if not name:
2373
+ return None
2374
+ try:
2375
+ image = UIImage.systemImageNamed_(str(name))
2376
+ return image if image else None
2377
+ except Exception:
2378
+ return None
2379
+
2355
2380
  def _set_active(self, tab_bar: Any, active: Any, items: list) -> None:
2356
2381
  if not active or not items:
2357
2382
  return
@@ -570,10 +570,14 @@ def _tab_navigator_impl(screens: Any = None, initial_route: Optional[str] = None
570
570
  if screen_def is None:
571
571
  screen_def = screen_map[screen_list[0].name]
572
572
 
573
- tab_items: List[Dict[str, str]] = []
573
+ tab_items: List[Dict[str, Any]] = []
574
574
  for s in screen_list:
575
575
  if isinstance(s, _ScreenDef):
576
- tab_items.append({"name": s.name, "title": s.options.get("title", s.name)})
576
+ item: Dict[str, Any] = {"name": s.name, "title": s.options.get("title", s.name)}
577
+ icon = s.options.get("tab_bar_icon")
578
+ if icon is not None:
579
+ item["icon"] = icon
580
+ tab_items.append(item)
577
581
 
578
582
  def on_tab_select(name: str) -> None:
579
583
  switch_tab(name)
@@ -639,8 +643,17 @@ def create_tab_navigator() -> Any:
639
643
  name: Route name and default tab title.
640
644
  component: A `@component` function rendered when this
641
645
  tab is active.
642
- options: Optional per-screen settings (e.g.,
643
- `{"title": "..."}`).
646
+ options: Optional per-screen settings. Recognized keys:
647
+
648
+ - `title` (str): Tab label.
649
+ - `tab_bar_icon` (str | dict): Native system icon
650
+ identifier. A string is used on every platform; a
651
+ dict like `{"ios": "house.fill", "android":
652
+ "ic_menu_home"}` selects per platform. iOS values
653
+ are resolved via SF Symbols
654
+ (`UIImage.systemImageNamed_`); Android values are
655
+ resolved against `android.R.drawable.<name>`.
656
+ Names that don't resolve fall back to text-only.
644
657
 
645
658
  Returns:
646
659
  A `_ScreenDef` consumed by `Navigator(...)`.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pythonnative
3
- Version: 0.13.1
3
+ Version: 0.14.0
4
4
  Summary: Cross-platform native UI toolkit for Android and iOS
5
5
  Author: Owen Carey
6
6
  License: MIT License
@@ -1,4 +1,4 @@
1
- pythonnative/__init__.py,sha256=hALoQQgBMyIeVuBzfTpxPhB16HBJpiG0Hw6MhiiDueE,4121
1
+ pythonnative/__init__.py,sha256=UWwcP6GyJyrIY7M3dd9zlYGLuFRql5MAEz1UB7lljvU,4121
2
2
  pythonnative/_ios_log.py,sha256=Oi7V28VxcVoZyrpAirvLeEmUW18McqnU87V4d37Zzlw,2582
3
3
  pythonnative/alerts.py,sha256=uU_b1rHGyxm1_hUzXhmTiB85oe7PZ0pWcWSzL9NVKYY,3588
4
4
  pythonnative/animated.py,sha256=0H3y7ZAtS4Lu9hqvCz1LTCORep57kb6S9ebyRoxO6-A,22051
@@ -7,7 +7,7 @@ pythonnative/element.py,sha256=W9varJj0Cl9HpckL8BcsC1u4ryUQOPVMrvetro4ilAE,2725
7
7
  pythonnative/hooks.py,sha256=j2FX7-66a-TK9ZlUsgoRyY8A484UgBzUJavGxaupgaI,27451
8
8
  pythonnative/hot_reload.py,sha256=j7z2c7o2Hdoyd-p4nQY15LTW7CBH_1z0TSAzLCer-aA,25036
9
9
  pythonnative/layout.py,sha256=-Wrvj4eHtQXqa9kn26ktKLAZVH4VMc_WuoCxV67UnQw,34994
10
- pythonnative/navigation.py,sha256=Ck728YpOWagjUyYcCDMpN9-kYXiseWhV7an3EvGvUCI,32564
10
+ pythonnative/navigation.py,sha256=BtmdAKHocAF3ub7PewkGJYn8Rxy3GdV3serYnU0TMWk,33282
11
11
  pythonnative/platform.py,sha256=jEya1KTDc3WfwpmrQkk3DIFyt7CWO4Vc3pej_wDiSR8,4629
12
12
  pythonnative/platform_metrics.py,sha256=m2u8M8x52n5THNsYdspcaI9mlWWMbfSJWai1svjD0NM,8976
13
13
  pythonnative/reconciler.py,sha256=4z-55fYkQJlCqtxfDGlrI8MY2KxXgZxsJSB20d42acw,37898
@@ -22,9 +22,9 @@ pythonnative/native_modules/file_system.py,sha256=NOaz1pM0XL3Ptu0Agg4v2XcsO8SLuO
22
22
  pythonnative/native_modules/location.py,sha256=Z4LBPphh20gwY88gxXkBfiJXXqFrFfiXQjDpjUNSTgE,8397
23
23
  pythonnative/native_modules/notifications.py,sha256=OIKleiiXXKscWTuobG9DTx18rxpIMLIFcTceSYgAgFY,6639
24
24
  pythonnative/native_views/__init__.py,sha256=N4XS-spTLWuWeyPcGwY7ZHIP2jhqXYTHZIfsni8I_Eg,9989
25
- pythonnative/native_views/android.py,sha256=hj_hI3V8y4yVL8QDoqdRYdO75aL_ugcUD3v9F4YAGD8,63116
25
+ pythonnative/native_views/android.py,sha256=jedaq4PzmUw2Fyqy8H9l-xmiT7thxTGm2da8J2NEy-0,64235
26
26
  pythonnative/native_views/base.py,sha256=84YLJDouGcEvAZlfwBicv-DesRDnfkw1Go1t7udw6jM,8965
27
- pythonnative/native_views/ios.py,sha256=w9bD0MURBgz7m8seoW7ZgyuAkfosV1kewJWvkklz64E,95491
27
+ pythonnative/native_views/ios.py,sha256=nyQ61pZ6ATfePxvTOrNAqTBA1ZHObKg_IHcWK3zWWzY,96412
28
28
  pythonnative/templates/android_template/build.gradle,sha256=4gE6CRS6RuBu9kp-_e_uYYU9mBgHVZrqQg9caSxgyuc,352
29
29
  pythonnative/templates/android_template/gradle.properties,sha256=REPaKLRfQiiVfIV8wYmgwzPWvF1f3bhh_kAMV9p4HME,1358
30
30
  pythonnative/templates/android_template/gradlew,sha256=YxNShxF6Hm0SyEWA8fScYdG6AiGOzShmBgXpf5dufWU,5766
@@ -77,9 +77,9 @@ pythonnative/templates/ios_template/ios_template.xcodeproj/project.xcworkspace/x
77
77
  pythonnative/templates/ios_template/ios_templateTests/ios_templateTests.swift,sha256=YnwzZx7yXB13xKAXEGNgz17VuhWeqkHTRTtBJ2Vu3_E,1238
78
78
  pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITests.swift,sha256=l2Pwa50F_rv-qPu2go6e4bQernM6PTQJeNPFl_c4ivY,1387
79
79
  pythonnative/templates/ios_template/ios_templateUITests/ios_templateUITestsLaunchTests.swift,sha256=f5JrG0uVtLMeJQy26Yyz7Om-JUkT220osqcbeIVkj2g,815
80
- pythonnative-0.13.1.dist-info/licenses/LICENSE,sha256=A69iG7TIAe6KkGQf6xoVHkc5JSZtOr5eRSvC5iuivnI,1067
81
- pythonnative-0.13.1.dist-info/METADATA,sha256=bcCREnUWDUOImi6EDGHcSozns4lYcnwNujtrYSW_y50,7453
82
- pythonnative-0.13.1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
83
- pythonnative-0.13.1.dist-info/entry_points.txt,sha256=iUtDawWSAJAEyWTycpZxDuYz73ol31butpzDIEAgPO0,48
84
- pythonnative-0.13.1.dist-info/top_level.txt,sha256=kT4SEATY2ywzrZ2Pgea6_zxyym44Q_PbOsUoOYjJLFE,13
85
- pythonnative-0.13.1.dist-info/RECORD,,
80
+ pythonnative-0.14.0.dist-info/licenses/LICENSE,sha256=A69iG7TIAe6KkGQf6xoVHkc5JSZtOr5eRSvC5iuivnI,1067
81
+ pythonnative-0.14.0.dist-info/METADATA,sha256=OF1hl45kye50u38UrjPwmqDwWF2SatVWqucH4XlasWg,7453
82
+ pythonnative-0.14.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
83
+ pythonnative-0.14.0.dist-info/entry_points.txt,sha256=iUtDawWSAJAEyWTycpZxDuYz73ol31butpzDIEAgPO0,48
84
+ pythonnative-0.14.0.dist-info/top_level.txt,sha256=kT4SEATY2ywzrZ2Pgea6_zxyym44Q_PbOsUoOYjJLFE,13
85
+ pythonnative-0.14.0.dist-info/RECORD,,