diff --git a/android/modules/ui/src/java/ti/modules/titanium/ui/ButtonBarProxy.java b/android/modules/ui/src/java/ti/modules/titanium/ui/ButtonBarProxy.java index 061b8a84e50..fcfd0984e13 100644 --- a/android/modules/ui/src/java/ti/modules/titanium/ui/ButtonBarProxy.java +++ b/android/modules/ui/src/java/ti/modules/titanium/ui/ButtonBarProxy.java @@ -14,7 +14,7 @@ import ti.modules.titanium.ui.widget.TiUIButtonBar; @Kroll.proxy(creatableInModule = UIModule.class, propertyAccessors = { - TiC.PROPERTY_LABELS, + TiC.PROPERTY_LABELS }) public class ButtonBarProxy extends TiViewProxy { diff --git a/android/modules/ui/src/java/ti/modules/titanium/ui/android/RadioButtonsProxy.java b/android/modules/ui/src/java/ti/modules/titanium/ui/android/RadioButtonsProxy.java new file mode 100644 index 00000000000..6852fc32115 --- /dev/null +++ b/android/modules/ui/src/java/ti/modules/titanium/ui/android/RadioButtonsProxy.java @@ -0,0 +1,35 @@ +/** + * Titanium SDK + * Copyright TiDev, Inc. 04/07/2022-Present. All Rights Reserved. + * Licensed under the terms of the Apache Public License + * Please see the LICENSE included with this distribution for details. + */ +package ti.modules.titanium.ui.android; + +import android.app.Activity; + +import org.appcelerator.kroll.annotations.Kroll; +import org.appcelerator.titanium.TiC; +import org.appcelerator.titanium.proxy.TiViewProxy; +import org.appcelerator.titanium.view.TiUIView; + +import ti.modules.titanium.ui.widget.TiUIRadioButtons; + +@Kroll.proxy(creatableInModule = AndroidModule.class, propertyAccessors = { + TiC.PROPERTY_LABELS, TiC.PROPERTY_SELECTED_INDEX, TiC.PROPERTY_COLOR, TiC.PROPERTY_TINT_COLOR +}) +public class RadioButtonsProxy extends TiViewProxy +{ + @Override + public TiUIView createView(Activity activity) + { + defaultValues.put(TiC.PROPERTY_SELECTED_INDEX, -1); + return new TiUIRadioButtons(this); + } + + @Override + public String getApiName() + { + return "Ti.UI.RadioButtons"; + } +} diff --git a/android/modules/ui/src/java/ti/modules/titanium/ui/widget/TiUIRadioButtons.java b/android/modules/ui/src/java/ti/modules/titanium/ui/widget/TiUIRadioButtons.java new file mode 100644 index 00000000000..8f34cd677dd --- /dev/null +++ b/android/modules/ui/src/java/ti/modules/titanium/ui/widget/TiUIRadioButtons.java @@ -0,0 +1,197 @@ +/** + * Titanium SDK + * Copyright TiDev, Inc. 04/07/2022-Present. All Rights Reserved. + * Licensed under the terms of the Apache Public License + * Please see the LICENSE included with this distribution for details. + */ +package ti.modules.titanium.ui.widget; + +import android.content.res.ColorStateList; +import android.view.View; +import android.widget.RadioButton; +import android.widget.RadioGroup; + +import org.appcelerator.kroll.KrollDict; +import org.appcelerator.kroll.KrollProxy; +import org.appcelerator.titanium.TiApplication; +import org.appcelerator.titanium.TiC; +import org.appcelerator.titanium.proxy.TiViewProxy; +import org.appcelerator.titanium.util.TiConvert; +import org.appcelerator.titanium.view.TiUIView; + +public class TiUIRadioButtons extends TiUIView +{ + private static final String TAG = "TiUIButtonBar"; + + public TiUIRadioButtons(TiViewProxy proxy) + { + super(proxy); + + // Create view group used to host buttons. + RadioGroup radioGroup = new RadioGroup(proxy.getActivity()); + setNativeView(radioGroup); + } + + @Override + public void processProperties(KrollDict properties) + { + // Validate. + if (properties == null) { + return; + } + + if (properties.containsKeyAndNotNull(TiC.PROPERTY_SELECTED_INDEX)) { + proxy.setProperty(TiC.PROPERTY_SELECTED_INDEX, properties.getInt(TiC.PROPERTY_SELECTED_INDEX)); + } + if (properties.containsKeyAndNotNull(TiC.PROPERTY_LABELS)) { + processLabels(properties.get(TiC.PROPERTY_LABELS)); + } + if (properties.containsKeyAndNotNull(TiC.PROPERTY_COLOR)) { + setTextColor(TiConvert.toColor( + properties.get(TiC.PROPERTY_COLOR), TiApplication.getAppRootOrCurrentActivity())); + } + if (properties.containsKeyAndNotNull(TiC.PROPERTY_TINT_COLOR)) { + setActiveColor(TiConvert.toColor( + properties.get(TiC.PROPERTY_TINT_COLOR), TiApplication.getAppRootOrCurrentActivity())); + } + + super.processProperties(properties); + } + + private void setActiveColor(int color) + { + if (this.proxy == null) { + return; + } + + RadioGroup radioGroup = getRadioGroup(); + if (radioGroup == null) { + return; + } + for (int i = 0; i < radioGroup.getChildCount(); ++i) { + ((RadioButton) radioGroup.getChildAt(i)).setButtonTintList(ColorStateList.valueOf(color)); + } + } + + private void setTextColor(int color) + { + if (this.proxy == null) { + return; + } + + RadioGroup radioGroup = getRadioGroup(); + if (radioGroup == null) { + return; + } + + for (int i = 0; i < radioGroup.getChildCount(); ++i) { + ((RadioButton) radioGroup.getChildAt(i)).setTextColor(color); + } + } + + @Override + public void propertyChanged(String key, Object oldValue, Object newValue, KrollProxy proxy) + { + if (key == null) { + return; + } + + if (key.equals(TiC.PROPERTY_LABELS)) { + processLabels(newValue); + } else if (key.equals(TiC.PROPERTY_COLOR)) { + setTextColor(TiConvert.toColor(newValue, TiApplication.getAppRootOrCurrentActivity())); + } else if (key.equals(TiC.PROPERTY_TINT_COLOR)) { + setActiveColor(TiConvert.toColor(newValue, TiApplication.getAppRootOrCurrentActivity())); + } else if (key.equals(TiC.PROPERTY_SELECTED_INDEX)) { + RadioGroup radioGroup = getRadioGroup(); + int newIndex = TiConvert.toInt(newValue); + if (radioGroup != null) { + if (newIndex < radioGroup.getChildCount()) { + RadioButton button = (RadioButton) + radioGroup.getChildAt(newIndex); + int id = button.getId(); + radioGroup.check(id); + button.setChecked(true); + } else { + // change selected property back to current value + int currentIndex = radioGroup.indexOfChild( + radioGroup.findViewById(radioGroup.getCheckedRadioButtonId()) + ); + getProxy().setProperty(TiC.PROPERTY_SELECTED_INDEX, currentIndex); + } + } + } else { + super.propertyChanged(key, oldValue, newValue, proxy); + } + } + + private void processLabels(Object labels) + { + if (this.proxy == null) { + return; + } + + RadioGroup radioGroup = getRadioGroup(); + if (radioGroup == null) { + return; + } + + radioGroup.removeAllViews(); + + if ((labels == null) || !labels.getClass().isArray()) { + return; + } + Object[] objectArray = (Object[]) labels; + if (objectArray.length == 0) { + return; + } + + int count = 0; + int selectedIndex = TiConvert.toInt(getProxy().getProperty(TiC.PROPERTY_SELECTED_INDEX)); + if (objectArray[0] instanceof String) { + for (Object title : objectArray) { + boolean selected = (selectedIndex > -1 && selectedIndex == count); + addButton(TiConvert.toString(title, ""), selected); + count++; + } + } + } + + private void addButton(String title, boolean isSelected) + { + // Fetch the radio group view. + RadioGroup radioGroup = getRadioGroup(); + if (radioGroup == null) { + return; + } + + // Title must be non-null. + if (title == null) { + title = ""; + } + + RadioButton radioButton = new RadioButton(TiApplication.getAppRootOrCurrentActivity()); + radioButton.setText(title); + radioGroup.addView(radioButton); + if (isSelected) { + radioButton.setChecked(true); + radioGroup.check(radioButton.getId()); + } + radioButton.setOnClickListener(v -> { + int index = radioGroup.indexOfChild(radioGroup.findViewById(v.getId())); + proxy.setProperty(TiC.PROPERTY_SELECTED_INDEX, index); + KrollDict kd = new KrollDict(); + kd.put("index", index); + fireEvent(TiC.EVENT_CLICK, kd); + }); + } + + private RadioGroup getRadioGroup() + { + View view = getNativeView(); + if (view instanceof RadioGroup) { + return (RadioGroup) view; + } + return null; + } +} diff --git a/apidoc/Titanium/UI/Android/RadioButtons.yml b/apidoc/Titanium/UI/Android/RadioButtons.yml new file mode 100644 index 00000000000..e0fafe5d570 --- /dev/null +++ b/apidoc/Titanium/UI/Android/RadioButtons.yml @@ -0,0 +1,66 @@ +--- +name: Titanium.UI.Android.RadioButtons +summary: An radio button group component. +description: | + | Android | + | ------- | + | ![Android](./radiobuttons_android.png) | + + Allows you to create a native Android radio button group. +platforms: [android] +extends: Titanium.UI.View +since: "12.7.0" +excludes: + events: [dblclick, doubletap, focus, keypressed, longclick, longpress, pinch, postlayout, + singletap, swipe, touchcancel, touchend, touchmove, touchstart, twofingertap] + methods: [add, animate, convertPointToView, remove, removeAllChildren, toImage, insertAt, replaceAt] + properties: [accessibilityHidden, accessibilityHint, accessibilityLabel, accessibilityValue, + anchorPoint, animatedCenter, backgroundDisabledColor, backgroundDisabledImage, + backgroundFocusedColor, backgroundFocusedImage, backgroundGradient, + backgroundImage, backgroundLeftCap, backgroundRepeat, backgroundSelectedColor, + backgroundSelectedImage, backgroundTopCap, borderColor, borderRadius, borderWidth, center, + children, clipMode, focusable, height, horizontalWrap, keepScreenOn, layout, opacity, overrideCurrentAnimation, + pullBackgroundColor, rect, size, softKeyboardOnFocus, touchEnabled, touchFeedback, transform, + viewShadowColor, viewShadowOffset, viewShadowRadius, width, zIndex] + +events: + - name: click + summary: Fired when a button is clicked. + properties: + - name: index + summary: Index of the clicked item. + type: Number + +properties: + - name: index + summary: Index of the currently selected item. + type: Number + + - name: labels + summary: Array of labels for the radio buttons. + description: | + Each item in the array will be one radio button in the group. + type: [Array] + + - name: tintColor + summary: Defines the color of the radio circles. + type: [String, Titanium.UI.Color] + + - name: color + summary: Defines the color of the labels + type: [String, Titanium.UI.Color] + +examples: + - title: Simple radio group with 3 radio buttons. + example: | + ``` js + const win = Ti.UI.createWindow({}); + const radioButtons = Ti.UI.Android.createRadioButtons({ + labels: ["option 1", "option 2", "option 3"], + top: 10, + left: 10, + selectedIndex: 1 + }) + win.add(radioButtons); + win.open(); + ``` diff --git a/apidoc/Titanium/UI/Android/radiobuttons_android.png b/apidoc/Titanium/UI/Android/radiobuttons_android.png new file mode 100644 index 00000000000..78bbd61d2d1 Binary files /dev/null and b/apidoc/Titanium/UI/Android/radiobuttons_android.png differ