4
4
import android .content .res .ColorStateList ;
5
5
import android .content .res .Resources ;
6
6
import android .graphics .Color ;
7
+ import android .graphics .Paint ;
8
+ import android .graphics .Typeface ;
7
9
import android .graphics .drawable .Drawable ;
8
10
import android .os .Build ;
9
11
import android .text .SpannableString ;
10
12
import android .text .Spanned ;
13
+ import android .text .TextPaint ;
11
14
import android .text .style .ForegroundColorSpan ;
15
+ import android .text .style .TypefaceSpan ;
12
16
import android .view .GestureDetector ;
13
17
import android .view .Menu ;
14
18
import android .view .MenuItem ;
34
38
35
39
public class ContextMenuView extends ReactViewGroup implements View .OnCreateContextMenuListener {
36
40
@ Nullable ReadableArray actions ;
41
+ @ Nullable private String fontName ; // Default font name
37
42
38
43
boolean cancelled = true ;
39
44
@@ -45,6 +50,46 @@ public class ContextMenuView extends ReactViewGroup implements View.OnCreateCont
45
50
46
51
private GestureDetector gestureDetector ;
47
52
53
+ private static class CustomTypefaceSpan extends TypefaceSpan {
54
+ private final Typeface newType ;
55
+
56
+ public CustomTypefaceSpan (String family , Typeface type ) {
57
+ super (family );
58
+ newType = type ;
59
+ }
60
+
61
+ @ Override
62
+ public void updateDrawState (TextPaint ds ) {
63
+ applyCustomTypeFace (ds , newType );
64
+ }
65
+
66
+ @ Override
67
+ public void updateMeasureState (TextPaint paint ) {
68
+ applyCustomTypeFace (paint , newType );
69
+ }
70
+
71
+ private static void applyCustomTypeFace (Paint paint , Typeface tf ) {
72
+ int oldStyle ;
73
+ Typeface old = paint .getTypeface ();
74
+ if (old == null ) {
75
+ oldStyle = 0 ;
76
+ } else {
77
+ oldStyle = old .getStyle ();
78
+ }
79
+
80
+ int fake = oldStyle & ~tf .getStyle ();
81
+ if ((fake & Typeface .BOLD ) != 0 ) {
82
+ paint .setFakeBoldText (true );
83
+ }
84
+
85
+ if ((fake & Typeface .ITALIC ) != 0 ) {
86
+ paint .setTextSkewX (-0.25f );
87
+ }
88
+
89
+ paint .setTypeface (tf );
90
+ }
91
+ }
92
+
48
93
public ContextMenuView (final Context context ) {
49
94
super (context );
50
95
@@ -142,9 +187,36 @@ public void setDisabled(@Nullable boolean disabled) {
142
187
this .disabled = disabled ;
143
188
}
144
189
190
+ public void setFontName (@ Nullable String fontName ) {
191
+ this .fontName = fontName ;
192
+ }
193
+
194
+ private Typeface getCustomFont () {
195
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .P && fontName != null ) {
196
+ try {
197
+ Resources resources = getContext ().getResources ();
198
+ int fontId = resources .getIdentifier (fontName , "font" , getContext ().getPackageName ());
199
+ if (fontId != 0 ) {
200
+ return ResourcesCompat .getFont (getContext (), fontId );
201
+ }
202
+ } catch (Exception e ) {
203
+ // Fallback to default font if custom font is not available
204
+ }
205
+ }
206
+ return null ;
207
+ }
208
+
145
209
private void createContextMenuSubMenu (Menu menu , ReadableMap action , ReadableArray childActions , int i ) {
146
210
String title = action .getString ("title" );
147
- Menu parentMenu = menu .addSubMenu (title );
211
+
212
+ // Apply custom font to submenu title
213
+ SpannableString spannableTitle = new SpannableString (title );
214
+ Typeface customFont = getCustomFont ();
215
+ if (customFont != null ) {
216
+ spannableTitle .setSpan (new CustomTypefaceSpan ("" , customFont ), 0 , title .length (), Spanned .SPAN_EXCLUSIVE_INCLUSIVE );
217
+ }
218
+
219
+ Menu parentMenu = menu .addSubMenu (spannableTitle );
148
220
149
221
@ Nullable Drawable icon = getResourceWithName (getContext (), action .getString ("icon" ));
150
222
menu .getItem (i ).setIcon (icon ); // set icon to current item.
@@ -160,7 +232,14 @@ private void createContextMenuAction(Menu menu, ReadableMap action, int i, int p
160
232
String title = action .getString ("title" );
161
233
@ Nullable Drawable icon = getResourceWithName (getContext (), action .getString ("icon" ));
162
234
163
- MenuItem item = menu .add (Menu .NONE , Menu .NONE , i , title );
235
+ // Create spannable string with custom font
236
+ SpannableString spannableTitle = new SpannableString (title );
237
+ Typeface customFont = getCustomFont ();
238
+ if (customFont != null ) {
239
+ spannableTitle .setSpan (new CustomTypefaceSpan ("" , customFont ), 0 , title .length (), Spanned .SPAN_EXCLUSIVE_INCLUSIVE );
240
+ }
241
+
242
+ MenuItem item = menu .add (Menu .NONE , Menu .NONE , i , spannableTitle );
164
243
item .setEnabled (!action .hasKey ("disabled" ) || !action .getBoolean ("disabled" ));
165
244
166
245
if (action .hasKey ("iconColor" ) && icon != null ) {
@@ -172,7 +251,7 @@ private void createContextMenuAction(Menu menu, ReadableMap action, int i, int p
172
251
if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .O ) {
173
252
item .setIconTintList (ColorStateList .valueOf (Color .RED ));
174
253
}
175
- SpannableString redTitle = new SpannableString (title );
254
+ SpannableString redTitle = new SpannableString (spannableTitle );
176
255
redTitle .setSpan (new ForegroundColorSpan (Color .RED ), 0 , title .length (), Spanned .SPAN_EXCLUSIVE_EXCLUSIVE );
177
256
item .setTitle (redTitle );
178
257
}
0 commit comments