From 4d813894527c0268679a3ac1f4b117e8128a6ad9 Mon Sep 17 00:00:00 2001 From: Joshua Quick Date: Sat, 19 Dec 2020 01:29:40 -0800 Subject: [PATCH] feat(android): add TextField/TextArea "borderStyle" property supporting material styles Fixes TIMOB-28299 --- .../modules/titanium/ui/widget/TiUIText.java | 50 +++++- .../java/org/appcelerator/titanium/TiC.java | 5 + apidoc/Titanium/UI/TextArea.yml | 9 + apidoc/Titanium/UI/TextField.yml | 8 +- apidoc/Titanium/UI/UI.yml | 156 +++++++++++++++++- 5 files changed, 214 insertions(+), 14 deletions(-) diff --git a/android/modules/ui/src/java/ti/modules/titanium/ui/widget/TiUIText.java b/android/modules/ui/src/java/ti/modules/titanium/ui/widget/TiUIText.java index b9f8473304c..5c291327811 100644 --- a/android/modules/ui/src/java/ti/modules/titanium/ui/widget/TiUIText.java +++ b/android/modules/ui/src/java/ti/modules/titanium/ui/widget/TiUIText.java @@ -15,8 +15,10 @@ import org.appcelerator.kroll.KrollDict; import org.appcelerator.kroll.KrollProxy; import org.appcelerator.kroll.common.Log; +import org.appcelerator.titanium.R; import org.appcelerator.titanium.TiApplication; import org.appcelerator.titanium.TiC; +import org.appcelerator.titanium.TiDimension; import org.appcelerator.titanium.proxy.TiViewProxy; import org.appcelerator.titanium.util.TiConvert; import org.appcelerator.titanium.util.TiRHelper; @@ -56,6 +58,7 @@ import android.widget.LinearLayout; import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; +import androidx.appcompat.view.ContextThemeWrapper; import com.google.android.material.textfield.TextInputLayout; public class TiUIText extends TiUIView implements TextWatcher, OnEditorActionListener, OnFocusChangeListener @@ -109,14 +112,47 @@ public void onLayoutChange(View v, int left, int top, int right, int bottom, int tv.setOnFocusChangeListener(this); // TODO refactor to TiUIView? tv.setIncludeFontPadding(true); if (field) { - tv.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); + tv.setGravity(Gravity.CENTER_VERTICAL | Gravity.START); } else { - tv.setGravity(Gravity.TOP | Gravity.LEFT); + tv.setGravity(Gravity.TOP | Gravity.START); + } + + int borderStyle = UIModule.INPUT_BORDERSTYLE_FILLED; + borderStyle = TiConvert.toInt(proxy.getProperty(TiC.PROPERTY_BORDER_STYLE), borderStyle); + switch (borderStyle) { + case UIModule.INPUT_BORDERSTYLE_BEZEL: + case UIModule.INPUT_BORDERSTYLE_LINE: + case UIModule.INPUT_BORDERSTYLE_ROUNDED: + textInputLayout = new TextInputLayout(new ContextThemeWrapper( + proxy.getActivity(), R.style.Widget_MaterialComponents_TextInputLayout_OutlinedBox)); + textInputLayout.setBoxBackgroundMode(TextInputLayout.BOX_BACKGROUND_OUTLINE); + if (borderStyle == UIModule.INPUT_BORDERSTYLE_ROUNDED) { + float radius = (new TiDimension("5dp", TiDimension.TYPE_LEFT)).getAsPixels(textInputLayout); + textInputLayout.setBoxCornerRadii(radius, radius, radius, radius); + } else { + textInputLayout.setBoxCornerRadii(0, 0, 0, 0); + } + break; + case UIModule.INPUT_BORDERSTYLE_NONE: + textInputLayout = new TextInputLayout(new ContextThemeWrapper( + proxy.getActivity(), R.style.Widget_MaterialComponents_TextInputLayout_FilledBox)); + textInputLayout.setBoxBackgroundMode(TextInputLayout.BOX_BACKGROUND_NONE); + break; + case UIModule.INPUT_BORDERSTYLE_UNDERLINED: + textInputLayout = new TextInputLayout(proxy.getActivity()); + textInputLayout.setBoxBackgroundMode(TextInputLayout.BOX_BACKGROUND_NONE); + break; + case UIModule.INPUT_BORDERSTYLE_FILLED: + default: + textInputLayout = new TextInputLayout(proxy.getActivity()); + textInputLayout.setBoxBackgroundMode(TextInputLayout.BOX_BACKGROUND_FILLED); + break; } - - textInputLayout = new TextInputLayout(proxy.getActivity()); - textInputLayout.addView(tv, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.MATCH_PARENT)); + if (borderStyle != UIModule.INPUT_BORDERSTYLE_UNDERLINED) { + tv.setBackground(null); + } + textInputLayout.addView(tv, new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)); setNativeView(textInputLayout); } @@ -481,7 +517,7 @@ protected KrollDict getFocusEventObject(boolean hasFocus) public boolean onEditorAction(TextView v, int actionId, KeyEvent keyEvent) { // TIMOB-23757: https://code.google.com/p/android/issues/detail?id=182191 - if (Build.VERSION.SDK_INT < 24 && (tv.getGravity() & Gravity.LEFT) != Gravity.LEFT) { + if (Build.VERSION.SDK_INT < 24 && (tv.getGravity() & Gravity.START) != Gravity.START) { if (getNativeView() != null) { ViewGroup view = (ViewGroup) getNativeView().getParent(); view.setFocusableInTouchMode(true); diff --git a/android/titanium/src/java/org/appcelerator/titanium/TiC.java b/android/titanium/src/java/org/appcelerator/titanium/TiC.java index c9ae6d167ff..cd8d28815f4 100644 --- a/android/titanium/src/java/org/appcelerator/titanium/TiC.java +++ b/android/titanium/src/java/org/appcelerator/titanium/TiC.java @@ -1172,6 +1172,11 @@ public class TiC */ public static final String PROPERTY_BORDER_RADIUS = "borderRadius"; + /** + * @module.api + */ + public static final String PROPERTY_BORDER_STYLE = "borderStyle"; + /** * @module.api */ diff --git a/apidoc/Titanium/UI/TextArea.yml b/apidoc/Titanium/UI/TextArea.yml index f0a4ba549de..0d1470b9487 100644 --- a/apidoc/Titanium/UI/TextArea.yml +++ b/apidoc/Titanium/UI/TextArea.yml @@ -224,6 +224,15 @@ properties: since: {android: "3.0.0"} platforms: [android, iphone, ipad, macos] + - name: borderStyle + summary: Border style for the text area. + type: Number + constants: Titanium.UI.INPUT_BORDERSTYLE_* + default: + availability: creation + platforms: [android] + since: 10.0.0 + - name: clearOnEdit summary: Determines whether the value of this text area should be cleared when it is focused. type: Boolean diff --git a/apidoc/Titanium/UI/TextField.yml b/apidoc/Titanium/UI/TextField.yml index b1a592a40d6..69b8d7f15e8 100644 --- a/apidoc/Titanium/UI/TextField.yml +++ b/apidoc/Titanium/UI/TextField.yml @@ -213,10 +213,14 @@ properties: - name: borderStyle summary: Border style for the field. + description: On Android, this is a creation-only property and cannot be changed dynamically. type: Number constants: Titanium.UI.INPUT_BORDERSTYLE_* - default: - platforms: [iphone, ipad, macos] + default: | + (on iOS), + (on Android) + platforms: [android, iphone, ipad, macos] + since: {android: 10.0.0, iphone: 0.8.0, ipad: 0.8.0, macos: 9.2.0} - name: clearButtonMode summary: Determines when the clear button is displayed. diff --git a/apidoc/Titanium/UI/UI.yml b/apidoc/Titanium/UI/UI.yml index cea1fe7c1f4..347180c58bf 100644 --- a/apidoc/Titanium/UI/UI.yml +++ b/apidoc/Titanium/UI/UI.yml @@ -1448,6 +1448,81 @@ properties: permission: read-only since: "7.3.0" + - name: BUTTON_STYLE_FILLED + summary: Use with [Button.style](Titanium.UI.Button.style) to show a solid filled button. + description: | + This is not supported on iOS and will show [BUTTON_STYLE_TEXT](Titanium.UI.BUTTON_STYLE_TEXT) instead. + type: Number + permission: read-only + since: "10.0.0" + + - name: BUTTON_STYLE_OUTLINED + summary: Use with [Button.style](Titanium.UI.Button.style) to show an unfilled rounded border button. + description: | + This is not supported on iOS and will show [BUTTON_STYLE_TEXT](Titanium.UI.BUTTON_STYLE_TEXT) instead. + type: Number + permission: read-only + since: "10.0.0" + + - name: BUTTON_STYLE_TEXT + summary: Use with [Button.style](Titanium.UI.Button.style) to show a text-only button without a background. + type: Number + permission: read-only + since: "10.0.0" + + - name: BUTTON_STYLE_OPTION_POSITIVE + summary: Use with [Button.style](Titanium.UI.Button.style) to show a positive themed accept button. + description: | + This is a text-only button without a background. It is intended to be used in conjunction with + [BUTTON_STYLE_OPTION_NEGATIVE](Titanium.UI.BUTTON_STYLE_OPTION_NEGATIVE) and + [BUTTON_STYLE_OPTION_NEUTRAL](Titanium.UI.BUTTON_STYLE_OPTION_NEUTRAL) to show an an accept button + before closing a window or dialog such as "OK", "Yes", "Done", etc. It is typically colored + differently than a [BUTTON_STYLE_TEXT](Titanium.UI.BUTTON_STYLE_TEXT) themed button on iOS. + + On Android, this can be customized by the `buttonBarPositiveButtonStyle` attribute. + + By default, the Android material theme does not style this button differently than any other + text-only button. Only the holo theme will style it differently. + type: Number + permission: read-only + since: "10.0.0" + + - name: BUTTON_STYLE_OPTION_NEGATIVE + summary: Use with [Button.style](Titanium.UI.Button.style) to show a negative themed escape button. + description: | + This is a text-only button without a background. It is intended to be used in conjunction with + [BUTTON_STYLE_OPTION_POSITIVE](Titanium.UI.BUTTON_STYLE_OPTION_POSITIVE) and + [BUTTON_STYLE_OPTION_NEUTRAL](Titanium.UI.BUTTON_STYLE_OPTION_NEUTRAL) to show an + escape button to exit a window or dialog such as "Cancel", "No", etc. + + This is not supported on iOS and will use [BUTTON_STYLE_TEXT](Titanium.UI.BUTTON_STYLE_TEXT) instead. + + On Android, this can be customized by the `buttonBarNegativeButtonStyle` attribute. By default, + Android's built-in themes will style this button the same as + [BUTTON_STYLE_OPTION_NEUTRAL](Titanium.UI.BUTTON_STYLE_OPTION_NEUTRAL) and + [BUTTON_STYLE_TEXT](Titanium.UI.BUTTON_STYLE_TEXT). + type: Number + permission: read-only + since: "10.0.0" + + - name: BUTTON_STYLE_OPTION_NEUTRAL + summary: Use with [Button.style](Titanium.UI.Button.style) to show a normal themed option button. + description: | + This is a text-only button without a background. It is intended to be used in conjunction with + [BUTTON_STYLE_OPTION_POSITIVE](Titanium.UI.BUTTON_STYLE_OPTION_POSITIVE) and + [BUTTON_STYLE_OPTION_NEGATIVE](Titanium.UI.BUTTON_STYLE_OPTION_NEGATIVE) to show + a normal informational button. + + This is not supported on iOS and will use [BUTTON_STYLE_TEXT](Titanium.UI.BUTTON_STYLE_TEXT) instead. + + On Android, this can be customized by the `buttonBarNeutralButtonStyle` attribute. By default, + Android's built-in themes will style this button the same as + [BUTTON_STYLE_OPTION_NEGATIVE](Titanium.UI.BUTTON_STYLE_OPTION_NEGATIVE) and + [BUTTON_STYLE_TEXT](Titanium.UI.BUTTON_STYLE_TEXT). + type: Number + permission: read-only + since: "10.0.0" + - name: HINT_TYPE_STATIC summary: | Use when creating a TextField to specify the hintType as static. @@ -1636,27 +1711,66 @@ properties: - name: INPUT_BORDERSTYLE_BEZEL summary: Use a bezel-style border on the input field. - description: Use with the property. + description: | + Use with the property. + + On Android, this can also be used by the property. + + Android does not support this style and will use + [INPUT_BORDERSTYLE_LINE](Titanium.UI.INPUT_BORDERSTYLE_LINE) instead. type: Number permission: read-only - name: INPUT_BORDERSTYLE_LINE summary: Use a simple line border on the input field. - description: Use with the property. + description: | + Use with the property. + + On Android, this can also be used by the property. type: Number permission: read-only - name: INPUT_BORDERSTYLE_NONE summary: Use no border on the input field. - description: Use with the property. + description: | + Use with the property. + + On Android, this can also be used by the property. type: Number permission: read-only - name: INPUT_BORDERSTYLE_ROUNDED summary: Use a rounded-rectangle border on the input field. - description: Use with the property. + description: | + Use with the property. + + On Android, this can also be used by the property. + type: Number + permission: read-only + + - name: INPUT_BORDERSTYLE_UNDERLINED + summary: Show an underline instead of a border around the input field. + description: | + Use with the and properties. + + iOS does not support this style and will use + [INPUT_BORDERSTYLE_LINE](Titanium.UI.INPUT_BORDERSTYLE_LINE) instead. + type: Number + permission: read-only + since: "10.0.0" + + - name: INPUT_BORDERSTYLE_FILLED + summary: Show an enclosed border with a filled background on the input field. + description: | + This is the default Android material theme on Android. + + Use with the and properties. + + iOS does not support this style and will use + [INPUT_BORDERSTYLE_BEZEL](Titanium.UI.INPUT_BORDERSTYLE_BEZEL) instead. type: Number permission: read-only + since: "10.0.0" - name: INPUT_BUTTONMODE_ALWAYS summary: Always show buttons on the input field. @@ -2244,7 +2358,6 @@ properties: type: Number permission: read-only - - name: RETURNKEY_JOIN summary: Set the return key text to "Join". description: | @@ -2329,6 +2442,39 @@ properties: permission: read-only since: "2.0.0" + - name: SWITCH_STYLE_CHECKBOX + summary: Use with [Switch.style](Titanium.UI.Switch.style) to show a checkbox. + description: | + This is supported by Android and macOS apps running on Big Sur (v11) or higher. iOS devices do not + support this style and will use [SWITCH_STYLE_SLIDER](Titanium.UI.SWITCH_STYLE_SLIDER) instead. + type: Number + permission: read-only + since: "10.0.0" + + - name: SWITCH_STYLE_TOGGLEBUTTON + summary: Use with [Switch.style](Titanium.UI.Switch.style) to show a toggleable button. + description: | + This style is only supported on Android. + On iOS, this will use [SWITCH_STYLE_SLIDER](Titanium.UI.SWITCH_STYLE_SLIDER) instead. + type: Number + permission: read-only + since: "10.0.0" + + - name: SWITCH_STYLE_SLIDER + summary: Use with [Switch.style](Titanium.UI.Switch.style) to show a slidable button. + type: Number + permission: read-only + since: "10.0.0" + + - name: SWITCH_STYLE_CHIP + summary: Use with [Switch.style](Titanium.UI.Switch.style) to show a material design checkable chip widget. + description: | + This style is only supported on Android. + On iOS, this will use [SWITCH_STYLE_SLIDER](Titanium.UI.SWITCH_STYLE_SLIDER) instead. + type: Number + permission: read-only + since: "10.0.0" + - name: TABLE_VIEW_SEPARATOR_STYLE_NONE summary: The row divider is hidden. type: Number