Skip to content

Commit

Permalink
Set button text in dp (#6443)
Browse files Browse the repository at this point in the history
TopBar button text broke in 6.5.0 and instead of being applied in sp it was applied in pixels. This made if seem like the fontSize option didn't work. This commit fixes the problem and also sets button fontSize in dp so it won't increase too much if users change font size settings in their device.

closes #6405
  • Loading branch information
guyca authored Jul 30, 2020
1 parent 956ddf3 commit 8d1309f
Show file tree
Hide file tree
Showing 12 changed files with 44 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ private List<ButtonController> getOrCreateButtonControllers(@Nullable Map<String

private ButtonController createButtonController(ButtonOptions button) {
ButtonController controller = new ButtonController(activity,
new ButtonPresenter(button, iconResolver),
new ButtonPresenter(activity, button, iconResolver),
button,
buttonCreator,
onClickListener
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.reactnativenavigation.viewcontrollers.stack.topbar.button

import android.content.Context
import android.graphics.Color
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
Expand All @@ -18,15 +19,15 @@ import com.reactnativenavigation.options.ButtonOptions
import com.reactnativenavigation.utils.*
import com.reactnativenavigation.views.stack.topbar.titlebar.TitleBar

open class ButtonPresenter(private val button: ButtonOptions, private val iconResolver: IconResolver) {
open class ButtonPresenter(private val context: Context, private val button: ButtonOptions, private val iconResolver: IconResolver) {
companion object {
const val DISABLED_COLOR = Color.LTGRAY
}

val styledText: SpannableString
get() {
return SpannableString(button.text.get("")).apply {
setSpan(ButtonSpan(button), 0, button.text.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE)
setSpan(ButtonSpan(context, button), 0, button.text.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package com.reactnativenavigation.viewcontrollers.stack.topbar.button

import android.content.Context
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Typeface
import android.text.TextPaint
import android.text.style.MetricAffectingSpan
import com.reactnativenavigation.options.ButtonOptions
import com.reactnativenavigation.utils.UiUtils

class ButtonSpan(private val button: ButtonOptions) : MetricAffectingSpan() {
class ButtonSpan(private val context: Context, private val button: ButtonOptions) : MetricAffectingSpan() {
override fun updateDrawState(drawState: TextPaint) = apply(drawState)

override fun updateMeasureState(paint: TextPaint) = apply(paint)
Expand All @@ -17,7 +19,7 @@ class ButtonSpan(private val button: ButtonOptions) : MetricAffectingSpan() {
val fakeStyle = (paint.typeface?.style ?: 0) and (fontFamily?.style?.inv() ?: 1)
if (fakeStyle and Typeface.BOLD != 0) paint.isFakeBoldText = true
if (fakeStyle and Typeface.ITALIC != 0) paint.textSkewX = -0.25f
if (fontSize.hasValue()) paint.textSize = fontSize.get().toFloat()
if (fontSize.hasValue()) paint.textSize = UiUtils.dpToPx(context, fontSize.get().toFloat())
paint.typeface = fontFamily
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public void beforeEach() {
activity.setContentView(titleBar);
button = createButton();

uut = new ButtonPresenter(button, new IconResolverFake(activity));
uut = new ButtonPresenter(activity, button, new IconResolverFake(activity));
buttonController = new ButtonController(
activity,
uut,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
package com.reactnativenavigation.utils;

import android.app.Activity;
import android.graphics.Color;
import android.graphics.Paint;

import com.reactnativenavigation.BaseTest;
import com.reactnativenavigation.options.ButtonOptions;
import com.reactnativenavigation.options.params.Colour;
import com.reactnativenavigation.options.params.Fraction;
import com.reactnativenavigation.viewcontrollers.stack.topbar.button.ButtonSpan;

import org.jetbrains.annotations.NotNull;
import org.junit.Test;
import org.robolectric.annotation.Config;

import static org.assertj.core.api.Java6Assertions.assertThat;

@Config(qualifiers = "xhdpi")
public class ButtonSpanTest extends BaseTest {
private ButtonSpan uut;
private ButtonOptions button;
private Activity activity;

@Override
public void beforeEach() {
button = createButton();
uut = new ButtonSpan(button);
activity = newActivity();
uut = new ButtonSpan(activity, button);
}

@Test
Expand All @@ -31,6 +37,15 @@ public void apply_colorIsNotHandled() {
assertThat(paint.getColor()).isNotEqualTo(button.color.get());
}

@Test
public void apply_fontSizeIsAppliedInDp() {
button.fontSize = new Fraction(14);
Paint paint = new Paint();
uut.apply(paint);

assertThat(paint.getTextSize()).isEqualTo(UiUtils.dpToPx(activity, 14));
}

@NotNull
private ButtonOptions createButton() {
ButtonOptions button = new ButtonOptions();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public static ButtonOptions iconButton(String id, String icon) {

public static ButtonController createButtonController(Activity activity, ButtonOptions button) {
return new ButtonController(activity,
new ButtonPresenter(button, new IconResolver(activity, ImageLoaderMock.mock())),
new ButtonPresenter(activity, button, new IconResolver(activity, ImageLoaderMock.mock())),
button,
new TitleBarButtonCreatorMock(),
buttonId -> {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public void beforeEach() {
ButtonOptions button = createComponentButton();
uut = new ButtonController(
activity,
new ButtonPresenter(button, new IconResolver(activity, ImageLoaderMock.mock())),
new ButtonPresenter(activity, button, new IconResolver(activity, ImageLoaderMock.mock())),
button,
new TitleBarButtonCreatorMock(),
Mockito.mock(ButtonController.OnClickListener.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public void setTitleFontSize_usesDpInsteadofSp() {
private ButtonController createButtonController(ButtonOptions b) {
return new ButtonController(
activity,
new ButtonPresenter(b, new IconResolverFake(activity)),
new ButtonPresenter(activity, b, new IconResolverFake(activity)),
b,
mock(TitleBarButtonCreator.class),
mock(ButtonController.OnClickListener.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public void beforeEach() {
stackController.getTopBar().layout(0, 0, 1080, 200);
getTitleBar().layout(0, 0, 1080, 200);

optionsPresenter = spy(new ButtonPresenter(button, new IconResolverFake(activity)));
optionsPresenter = spy(new ButtonPresenter(activity, button, new IconResolverFake(activity)));
uut = new ButtonController(activity, optionsPresenter, button, buttonCreatorMock, (buttonId) -> {});

stackController.ensureViewIsCreated();
Expand Down
4 changes: 4 additions & 0 deletions lib/src/interfaces/Options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,10 @@ export interface OptionsTopBarButton {
* #### (iOS specific)
*/
fontWeight?: FontWeight;
/**
* Set the font size in dp
*/
fontSize?: number;
/**
* Set the button enabled or disabled
* @default true
Expand Down
6 changes: 3 additions & 3 deletions playground/src/screens/ButtonsScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { NavigationComponentProps } from 'react-native-navigation';
import { NavigationComponent, Options } from 'react-native-navigation';
import Root from '../components/Root';
import Button from '../components/Button';
import Navigation from '../services/Navigation';
Expand All @@ -18,8 +18,8 @@ const {
CHANGE_BUTTON_PROPS,
} = testIDs;

export default class Options extends React.Component<NavigationComponentProps> {
static options() {
export default class ButtonOptions extends NavigationComponent {
static options(): Options {
return {
fab: {
id: 'fab',
Expand Down
8 changes: 8 additions & 0 deletions website/api/options-button.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ This option will set whether characters are all capitalized or not.
| ------- | -------- | -------- | ------- |
| boolean | No | Android | true |

### `fontSize`

If the button has text, this option is used to set font size in DP.

| Type | Required | Platform |
| ------ | -------- | -------- |
| number | No | Both |

### `id`

Buttons are identified by their id property. When a button is clicked, a buttonPress event is emitted to js, containing the id of the clicked button.
Expand Down

0 comments on commit 8d1309f

Please sign in to comment.