Browse Source

Top tab font family (#2410)

* Implement titleFontFamily in topTab option

* docs

* Pass TypefaceLoader instead of context
Guy Carmeli 6 years ago
parent
commit
29b34c774e
No account linked to committer's email address
22 changed files with 189 additions and 51 deletions
  1. 1
    0
      docs/_sidebar.md
  2. 9
    0
      docs/docs/options/TopTab.md
  3. 9
    4
      lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutFactory.java
  4. 4
    0
      lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutNode.java
  5. 7
    5
      lib/android/app/src/main/java/com/reactnativenavigation/parse/NavigationOptions.java
  6. 9
    1
      lib/android/app/src/main/java/com/reactnativenavigation/parse/TopTabOptions.java
  7. 7
    2
      lib/android/app/src/main/java/com/reactnativenavigation/parse/TopTabsOptions.java
  8. 12
    4
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/OptionsPresenter.java
  9. 3
    2
      lib/android/app/src/main/java/com/reactnativenavigation/react/NavigationModule.java
  10. 11
    7
      lib/android/app/src/main/java/com/reactnativenavigation/utils/TypefaceLoader.java
  11. 25
    0
      lib/android/app/src/main/java/com/reactnativenavigation/utils/ViewUtils.java
  12. 4
    0
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabController.java
  13. 6
    2
      lib/android/app/src/main/java/com/reactnativenavigation/views/TopBar.java
  14. 7
    0
      lib/android/app/src/main/java/com/reactnativenavigation/views/TopTabs.java
  15. 26
    0
      lib/android/app/src/main/java/com/reactnativenavigation/views/TopTabsStyleHelper.java
  16. 8
    5
      lib/android/app/src/test/java/com/reactnativenavigation/parse/NavigationOptionsTest.java
  17. 11
    17
      lib/android/app/src/test/java/com/reactnativenavigation/utils/TypefaceLoaderTest.java
  18. 1
    1
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopTabsControllerMock.java
  19. 13
    0
      lib/src/params/options/TopTab.js
  20. 14
    0
      lib/src/params/options/TopTab.test.js
  21. BIN
      playground/android/app/src/main/assets/fonts/Dosis-Regular.ttf
  22. 2
    1
      playground/src/containers/WelcomeScreen.js

+ 1
- 0
docs/_sidebar.md View File

11
 - Options
11
 - Options
12
  - [NavigationOptions](/docs/options/NavigationOptions)
12
  - [NavigationOptions](/docs/options/NavigationOptions)
13
  - [TopBar](/docs/options/TopBar)
13
  - [TopBar](/docs/options/TopBar)
14
+ - [TopTab](/docs/options/TopTab)
14
  - [Button](/docs/options/Button)
15
  - [Button](/docs/options/Button)
15
  - [BottomTabs](/docs/options/BottomTabs)
16
  - [BottomTabs](/docs/options/BottomTabs)
16
  - [BottomTab](/docs/options/BottomTab)
17
  - [BottomTab](/docs/options/BottomTab)

+ 9
- 0
docs/docs/options/TopTab.md View File

1
+<h1>TopTab</h1>
2
+
3
+**Properties**
4
+
5
+| Name | Type | Description |
6
+| --- | --- | --- |
7
+| title | <code>string</code> | The tab's title in the TopTabs view |
8
+| titleFontFamily | <code>string</code> | Change the tab's title font family |
9
+

+ 9
- 4
lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutFactory.java View File

4
 
4
 
5
 import com.facebook.react.ReactInstanceManager;
5
 import com.facebook.react.ReactInstanceManager;
6
 import com.reactnativenavigation.react.ReactContainerViewCreator;
6
 import com.reactnativenavigation.react.ReactContainerViewCreator;
7
+import com.reactnativenavigation.utils.TypefaceLoader;
7
 import com.reactnativenavigation.viewcontrollers.BottomTabsController;
8
 import com.reactnativenavigation.viewcontrollers.BottomTabsController;
8
 import com.reactnativenavigation.viewcontrollers.ContainerViewController;
9
 import com.reactnativenavigation.viewcontrollers.ContainerViewController;
9
 import com.reactnativenavigation.viewcontrollers.SideMenuController;
10
 import com.reactnativenavigation.viewcontrollers.SideMenuController;
22
 	private final Activity activity;
23
 	private final Activity activity;
23
 	private final ReactInstanceManager reactInstanceManager;
24
 	private final ReactInstanceManager reactInstanceManager;
24
     private NavigationOptions defaultOptions;
25
     private NavigationOptions defaultOptions;
26
+    private final TypefaceLoader typefaceManager;
25
 
27
 
26
     public LayoutFactory(Activity activity, final ReactInstanceManager reactInstanceManager, NavigationOptions defaultOptions) {
28
     public LayoutFactory(Activity activity, final ReactInstanceManager reactInstanceManager, NavigationOptions defaultOptions) {
27
 		this.activity = activity;
29
 		this.activity = activity;
28
 		this.reactInstanceManager = reactInstanceManager;
30
 		this.reactInstanceManager = reactInstanceManager;
29
         this.defaultOptions = defaultOptions;
31
         this.defaultOptions = defaultOptions;
32
+        typefaceManager = new TypefaceLoader(activity);
30
     }
33
     }
31
 
34
 
32
 	public ViewController create(final LayoutNode node) {
35
 	public ViewController create(final LayoutNode node) {
92
 	private ViewController createContainer(LayoutNode node) {
95
 	private ViewController createContainer(LayoutNode node) {
93
 		String id = node.id;
96
 		String id = node.id;
94
 		String name = node.data.optString("name");
97
 		String name = node.data.optString("name");
95
-		NavigationOptions navigationOptions = NavigationOptions.parse(node.data.optJSONObject("navigationOptions"), defaultOptions);
98
+		NavigationOptions navigationOptions = NavigationOptions.parse(typefaceManager, node.data.optJSONObject("navigationOptions"), defaultOptions);
96
 		return new ContainerViewController(activity,
99
 		return new ContainerViewController(activity,
97
                 id,
100
                 id,
98
                 name,
101
                 name,
128
 
131
 
129
     private ViewController createTopTabs(LayoutNode node) {
132
     private ViewController createTopTabs(LayoutNode node) {
130
         final List<TopTabController> tabs = new ArrayList<>();
133
         final List<TopTabController> tabs = new ArrayList<>();
131
-        for (LayoutNode child : node.children) {
132
-            tabs.add((TopTabController) create(child));
134
+        for (int i = 0; i < node.children.size(); i++) {
135
+            TopTabController tabController = (TopTabController) create(node.children.get(i));
136
+            tabController.setTabIndex(i);
137
+            tabs.add(tabController);
133
         }
138
         }
134
         return new TopTabsController(activity, node.id, tabs);
139
         return new TopTabsController(activity, node.id, tabs);
135
     }
140
     }
137
     private ViewController createTopTab(LayoutNode node) {
142
     private ViewController createTopTab(LayoutNode node) {
138
         String id = node.id;
143
         String id = node.id;
139
         String name = node.data.optString("name");
144
         String name = node.data.optString("name");
140
-        NavigationOptions navigationOptions = NavigationOptions.parse(node.data.optJSONObject("navigationOptions"), defaultOptions);
145
+        NavigationOptions navigationOptions = NavigationOptions.parse(typefaceManager, node.getNavigationOptions(), defaultOptions);
141
         return new TopTabController(activity,
146
         return new TopTabController(activity,
142
                 id,
147
                 id,
143
                 name,
148
                 name,

+ 4
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutNode.java View File

35
 		this.data = data;
35
 		this.data = data;
36
 		this.children = children;
36
 		this.children = children;
37
 	}
37
 	}
38
+
39
+    JSONObject getNavigationOptions() {
40
+	    return data.optJSONObject("navigationOptions");
41
+    }
38
 }
42
 }

+ 7
- 5
lib/android/app/src/main/java/com/reactnativenavigation/parse/NavigationOptions.java View File

2
 
2
 
3
 import android.support.annotation.NonNull;
3
 import android.support.annotation.NonNull;
4
 
4
 
5
+import com.reactnativenavigation.utils.TypefaceLoader;
6
+
5
 import org.json.JSONObject;
7
 import org.json.JSONObject;
6
 
8
 
7
 import java.util.ArrayList;
9
 import java.util.ArrayList;
22
 	}
24
 	}
23
 
25
 
24
     @NonNull
26
     @NonNull
25
-    public static NavigationOptions parse(JSONObject json) {
26
-        return parse(json, new NavigationOptions());
27
+    public static NavigationOptions parse(TypefaceLoader typefaceManager, JSONObject json) {
28
+        return parse(typefaceManager, json, new NavigationOptions());
27
     }
29
     }
28
 
30
 
29
 	@NonNull
31
 	@NonNull
30
-	public static NavigationOptions parse(JSONObject json, @NonNull NavigationOptions defaultOptions) {
32
+	public static NavigationOptions parse(TypefaceLoader typefaceManager, JSONObject json, @NonNull NavigationOptions defaultOptions) {
31
 		NavigationOptions result = new NavigationOptions();
33
 		NavigationOptions result = new NavigationOptions();
32
 		if (json == null) return result;
34
 		if (json == null) return result;
33
 
35
 
34
 		result.topBarOptions = TopBarOptions.parse(json.optJSONObject("topBar"));
36
 		result.topBarOptions = TopBarOptions.parse(json.optJSONObject("topBar"));
35
 		result.topTabsOptions = TopTabsOptions.parse(json.optJSONObject("topTabs"));
37
 		result.topTabsOptions = TopTabsOptions.parse(json.optJSONObject("topTabs"));
36
-        result.topTabOptions = TopTabOptions.parse(json.optJSONObject("topTab"));
38
+        result.topTabOptions = TopTabOptions.parse(typefaceManager, json.optJSONObject("topTab"));
37
 		result.bottomTabsOptions = BottomTabsOptions.parse(json.optJSONObject("bottomTabs"));
39
 		result.bottomTabsOptions = BottomTabsOptions.parse(json.optJSONObject("bottomTabs"));
38
 		result.rightButtons = Button.parseJsonArray(json.optJSONArray("rightButtons"));
40
 		result.rightButtons = Button.parseJsonArray(json.optJSONArray("rightButtons"));
39
         result.leftButtons = Button.parseJsonArray(json.optJSONArray("leftButtons"));
41
         result.leftButtons = Button.parseJsonArray(json.optJSONArray("leftButtons"));
42
 	}
44
 	}
43
 
45
 
44
     @NonNull public TopBarOptions topBarOptions = new TopBarOptions();
46
     @NonNull public TopBarOptions topBarOptions = new TopBarOptions();
45
-    @NonNull private TopTabsOptions topTabsOptions = new TopTabsOptions();
47
+    @NonNull public TopTabsOptions topTabsOptions = new TopTabsOptions();
46
     @NonNull public TopTabOptions topTabOptions = new TopTabOptions();
48
     @NonNull public TopTabOptions topTabOptions = new TopTabOptions();
47
     @NonNull public BottomTabsOptions bottomTabsOptions = new BottomTabsOptions();
49
     @NonNull public BottomTabsOptions bottomTabsOptions = new BottomTabsOptions();
48
     public ArrayList<Button> leftButtons;
50
     public ArrayList<Button> leftButtons;

+ 9
- 1
lib/android/app/src/main/java/com/reactnativenavigation/parse/TopTabOptions.java View File

1
 package com.reactnativenavigation.parse;
1
 package com.reactnativenavigation.parse;
2
 
2
 
3
+import android.graphics.Typeface;
4
+import android.support.annotation.Nullable;
5
+
6
+import com.reactnativenavigation.utils.TypefaceLoader;
7
+
3
 import org.json.JSONObject;
8
 import org.json.JSONObject;
4
 
9
 
5
 public class TopTabOptions implements DEFAULT_VALUES {
10
 public class TopTabOptions implements DEFAULT_VALUES {
6
     public String title = NO_VALUE;
11
     public String title = NO_VALUE;
12
+    @Nullable public Typeface fontFamily;
13
+    public int tabIndex;
7
 
14
 
8
-    public static TopTabOptions parse(JSONObject json) {
15
+    public static TopTabOptions parse(TypefaceLoader typefaceManager, JSONObject json) {
9
         TopTabOptions result = new TopTabOptions();
16
         TopTabOptions result = new TopTabOptions();
10
         if (json == null) return result;
17
         if (json == null) return result;
11
 
18
 
12
         result.title = json.optString("title", NO_VALUE);
19
         result.title = json.optString("title", NO_VALUE);
20
+        result.fontFamily = typefaceManager.getTypeFace(json.optString("titleFontFamily"));
13
         return result;
21
         return result;
14
     }
22
     }
15
 
23
 

+ 7
- 2
lib/android/app/src/main/java/com/reactnativenavigation/parse/TopTabsOptions.java View File

1
 package com.reactnativenavigation.parse;
1
 package com.reactnativenavigation.parse;
2
 
2
 
3
+import android.support.annotation.Nullable;
4
+
3
 import org.json.JSONObject;
5
 import org.json.JSONObject;
4
 
6
 
5
 public class TopTabsOptions implements DEFAULT_VALUES {
7
 public class TopTabsOptions implements DEFAULT_VALUES {
6
-    public static TopTabsOptions parse(JSONObject topTabs) {
7
-        return new TopTabsOptions();
8
+
9
+    public static TopTabsOptions parse(@Nullable JSONObject json) {
10
+        TopTabsOptions result = new TopTabsOptions();
11
+        if (json == null) return result;
12
+        return result;
8
     }
13
     }
9
 
14
 
10
     void mergeWith(TopTabsOptions topTabsOptions) {
15
     void mergeWith(TopTabsOptions topTabsOptions) {

+ 12
- 4
lib/android/app/src/main/java/com/reactnativenavigation/presentation/OptionsPresenter.java View File

6
 import com.reactnativenavigation.parse.Button;
6
 import com.reactnativenavigation.parse.Button;
7
 import com.reactnativenavigation.parse.NavigationOptions;
7
 import com.reactnativenavigation.parse.NavigationOptions;
8
 import com.reactnativenavigation.parse.TopBarOptions;
8
 import com.reactnativenavigation.parse.TopBarOptions;
9
+import com.reactnativenavigation.parse.TopTabOptions;
9
 import com.reactnativenavigation.utils.TypefaceLoader;
10
 import com.reactnativenavigation.utils.TypefaceLoader;
10
 import com.reactnativenavigation.views.TopBar;
11
 import com.reactnativenavigation.views.TopBar;
11
 
12
 
23
         animator = new StackAnimator(topBar.getContext());
24
         animator = new StackAnimator(topBar.getContext());
24
     }
25
     }
25
 
26
 
26
-	public void applyOptions(NavigationOptions options) {
27
+    public void applyOptions(NavigationOptions options) {
27
         applyTopBarOptions(options.topBarOptions);
28
         applyTopBarOptions(options.topBarOptions);
28
         applyButtons(options.leftButtons, options.rightButtons);
29
         applyButtons(options.leftButtons, options.rightButtons);
29
-	}
30
+        applyTopTabOptions(options.topTabOptions);
31
+    }
30
 
32
 
31
     private void applyTopBarOptions(TopBarOptions options) {
33
     private void applyTopBarOptions(TopBarOptions options) {
32
         topBar.setTitle(options.title);
34
         topBar.setTitle(options.title);
34
         topBar.setTitleTextColor(options.textColor);
36
         topBar.setTitleTextColor(options.textColor);
35
         topBar.setTitleFontSize(options.textFontSize);
37
         topBar.setTitleFontSize(options.textFontSize);
36
 
38
 
37
-        TypefaceLoader typefaceLoader = new TypefaceLoader();
38
-        topBar.setTitleTypeface(typefaceLoader.getTypeFace(topBar.getContext(), options.textFontFamily));
39
+        TypefaceLoader typefaceLoader = new TypefaceLoader(topBar.getContext());
40
+        topBar.setTitleTypeface(typefaceLoader.getTypeFace(options.textFontFamily));
39
         if (options.hidden == NavigationOptions.BooleanOptions.True) {
41
         if (options.hidden == NavigationOptions.BooleanOptions.True) {
40
             hideTopBar(options.animateHide);
42
             hideTopBar(options.animateHide);
41
         }
43
         }
69
     private void applyButtons(ArrayList<Button> leftButtons, ArrayList<Button> rightButtons) {
71
     private void applyButtons(ArrayList<Button> leftButtons, ArrayList<Button> rightButtons) {
70
         topBar.setButtons(leftButtons, rightButtons);
72
         topBar.setButtons(leftButtons, rightButtons);
71
     }
73
     }
74
+
75
+    private void applyTopTabOptions(TopTabOptions topTabOptions) {
76
+        if (topTabOptions.fontFamily != null) {
77
+            topBar.setTopTabFontFamily(topTabOptions.tabIndex, topTabOptions.fontFamily);
78
+        }
79
+    }
72
 }
80
 }

+ 3
- 2
lib/android/app/src/main/java/com/reactnativenavigation/react/NavigationModule.java View File

15
 import com.reactnativenavigation.parse.LayoutNodeParser;
15
 import com.reactnativenavigation.parse.LayoutNodeParser;
16
 import com.reactnativenavigation.parse.NavigationOptions;
16
 import com.reactnativenavigation.parse.NavigationOptions;
17
 import com.reactnativenavigation.parse.OverlayOptions;
17
 import com.reactnativenavigation.parse.OverlayOptions;
18
+import com.reactnativenavigation.utils.TypefaceLoader;
18
 import com.reactnativenavigation.utils.UiThread;
19
 import com.reactnativenavigation.utils.UiThread;
19
 import com.reactnativenavigation.viewcontrollers.Navigator;
20
 import com.reactnativenavigation.viewcontrollers.Navigator;
20
 import com.reactnativenavigation.viewcontrollers.ViewController;
21
 import com.reactnativenavigation.viewcontrollers.ViewController;
48
 
49
 
49
 	@ReactMethod
50
 	@ReactMethod
50
 	public void setDefaultOptions(final ReadableMap options) {
51
 	public void setDefaultOptions(final ReadableMap options) {
51
-        final NavigationOptions defaultOptions = NavigationOptions.parse(JSONParser.parse(options));
52
+        final NavigationOptions defaultOptions = NavigationOptions.parse(new TypefaceLoader(activity()), JSONParser.parse(options));
52
         handle(new Runnable() {
53
         handle(new Runnable() {
53
             @Override
54
             @Override
54
             public void run() {
55
             public void run() {
59
 
60
 
60
 	@ReactMethod
61
 	@ReactMethod
61
 	public void setOptions(final String onContainerId, final ReadableMap options) {
62
 	public void setOptions(final String onContainerId, final ReadableMap options) {
62
-		final NavigationOptions navOptions = NavigationOptions.parse(JSONParser.parse(options));
63
+		final NavigationOptions navOptions = NavigationOptions.parse(new TypefaceLoader(activity()), JSONParser.parse(options));
63
 		handle(new Runnable() {
64
 		handle(new Runnable() {
64
 			@Override
65
 			@Override
65
 			public void run() {
66
 			public void run() {

+ 11
- 7
lib/android/app/src/main/java/com/reactnativenavigation/utils/TypefaceLoader.java View File

4
 import android.content.res.AssetManager;
4
 import android.content.res.AssetManager;
5
 import android.graphics.Typeface;
5
 import android.graphics.Typeface;
6
 import android.support.annotation.Nullable;
6
 import android.support.annotation.Nullable;
7
+import android.text.TextUtils;
7
 
8
 
8
 import java.io.IOException;
9
 import java.io.IOException;
9
 import java.util.Arrays;
10
 import java.util.Arrays;
13
 
14
 
14
 public class TypefaceLoader {
15
 public class TypefaceLoader {
15
 	private static final Map<String, Typeface> typefaceCache = new HashMap<>();
16
 	private static final Map<String, Typeface> typefaceCache = new HashMap<>();
17
+    private Context context;
18
+
19
+    public TypefaceLoader(Context context) {
20
+        this.context = context;
21
+    }
22
+
23
+    @Nullable
24
+	public Typeface getTypeFace(String fontFamilyName) {
25
+		if (TextUtils.isEmpty(fontFamilyName)) return null;
26
+		if (typefaceCache.containsKey(fontFamilyName)) return typefaceCache.get(fontFamilyName);
16
 
27
 
17
-	public Typeface getTypeFace(Context context, String fontFamilyName) {
18
-		if (fontFamilyName == null) {
19
-			return null;
20
-		}
21
-		if (typefaceCache.containsKey(fontFamilyName)) {
22
-			return typefaceCache.get(fontFamilyName);
23
-		}
24
 		Typeface result = load(context, fontFamilyName);
28
 		Typeface result = load(context, fontFamilyName);
25
 		typefaceCache.put(fontFamilyName, result);
29
 		typefaceCache.put(fontFamilyName, result);
26
 		return result;
30
 		return result;

+ 25
- 0
lib/android/app/src/main/java/com/reactnativenavigation/utils/ViewUtils.java View File

1
+package com.reactnativenavigation.utils;
2
+
3
+import android.support.annotation.Nullable;
4
+import android.view.View;
5
+import android.view.ViewGroup;
6
+
7
+public class ViewUtils {
8
+    @Nullable
9
+    public static <T> T findChildByClass(ViewGroup root, Class clazz) {
10
+        for (int i = 0; i < root.getChildCount(); i++) {
11
+            View view = root.getChildAt(i);
12
+            if (clazz.isAssignableFrom(view.getClass())) {
13
+                return (T) view;
14
+            }
15
+
16
+            if (view instanceof ViewGroup) {
17
+                view = findChildByClass((ViewGroup) view, clazz);
18
+                if (view != null && clazz.isAssignableFrom(view.getClass())) {
19
+                    return (T) view;
20
+                }
21
+            }
22
+        }
23
+        return null;
24
+    }
25
+}

+ 4
- 0
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabController.java View File

74
     String getTabTitle() {
74
     String getTabTitle() {
75
         return options.topTabOptions.title;
75
         return options.topTabOptions.title;
76
     }
76
     }
77
+
78
+    public void setTabIndex(int i) {
79
+        options.topTabOptions.tabIndex = i;
80
+    }
77
 }
81
 }

+ 6
- 2
lib/android/app/src/main/java/com/reactnativenavigation/views/TopBar.java View File

26
 
26
 
27
     public TopBar(final Context context, Container container) {
27
     public TopBar(final Context context, Container container) {
28
         super(context);
28
         super(context);
29
-        titleBar = new Toolbar(context);
30
         this.container = container;
29
         this.container = container;
30
+        titleBar = new Toolbar(context);
31
+        topTabs = new TopTabs(getContext());
31
         addView(titleBar);
32
         addView(titleBar);
32
     }
33
     }
33
 
34
 
57
 		}
58
 		}
58
 	}
59
 	}
59
 
60
 
61
+    public void setTopTabFontFamily(int tabIndex, Typeface fontFamily) {
62
+        topTabs.setFontFamily(tabIndex, fontFamily);
63
+    }
64
+
60
 	public void setButtons(ArrayList<Button> leftButtons, ArrayList<Button> rightButtons) {
65
 	public void setButtons(ArrayList<Button> leftButtons, ArrayList<Button> rightButtons) {
61
 		setLeftButtons(leftButtons);
66
 		setLeftButtons(leftButtons);
62
 		setRightButtons(rightButtons);
67
 		setRightButtons(rightButtons);
129
     }
134
     }
130
 
135
 
131
     private void initTopTabs() {
136
     private void initTopTabs() {
132
-        topTabs = new TopTabs(getContext());
133
         addView(topTabs);
137
         addView(topTabs);
134
     }
138
     }
135
 }
139
 }

+ 7
- 0
lib/android/app/src/main/java/com/reactnativenavigation/views/TopTabs.java View File

1
 package com.reactnativenavigation.views;
1
 package com.reactnativenavigation.views;
2
 
2
 
3
 import android.content.Context;
3
 import android.content.Context;
4
+import android.graphics.Typeface;
4
 import android.support.design.widget.TabLayout;
5
 import android.support.design.widget.TabLayout;
5
 
6
 
6
 public class TopTabs extends TabLayout {
7
 public class TopTabs extends TabLayout {
8
+    private final TopTabsStyleHelper styleHelper;
7
 
9
 
8
     public TopTabs(Context context) {
10
     public TopTabs(Context context) {
9
         super(context);
11
         super(context);
12
+        styleHelper = new TopTabsStyleHelper(this);
13
+    }
14
+
15
+    public void setFontFamily(int tabIndex, Typeface fontFamily) {
16
+        styleHelper.setFontFamily(tabIndex, fontFamily);
10
     }
17
     }
11
 }
18
 }

+ 26
- 0
lib/android/app/src/main/java/com/reactnativenavigation/views/TopTabsStyleHelper.java View File

1
+package com.reactnativenavigation.views;
2
+
3
+import android.graphics.Typeface;
4
+import android.view.ViewGroup;
5
+import android.widget.TextView;
6
+
7
+import com.reactnativenavigation.utils.ViewUtils;
8
+
9
+class TopTabsStyleHelper {
10
+    private TopTabs topTabs;
11
+
12
+    TopTabsStyleHelper(TopTabs topTabs) {
13
+        this.topTabs = topTabs;
14
+    }
15
+
16
+    void setFontFamily(int tabIndex, Typeface fontFamily) {
17
+        TextView title = ViewUtils.findChildByClass(getTabView(tabIndex), TextView.class);
18
+        if (title != null) {
19
+            title.setTypeface(fontFamily);
20
+        }
21
+    }
22
+
23
+    private ViewGroup getTabView(int tabIndex) {
24
+        return (ViewGroup) ((ViewGroup) topTabs.getChildAt(0)).getChildAt(tabIndex);
25
+    }
26
+}

+ 8
- 5
lib/android/app/src/test/java/com/reactnativenavigation/parse/NavigationOptionsTest.java View File

1
 package com.reactnativenavigation.parse;
1
 package com.reactnativenavigation.parse;
2
 
2
 
3
 import android.support.annotation.NonNull;
3
 import android.support.annotation.NonNull;
4
+import android.test.mock.MockContext;
4
 
5
 
5
 import com.reactnativenavigation.BaseTest;
6
 import com.reactnativenavigation.BaseTest;
7
+import com.reactnativenavigation.utils.TypefaceLoader;
6
 
8
 
7
 import org.json.JSONException;
9
 import org.json.JSONException;
8
 import org.json.JSONObject;
10
 import org.json.JSONObject;
24
     private static final int BOTTOM_TABS_BADGE = 3;
26
     private static final int BOTTOM_TABS_BADGE = 3;
25
     private static final String BOTTOM_TABS_CURRENT_TAB_ID = "ContainerId";
27
     private static final String BOTTOM_TABS_CURRENT_TAB_ID = "ContainerId";
26
     private static final int BOTTOM_TABS_CURRENT_TAB_INDEX = 1;
28
     private static final int BOTTOM_TABS_CURRENT_TAB_INDEX = 1;
29
+    private TypefaceLoader mockLoader = new TypefaceLoader(new MockContext());
27
 
30
 
28
     @Test
31
     @Test
29
 	public void parsesNullAsDefaultEmptyOptions() throws Exception {
32
 	public void parsesNullAsDefaultEmptyOptions() throws Exception {
30
-		assertThat(NavigationOptions.parse(null)).isNotNull();
33
+		assertThat(NavigationOptions.parse(mockLoader, null)).isNotNull();
31
 	}
34
 	}
32
 
35
 
33
 	@Test
36
 	@Test
35
 		JSONObject json = new JSONObject()
38
 		JSONObject json = new JSONObject()
36
                 .put("topBar", createTopBar())
39
                 .put("topBar", createTopBar())
37
                 .put("bottomTabs", createTabBar());
40
                 .put("bottomTabs", createTabBar());
38
-		NavigationOptions result = NavigationOptions.parse(json);
41
+		NavigationOptions result = NavigationOptions.parse(mockLoader, json);
39
         assertResult(result);
42
         assertResult(result);
40
 	}
43
 	}
41
 
44
 
100
         JSONObject json = new JSONObject();
103
         JSONObject json = new JSONObject();
101
         json.put("topBar", createTopBar());
104
         json.put("topBar", createTopBar());
102
         json.put("bottomTabs", createTabBar());
105
         json.put("bottomTabs", createTabBar());
103
-        NavigationOptions defaultOptions = NavigationOptions.parse(json);
106
+        NavigationOptions defaultOptions = NavigationOptions.parse(mockLoader, json);
104
         NavigationOptions options = new NavigationOptions();
107
         NavigationOptions options = new NavigationOptions();
105
 
108
 
106
         options.mergeWith(defaultOptions);
109
         options.mergeWith(defaultOptions);
112
         JSONObject defaultJson = new JSONObject()
115
         JSONObject defaultJson = new JSONObject()
113
             .put("topBar", createOtherTopBar())
116
             .put("topBar", createOtherTopBar())
114
             .put("bottomTabs", createOtherTabBar());
117
             .put("bottomTabs", createOtherTabBar());
115
-        NavigationOptions defaultOptions = NavigationOptions.parse(defaultJson);
118
+        NavigationOptions defaultOptions = NavigationOptions.parse(mockLoader, defaultJson);
116
 
119
 
117
         JSONObject json = new JSONObject()
120
         JSONObject json = new JSONObject()
118
                 .put("topBar", createTopBar())
121
                 .put("topBar", createTopBar())
119
                 .put("bottomTabs", createTabBar());
122
                 .put("bottomTabs", createTabBar());
120
-        NavigationOptions options = NavigationOptions.parse(json);
123
+        NavigationOptions options = NavigationOptions.parse(mockLoader, json);
121
         options.withDefaultOptions(defaultOptions);
124
         options.withDefaultOptions(defaultOptions);
122
         assertResult(options);
125
         assertResult(options);
123
     }
126
     }

+ 11
- 17
lib/android/app/src/test/java/com/reactnativenavigation/utils/TypefaceLoaderTest.java View File

9
 import org.junit.Test;
9
 import org.junit.Test;
10
 import org.mockito.Mockito;
10
 import org.mockito.Mockito;
11
 
11
 
12
-import java.io.IOException;
13
-
14
 import static org.assertj.core.api.Java6Assertions.assertThat;
12
 import static org.assertj.core.api.Java6Assertions.assertThat;
15
 
13
 
16
-/**
17
- * Created by romanko on 9/19/17.
18
- */
19
-
20
 public class TypefaceLoaderTest extends BaseTest {
14
 public class TypefaceLoaderTest extends BaseTest {
21
 
15
 
22
 	@Test
16
 	@Test
23
 	public void loadTypefaceNoAssets() {
17
 	public void loadTypefaceNoAssets() {
24
 		Context context = new MockContext();
18
 		Context context = new MockContext();
25
-		TypefaceLoader mockedLoader = Mockito.spy(TypefaceLoader.class);
19
+		TypefaceLoader mockedLoader = Mockito.spy(new TypefaceLoader(context));
26
 		Mockito.doReturn(null).when(mockedLoader).getTypefaceFromAssets(context, "Helvetica-Bold");
20
 		Mockito.doReturn(null).when(mockedLoader).getTypefaceFromAssets(context, "Helvetica-Bold");
27
 
21
 
28
-		Typeface typeface = mockedLoader.getTypeFace(context, "Helvetica-Bold");
22
+		Typeface typeface = mockedLoader.getTypeFace("Helvetica-Bold");
29
 		assertThat(typeface).isNotNull();
23
 		assertThat(typeface).isNotNull();
30
 		assertThat(typeface.getStyle()).isEqualTo(Typeface.BOLD);
24
 		assertThat(typeface.getStyle()).isEqualTo(Typeface.BOLD);
31
 	}
25
 	}
32
 
26
 
33
 	@Test
27
 	@Test
34
 	public void loadTypefaceWithAssets() {
28
 	public void loadTypefaceWithAssets() {
35
-		Context context = new MockContext();
36
-		TypefaceLoader mockedLoader = Mockito.spy(TypefaceLoader.class);
29
+        Context context = new MockContext();
30
+        TypefaceLoader mockedLoader = Mockito.spy(new TypefaceLoader(context));
37
 		Mockito.doReturn(Typeface.create("Helvetica-Italic", Typeface.ITALIC)).when(mockedLoader).getTypefaceFromAssets(context, "Helvetica-Italic");
31
 		Mockito.doReturn(Typeface.create("Helvetica-Italic", Typeface.ITALIC)).when(mockedLoader).getTypefaceFromAssets(context, "Helvetica-Italic");
38
 
32
 
39
-		Typeface typeface = mockedLoader.getTypeFace(context, "Helvetica-Italic");
33
+		Typeface typeface = mockedLoader.getTypeFace("Helvetica-Italic");
40
 		assertThat(typeface).isNotNull();
34
 		assertThat(typeface).isNotNull();
41
 		assertThat(typeface.getStyle()).isEqualTo(Typeface.ITALIC);
35
 		assertThat(typeface.getStyle()).isEqualTo(Typeface.ITALIC);
42
 	}
36
 	}
43
 
37
 
44
 	@Test
38
 	@Test
45
 	public void loadTypefaceWrongName() {
39
 	public void loadTypefaceWrongName() {
46
-		Context context = new MockContext();
47
-		TypefaceLoader mockedLoader = Mockito.spy(TypefaceLoader.class);
40
+        Context context = new MockContext();
41
+        TypefaceLoader mockedLoader = Mockito.spy(new TypefaceLoader(context));
48
 		Mockito.doReturn(null).when(mockedLoader).getTypefaceFromAssets(context, "Some-name");
42
 		Mockito.doReturn(null).when(mockedLoader).getTypefaceFromAssets(context, "Some-name");
49
 
43
 
50
-		Typeface typeface = mockedLoader.getTypeFace(context, "Some-name");
44
+		Typeface typeface = mockedLoader.getTypeFace("Some-name");
51
 		assertThat(typeface).isNotNull();
45
 		assertThat(typeface).isNotNull();
52
 		assertThat(typeface.getStyle()).isEqualTo(Typeface.NORMAL);
46
 		assertThat(typeface.getStyle()).isEqualTo(Typeface.NORMAL);
53
 	}
47
 	}
54
 
48
 
55
 	@Test
49
 	@Test
56
 	public void loadTypefaceNull() {
50
 	public void loadTypefaceNull() {
57
-		Context context = new MockContext();
58
-		TypefaceLoader mockedLoader = Mockito.spy(TypefaceLoader.class);
51
+        Context context = new MockContext();
52
+        TypefaceLoader mockedLoader = Mockito.spy(new TypefaceLoader(context));
59
 		Mockito.doReturn(null).when(mockedLoader).getTypefaceFromAssets(context, null);
53
 		Mockito.doReturn(null).when(mockedLoader).getTypefaceFromAssets(context, null);
60
 
54
 
61
-		Typeface typeface = mockedLoader.getTypeFace(context, null);
55
+		Typeface typeface = mockedLoader.getTypeFace(null);
62
 		assertThat(typeface).isNull();
56
 		assertThat(typeface).isNull();
63
 	}
57
 	}
64
 }
58
 }

+ 1
- 1
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopTabsControllerMock.java View File

7
 import java.util.Collection;
7
 import java.util.Collection;
8
 
8
 
9
 public class TopTabsControllerMock extends ParentController {
9
 public class TopTabsControllerMock extends ParentController {
10
-    public TopTabsControllerMock(Activity activity, String id) {
10
+    TopTabsControllerMock(Activity activity, String id) {
11
         super(activity, id);
11
         super(activity, id);
12
     }
12
     }
13
 
13
 

+ 13
- 0
lib/src/params/options/TopTab.js View File

1
+class TopTab {
2
+  /**
3
+   * @property {string} title The tab's title in the TopTabs view
4
+   * @property {string} [titleFontFamily] Change the tab's title font family
5
+   */
6
+  constructor(topTab) {
7
+    this.title = topTab.title;
8
+    this.titleFontFamily = topTab.titleFontFamily;
9
+  }
10
+
11
+}
12
+
13
+module.exports = TopTab;

+ 14
- 0
lib/src/params/options/TopTab.test.js View File

1
+const TopTab = require('./TopTab');
2
+
3
+const TOP_TAB = {
4
+  title: 'something',
5
+  titleFontFamily: 'Dosis-Regular'
6
+};
7
+
8
+describe('TopBar', () => {
9
+  it('Parses TopBar', () => {
10
+    const uut = new TopTab(TOP_TAB);
11
+    expect(uut.title).toEqual('something');
12
+    expect(uut.titleFontFamily).toEqual('Dosis-Regular');
13
+  });
14
+});

BIN
playground/android/app/src/main/assets/fonts/Dosis-Regular.ttf View File


+ 2
- 1
playground/src/containers/WelcomeScreen.js View File

182
           },
182
           },
183
           navigationOptions: {
183
           navigationOptions: {
184
             topTab: {
184
             topTab: {
185
-              title: 'Tab 2'
185
+              title: 'Tab 2',
186
+              titleFontFamily: 'Dosis-Regular'
186
             }
187
             }
187
           }
188
           }
188
         },
189
         },