Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TIMOB-25985] iOS/Android: Add "attributedString" API to Ti.UI.Button #10010

Merged
merged 12 commits into from
Jun 21, 2018
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
*/
package ti.modules.titanium.ui.widget;

import java.lang.CharSequence;
import java.util.HashMap;

import android.text.TextUtils;
import org.appcelerator.kroll.KrollDict;
import org.appcelerator.kroll.KrollProxy;
import org.appcelerator.kroll.common.Log;
import org.appcelerator.titanium.TiApplication;
import org.appcelerator.titanium.TiBlob;
import org.appcelerator.titanium.TiC;
import org.appcelerator.titanium.proxy.TiViewProxy;
Expand All @@ -20,9 +21,13 @@
import org.appcelerator.titanium.view.TiDrawableReference;
import org.appcelerator.titanium.view.TiUIView;

import ti.modules.titanium.ui.AttributedStringProxy;

import android.graphics.Color;
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Gravity;
import android.support.v7.widget.AppCompatButton;

Expand Down Expand Up @@ -85,6 +90,12 @@ public void processProperties(KrollDict d)
if (d.containsKey(TiC.PROPERTY_TITLE)) {
btn.setText(d.getString(TiC.PROPERTY_TITLE));
}
if (d.containsKey(TiC.PROPERTY_ATTRIBUTED_STRING)) {
Object attributedString = d.get(TiC.PROPERTY_ATTRIBUTED_STRING);
if (attributedString instanceof AttributedStringProxy) {
setAttributedStringText((AttributedStringProxy) attributedString);
}
}
if (d.containsKey(TiC.PROPERTY_COLOR)) {
Object color = d.get(TiC.PROPERTY_COLOR);
if (color == null) {
Expand Down Expand Up @@ -144,6 +155,8 @@ public void propertyChanged(String key, Object oldValue, Object newValue, KrollP
AppCompatButton btn = (AppCompatButton) getNativeView();
if (key.equals(TiC.PROPERTY_TITLE)) {
btn.setText((String) newValue);
} else if (key.equals(TiC.PROPERTY_ATTRIBUTED_STRING) && newValue instanceof AttributedStringProxy) {
setAttributedStringText((AttributedStringProxy) newValue);
} else if (key.equals(TiC.PROPERTY_COLOR)) {
btn.setTextColor(TiConvert.toColor(TiConvert.toString(newValue)));
} else if (key.equals(TiC.PROPERTY_FONT)) {
Expand Down Expand Up @@ -188,4 +201,19 @@ public void propertyChanged(String key, Object oldValue, Object newValue, KrollP
super.propertyChanged(key, oldValue, newValue, proxy);
}
}

private void setAttributedStringText(AttributedStringProxy attrString)
{
AppCompatButton btn = (AppCompatButton) getNativeView();

if (btn == null) {
return;
}

CharSequence text = AttributedStringProxy.toSpannable(attrString, TiApplication.getAppCurrentActivity());
if (text == null) {
text = "";
}
btn.setText(text);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need to call toSpannableInBundle() do you? We don't need to for labels, which uses Android's TextView Java class... andr Android Button class inherits from TextView as well. Also, the setText() method accepts a CharSequence type that a Spannable type inherits from. So, no casting should be needed. How about something like this?

AppCompatButton btn = (AppCompatButton) getNativeView();
if (btn != null) {
	CharSequence text = AttributedStringProxy.toSpannable(attrString, TiApplication.getAppCurrentActivity());
	if (text == null) {
		text = "";
	}
	btn.setText(text);
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was basically copied from the label implementation, but I could change it!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see. You copied it from "TiUIText.java" which is our TextField/TextArea code (seems to be doing an unnecessary step). The way I'm doing it is based on the "TiUILabel.java" code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect! Will change now.

}
19 changes: 16 additions & 3 deletions apidoc/Titanium/UI/Button.yml
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,22 @@ methods:
platforms: [iphone, ipad]

properties:
- name: attributedString
summary: Specify an attributed string for the label.
description: |
The underlying attributed string drawn by the label. If set, avoid setting common attributes
in the label, such as `color` and `font`, as unexpected behaviors may result.

iOS Note: This property can also be used to supress the underline style when accessibility
is enabled. To do so, set the `type` to <Titanium.UI.ATTRIBUTE_UNDERLINES_STYLE> and the
`value` to <Titanium.UI.ATTRIBUTE_UNDERLINE_STYLE_NONE>.
type: Titanium.UI.AttributedString
platforms: [android, iphone, ipad]
since:
android: 7.3.0
iphone: 7.3.0
ipad: 7.3.0

- name: backgroundImage
summary: |
Background image for the button in its normal state, specified as a local file path or URL.
Expand All @@ -163,7 +179,6 @@ properties:
is unset, the image will be darkened to indicate being selected.
type: String


- name: backgroundDisabledImage
summary: |
Background image for the button in its disabled state, specified as a local file path
Expand Down Expand Up @@ -209,7 +224,6 @@ properties:
For information about color values, see the "Colors" section of <Titanium.UI>.
type: String


- name: disabledColor
summary: Text color of the button in its disabled state, as a color name or hex triplet.
type: String
Expand All @@ -226,7 +240,6 @@ properties:
summary: Font to use for the button text.
type: Font


- name: image
summary: Image to display on the button, specified as a local
path, URL or a `Blob`.
Expand Down
14 changes: 14 additions & 0 deletions iphone/Classes/TiUIButton.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
#import "TiUIView.h"
#import "TiUtils.h"

#ifdef USE_TI_UIATTRIBUTEDSTRING
#import "TiUIAttributedStringProxy.h"
#endif

@implementation TiUIButton

#pragma mark Internal
Expand Down Expand Up @@ -252,6 +256,16 @@ - (void)setTitle_:(id)value
[[self button] setTitle:[TiUtils stringValue:value] forState:UIControlStateNormal];
}

- (void)setAttributedString_:(id)arg
{
#ifdef USE_TI_UIATTRIBUTEDSTRING
ENSURE_SINGLE_ARG(arg, TiUIAttributedStringProxy);
[[self proxy] replaceValue:arg forKey:@"attributedString" notification:NO];
[[self button] setAttributedTitle:[arg attributedString] forState:UIControlStateNormal];
[(TiViewProxy *)[self proxy] contentsWillChange];
#endif
}

- (void)setBackgroundImage_:(id)value
{
[backgroundImageCache release];
Expand Down
45 changes: 45 additions & 0 deletions tests/Resources/ti.ui.button.addontest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Appcelerator Titanium Mobile
* Copyright (c) 2015-Present by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
/* eslint-env mocha */
/* global Ti */
/* eslint no-unused-expressions: 'off' */
'use strict';

describe('Titanium.UI.Button', function () {

this.timeout(5000);

it('attributedString', function (finish) {
var button, attr, text;

text = 'Titanium rocks!';
attr = Ti.UI.createAttributedString({
text: text,
attributes: [
// Remove underline
{
type: Ti.UI.ATTRIBUTE_UNDERLINES_STYLE,
value: Ti.UI.ATTRIBUTE_UNDERLINE_STYLE_NONE,
range: [ 0, text.length ]
}
]
});

button = Ti.UI.createButton({ attributedString: attr });

should(button.attributedString).be.an.Object;
should(button.attributedString.text).be.a.String;
should(button.attributedString.text).eql('Titanium rocks!');
should(button.attributedString.attributes).be.an.Array;
should(button.attributedString.attributes[0].type).eql(Ti.UI.ATTRIBUTE_UNDERLINES_STYLE);
should(button.attributedString.attributes[0].value).eql(Ti.UI.ATTRIBUTE_UNDERLINE_STYLE_NONE);
should(button.attributedString.attributes[0].range[0]).eql(0);
should(button.attributedString.attributes[0].range[1]).eql(text.length);

finish();
});
});