From bc2eefbc346b3514da53574bd4a3a64f5c9ad70e Mon Sep 17 00:00:00 2001 From: Michael Gangolf Date: Sat, 22 Mar 2025 11:53:10 +0100 Subject: [PATCH 1/8] feat(android): parity for Ti.UI.VIew clipMode --- .../java/ti/modules/titanium/ui/UIModule.java | 7 ++++++ .../java/org/appcelerator/titanium/TiC.java | 1 + .../appcelerator/titanium/view/TiUIView.java | 10 +++++++++ apidoc/Titanium/UI/View.yml | 22 ++++++++++--------- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/android/modules/ui/src/java/ti/modules/titanium/ui/UIModule.java b/android/modules/ui/src/java/ti/modules/titanium/ui/UIModule.java index 19d77525a1f..b4f23e88b7a 100644 --- a/android/modules/ui/src/java/ti/modules/titanium/ui/UIModule.java +++ b/android/modules/ui/src/java/ti/modules/titanium/ui/UIModule.java @@ -436,6 +436,13 @@ public class UIModule extends KrollModule implements TiApplication.Configuration @Kroll.constant public static final int HIDDEN_BEHAVIOR_INVISIBLE = View.INVISIBLE; + @Kroll.constant + public static final int CLIP_MODE_DEFAULT = 0; + @Kroll.constant + public static final int CLIP_MODE_ENABLED = 1; + @Kroll.constant + public static final int CLIP_MODE_DISABLED = -1; + @Kroll.constant public static final int USER_INTERFACE_STYLE_LIGHT = Configuration.UI_MODE_NIGHT_NO; @Kroll.constant diff --git a/android/titanium/src/java/org/appcelerator/titanium/TiC.java b/android/titanium/src/java/org/appcelerator/titanium/TiC.java index 880971509cf..37c56bfb34f 100644 --- a/android/titanium/src/java/org/appcelerator/titanium/TiC.java +++ b/android/titanium/src/java/org/appcelerator/titanium/TiC.java @@ -362,6 +362,7 @@ public class TiC public static final String PROPERTY_CLASS_NAMES = "classNames"; public static final String PROPERTY_CLEAR_ON_EDIT = "clearOnEdit"; public static final String PROPERTY_CLIP_VIEWS = "clipViews"; + public static final String PROPERTY_CLIP_MODE = "clipMode"; public static final String PROPERTY_CODE = "code"; public static final String PROPERTY_COLOR = "color"; public static final String PROPERTY_COLUMNS = "columns"; diff --git a/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java b/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java index 73630f0c02a..d96de6d75a3 100644 --- a/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java +++ b/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java @@ -1141,6 +1141,16 @@ public void processProperties(KrollDict d) } } + if (d.containsKey(TiC.PROPERTY_CLIP_MODE) && !nativeViewNull) { + if (nativeView != null + && TiConvert.toInt(d, TiC.PROPERTY_CLIP_MODE) == -1 + && nativeView instanceof ViewGroup viewGroup + && viewGroup.getParent() == null) { + viewGroup.setClipChildren(false); + viewGroup.setClipToPadding(false); + } + } + if (!nativeViewNull && d.containsKeyAndNotNull(TiC.PROPERTY_TRANSITION_NAME)) { ViewCompat.setTransitionName(nativeView, d.getString(TiC.PROPERTY_TRANSITION_NAME)); } diff --git a/apidoc/Titanium/UI/View.yml b/apidoc/Titanium/UI/View.yml index 2233fe4011e..42337c02213 100644 --- a/apidoc/Titanium/UI/View.yml +++ b/apidoc/Titanium/UI/View.yml @@ -198,9 +198,9 @@ description: | The shadow of the view is drawn using a rounded rectangle with the arc radius set to the `borderRadius` property. The `clipMode` property lets the user control the clipping behavior of the View. - Setting this to enforces all child views to be clipped to this views bounds. - Setting this to allows child views to be drawn outside the bounds of this view. - When set to or when this property is not set, clipping behavior is defined by the following rules applied in order. + Setting this to enforces all child views to be clipped to this views bounds. + Setting this to allows child views to be drawn outside the bounds of this view. + When set to or when this property is not set, clipping behavior is defined by the following rules applied in order. * If the `viewShadowColor` is defined to be a color with alpha > 0, clipping is disabled. * If the `borderWidth` or `borderRadius` of the view is set to a value > 0, clipping is enabled. @@ -1431,15 +1431,17 @@ properties: - name: clipMode summary: View's clipping behavior. description: | - Setting this to enforces all child views to be clipped to this views bounds. - Setting this to allows child views to be drawn outside the bounds of this view. - When set to or when this property is not set, clipping behavior is inferred. - See section on iOS Clipping Behavior in . + Setting this to enforces all child views to be clipped to this views bounds. + Setting this to allows child views to be drawn outside the bounds of this view. + When set to or when this property is not set, clipping behavior is inferred. + See section on Clipping Behavior in . - Defaults to `undefined`. Behaves as if set to . + Android: This property is "creation only" and has to be on the top-level view. + + Defaults to `undefined`. Behaves as if set to . type: Number - platforms: [iphone, ipad, macos] - since: "3.3.0" + platforms: [android, iphone, ipad, macos] + since: {android: "12.7.0", iphone: "3.3.0", ipad: "3.3.0"} - name: elevation summary: Base elevation of the view relative to its parent in pixels. From 3cdd664b68829a30814770256614c856e8535249 Mon Sep 17 00:00:00 2001 From: Michael Gangolf Date: Sun, 6 Apr 2025 17:12:13 +0200 Subject: [PATCH 2/8] copy ios namespace --- iphone/Classes/UIModule.h | 4 ++++ iphone/Classes/UIModule.m | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/iphone/Classes/UIModule.h b/iphone/Classes/UIModule.h index 046ab93448a..2cd911a4cc4 100644 --- a/iphone/Classes/UIModule.h +++ b/iphone/Classes/UIModule.h @@ -233,6 +233,10 @@ @property (nonatomic, readonly) NSString *TEXT_STYLE_CALLOUT; @property (nonatomic, readonly) NSString *TEXT_STYLE_LARGE_TITLE; +@property (nonatomic, readonly) NSNumber *CLIP_MODE_DEFAULT; +@property (nonatomic, readonly) NSNumber *CLIP_MODE_ENABLED; +@property (nonatomic, readonly) NSNumber *CLIP_MODE_DISABLED; + - (id)createMatrix2D:(id)args; - (id)create2DMatrix:(id)args; // Deprecated since 8.0.0 - (id)createMatrix3D:(id)args; diff --git a/iphone/Classes/UIModule.m b/iphone/Classes/UIModule.m index 114792f1cfb..bfe80e8ba78 100644 --- a/iphone/Classes/UIModule.m +++ b/iphone/Classes/UIModule.m @@ -445,6 +445,18 @@ - (NSString *)TEXT_STYLE_LARGE_TITLE { return UIFontTextStyleLargeTitle; } +- (NSNumber *)CLIP_MODE_DEFAULT +{ + return NUMINT(0); +} +- (NSNumber *)CLIP_MODE_ENABLED +{ + return NUMINT(1); +} +- (NSNumber *)CLIP_MODE_DISABLED +{ + return NUMINT(-1); +} - (void)setOverrideUserInterfaceStyle:(id)args { From a8dba5b1f24701533fab8ab8b524103f0e85fad0 Mon Sep 17 00:00:00 2001 From: Michael Gangolf Date: Sun, 6 Apr 2025 17:18:45 +0200 Subject: [PATCH 3/8] deprecation info --- apidoc/Titanium/UI/iOS/iOS.yml | 9 +++++++++ iphone/Classes/TiUIiOSProxy.m | 3 +++ 2 files changed, 12 insertions(+) diff --git a/apidoc/Titanium/UI/iOS/iOS.yml b/apidoc/Titanium/UI/iOS/iOS.yml index 41209867667..19b972d6225 100644 --- a/apidoc/Titanium/UI/iOS/iOS.yml +++ b/apidoc/Titanium/UI/iOS/iOS.yml @@ -340,6 +340,9 @@ properties: type: Number permission: read-only since: "3.3.0" + deprecated: + since: "12.7.0" + notes: Use [Titanium.UI.CLIP_MODE_DEFAULT](Titanium.UI.CLIP_MODE_DEFAULT) instead. - name: CLIP_MODE_DISABLED summary: | @@ -347,6 +350,9 @@ properties: type: Number permission: read-only since: "3.3.0" + deprecated: + since: "12.7.0" + notes: Use [Titanium.UI.CLIP_MODE_DISABLED](Titanium.UI.CLIP_MODE_DISABLED) instead. - name: CLIP_MODE_ENABLED summary: | @@ -354,6 +360,9 @@ properties: type: Number permission: read-only since: "3.3.0" + deprecated: + since: "12.7.0" + notes: Use [Titanium.UI.CLIP_MODE_ENABLED](Titanium.UI.CLIP_MODE_ENABLED) instead. - name: COLLISION_MODE_ALL summary: | diff --git a/iphone/Classes/TiUIiOSProxy.m b/iphone/Classes/TiUIiOSProxy.m index e06f49302e4..ce7f2e37452 100644 --- a/iphone/Classes/TiUIiOSProxy.m +++ b/iphone/Classes/TiUIiOSProxy.m @@ -143,14 +143,17 @@ - (NSNumber *)SCROLL_DECELERATION_RATE_FAST - (NSNumber *)CLIP_MODE_DEFAULT { + DEPRECATED_REPLACED(@"UI.iOS.CLIP_MODE_DEFAULT", @"12.7.0", @"UI.CLIP_MODE_DEFAULT"); return NUMINT(0); } - (NSNumber *)CLIP_MODE_ENABLED { + DEPRECATED_REPLACED(@"UI.iOS.CLIP_MODE_ENABLED", @"12.7.0", @"UI.CLIP_MODE_ENABLED"); return NUMINT(1); } - (NSNumber *)CLIP_MODE_DISABLED { + DEPRECATED_REPLACED(@"UI.iOS.CLIP_MODE_DISABLED", @"12.7.0", @"UI.CLIP_MODE_DISABLED"); return NUMINT(-1); } From 5623036bb7e6395b66d791f3b72921f9eb4a080d Mon Sep 17 00:00:00 2001 From: Michael Gangolf Date: Thu, 1 May 2025 10:52:09 +0200 Subject: [PATCH 4/8] make it dynamic --- .../titanium/proxy/TiViewProxy.java | 3 +- .../appcelerator/titanium/view/TiUIView.java | 29 ++++++++++++++----- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/android/titanium/src/java/org/appcelerator/titanium/proxy/TiViewProxy.java b/android/titanium/src/java/org/appcelerator/titanium/proxy/TiViewProxy.java index 3d82f0448a9..47a429d50a6 100644 --- a/android/titanium/src/java/org/appcelerator/titanium/proxy/TiViewProxy.java +++ b/android/titanium/src/java/org/appcelerator/titanium/proxy/TiViewProxy.java @@ -95,7 +95,8 @@ TiC.PROPERTY_TRANSITION_NAME, TiC.PROPERTY_HIDDEN_BEHAVIOR, TiC.PROPERTY_ANCHOR_POINT, - TiC.PROPERTY_ACCESSIBILITY_DISABLE_LONG + TiC.PROPERTY_ACCESSIBILITY_DISABLE_LONG, + TiC.PROPERTY_CLIP_MODE }) public abstract class TiViewProxy extends KrollProxy { diff --git a/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java b/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java index d96de6d75a3..cee8f8579cf 100644 --- a/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java +++ b/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java @@ -73,6 +73,8 @@ import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; +import ti.modules.titanium.ui.UIModule; + /** * This class is for Titanium View implementations, that correspond with TiViewProxy. * A TiUIView is responsible for creating and maintaining a native Android View instance. @@ -974,6 +976,10 @@ public void propertyChanged(String key, Object oldValue, Object newValue, KrollP } else { Log.w(TAG, "Setting the 'viewShadowColor' property requires Android P or later"); } + } else if (key.equals(TiC.PROPERTY_CLIP_MODE)) { + if (nativeView != null) { + setClipMode(TiConvert.toInt(newValue)); + } } else if (Log.isDebugModeEnabled()) { Log.d(TAG, "Unhandled property key: " + key, Log.DEBUG_MODE); } @@ -1142,13 +1148,7 @@ public void processProperties(KrollDict d) } if (d.containsKey(TiC.PROPERTY_CLIP_MODE) && !nativeViewNull) { - if (nativeView != null - && TiConvert.toInt(d, TiC.PROPERTY_CLIP_MODE) == -1 - && nativeView instanceof ViewGroup viewGroup - && viewGroup.getParent() == null) { - viewGroup.setClipChildren(false); - viewGroup.setClipToPadding(false); - } + setClipMode(TiConvert.toInt(d, TiC.PROPERTY_CLIP_MODE)); } if (!nativeViewNull && d.containsKeyAndNotNull(TiC.PROPERTY_TRANSITION_NAME)) { @@ -1207,6 +1207,21 @@ private void applyCustomBackground(boolean reuseCurrentDrawable) } } + private void setClipMode(int clipMode) + { + + if (nativeView instanceof ViewGroup viewGroup) { + if (clipMode == UIModule.CLIP_MODE_DISABLED) { + viewGroup.setClipChildren(false); + viewGroup.setClipToPadding(false); + } else { + viewGroup.setClipChildren(true); + viewGroup.setClipToPadding(true); + } + viewGroup.invalidate(); + } + } + /** * @param props View's property dictionary * @return true if touch feedback can be applied. From 270f8b25844f6d16078e3f223711e5e438211267 Mon Sep 17 00:00:00 2001 From: Michael Gangolf Date: Thu, 1 May 2025 18:17:45 +0200 Subject: [PATCH 5/8] updates --- .../org/appcelerator/titanium/view/TiUIView.java | 15 ++++----------- apidoc/Titanium/UI/View.yml | 2 +- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java b/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java index cee8f8579cf..ddbc4eaffb5 100644 --- a/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java +++ b/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java @@ -978,7 +978,7 @@ public void propertyChanged(String key, Object oldValue, Object newValue, KrollP } } else if (key.equals(TiC.PROPERTY_CLIP_MODE)) { if (nativeView != null) { - setClipMode(TiConvert.toInt(newValue)); + setClipMode(TiConvert.toInt(newValue, UIModule.CLIP_MODE_DEFAULT)); } } else if (Log.isDebugModeEnabled()) { Log.d(TAG, "Unhandled property key: " + key, Log.DEBUG_MODE); @@ -1148,7 +1148,7 @@ public void processProperties(KrollDict d) } if (d.containsKey(TiC.PROPERTY_CLIP_MODE) && !nativeViewNull) { - setClipMode(TiConvert.toInt(d, TiC.PROPERTY_CLIP_MODE)); + setClipMode(TiConvert.toInt(d, UIModule.CLIP_MODE_DEFAULT)); } if (!nativeViewNull && d.containsKeyAndNotNull(TiC.PROPERTY_TRANSITION_NAME)) { @@ -1209,16 +1209,9 @@ private void applyCustomBackground(boolean reuseCurrentDrawable) private void setClipMode(int clipMode) { - if (nativeView instanceof ViewGroup viewGroup) { - if (clipMode == UIModule.CLIP_MODE_DISABLED) { - viewGroup.setClipChildren(false); - viewGroup.setClipToPadding(false); - } else { - viewGroup.setClipChildren(true); - viewGroup.setClipToPadding(true); - } - viewGroup.invalidate(); + viewGroup.setClipChildren(clipMode != UIModule.CLIP_MODE_DISABLED); + viewGroup.setClipToPadding(clipMode != UIModule.CLIP_MODE_DISABLED) } } diff --git a/apidoc/Titanium/UI/View.yml b/apidoc/Titanium/UI/View.yml index 42337c02213..9045a2c066f 100644 --- a/apidoc/Titanium/UI/View.yml +++ b/apidoc/Titanium/UI/View.yml @@ -1436,7 +1436,7 @@ properties: When set to or when this property is not set, clipping behavior is inferred. See section on Clipping Behavior in . - Android: This property is "creation only" and has to be on the top-level view. + Android: Has to be on the top-level view. Defaults to `undefined`. Behaves as if set to . type: Number From 800ab47cf8746778c876a09c8fe82156a8503a6b Mon Sep 17 00:00:00 2001 From: Michael Gangolf Date: Thu, 1 May 2025 18:23:58 +0200 Subject: [PATCH 6/8] missing ; --- .../src/java/org/appcelerator/titanium/view/TiUIView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java b/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java index ddbc4eaffb5..e17069ad376 100644 --- a/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java +++ b/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java @@ -1211,7 +1211,7 @@ private void setClipMode(int clipMode) { if (nativeView instanceof ViewGroup viewGroup) { viewGroup.setClipChildren(clipMode != UIModule.CLIP_MODE_DISABLED); - viewGroup.setClipToPadding(clipMode != UIModule.CLIP_MODE_DISABLED) + viewGroup.setClipToPadding(clipMode != UIModule.CLIP_MODE_DISABLED); } } From b70f1c2d69243b3ad49da35d1baf3e99059a8431 Mon Sep 17 00:00:00 2001 From: Michael Gangolf Date: Thu, 1 May 2025 18:44:23 +0200 Subject: [PATCH 7/8] fix clip direction --- .../src/java/org/appcelerator/titanium/view/TiUIView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java b/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java index e17069ad376..4c0bd41de1e 100644 --- a/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java +++ b/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java @@ -1210,8 +1210,8 @@ private void applyCustomBackground(boolean reuseCurrentDrawable) private void setClipMode(int clipMode) { if (nativeView instanceof ViewGroup viewGroup) { - viewGroup.setClipChildren(clipMode != UIModule.CLIP_MODE_DISABLED); - viewGroup.setClipToPadding(clipMode != UIModule.CLIP_MODE_DISABLED); + viewGroup.setClipChildren(clipMode == UIModule.CLIP_MODE_ENABLED); + viewGroup.setClipToPadding(clipMode == UIModule.CLIP_MODE_ENABLED); } } From 91e909ec4318614eec24ac13b43233ea87622df1 Mon Sep 17 00:00:00 2001 From: Michael Gangolf Date: Thu, 22 May 2025 18:51:43 +0200 Subject: [PATCH 8/8] loop --- .../appcelerator/titanium/view/TiUIView.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java b/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java index 0cbc0a1e583..50205552f7c 100644 --- a/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java +++ b/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java @@ -1148,7 +1148,7 @@ public void processProperties(KrollDict d) } if (d.containsKey(TiC.PROPERTY_CLIP_MODE) && !nativeViewNull) { - setClipMode(TiConvert.toInt(d, UIModule.CLIP_MODE_DEFAULT)); + setClipMode(TiConvert.toInt(d.getInt(TiC.PROPERTY_CLIP_MODE), UIModule.CLIP_MODE_DEFAULT)); } if (!nativeViewNull && d.containsKeyAndNotNull(TiC.PROPERTY_TRANSITION_NAME)) { @@ -1209,9 +1209,19 @@ private void applyCustomBackground(boolean reuseCurrentDrawable) private void setClipMode(int clipMode) { - if (nativeView instanceof ViewGroup viewGroup) { - viewGroup.setClipChildren(clipMode == UIModule.CLIP_MODE_ENABLED); - viewGroup.setClipToPadding(clipMode == UIModule.CLIP_MODE_ENABLED); + if (nativeView == null) { + return; + } + + TiViewProxy currentProxy = proxy; + while (currentProxy.getParent() != null) { + if (currentProxy.getOrCreateView().getOuterView() instanceof ViewGroup viewGroup) { + viewGroup.setClipChildren(clipMode != UIModule.CLIP_MODE_DISABLED); + } + currentProxy = currentProxy.getParent(); + if (currentProxy.getApiName().equals("Ti.UI.Window")) { + return; + } } }