Skip to content

Commit 7392dea

Browse files
committed
Each CalligraphyContext can have its own CalligraphyConfig
Useful when Calligraphy is used in a library project where the default configuration need not be changed, or when different defaults are needed in multiple contexts.
1 parent 417120b commit 7392dea

File tree

8 files changed

+195
-24
lines changed

8 files changed

+195
-24
lines changed

CalligraphySample/src/main/java/uk/co/chrisjenx/calligraphy/sample/PlaceholderFragment.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package uk.co.chrisjenx.calligraphy.sample;
22

33
import android.app.AlertDialog;
4+
import android.content.Context;
45
import android.content.DialogInterface;
56
import android.os.Bundle;
67
import android.support.v4.app.Fragment;
@@ -12,6 +13,8 @@
1213

1314
import butterknife.ButterKnife;
1415
import butterknife.OnClick;
16+
import uk.co.chrisjenx.calligraphy.CalligraphyConfig;
17+
import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper;
1518

1619
/**
1720
* A placeholder fragment containing a simple view.
@@ -57,4 +60,19 @@ public void onClick(DialogInterface dialog, int which) {
5760
});
5861
builder.create().show();
5962
}
63+
64+
@OnClick(R.id.button_non_default_config)
65+
public void onClickNonDefaultConfig() {
66+
final Context calligraphyContext =
67+
CalligraphyContextWrapper.wrap(getActivity(), new CalligraphyConfig.Builder()
68+
.setDefaultFontPath("fonts/Oswald-Stencbab.ttf")
69+
.setFontAttrId(R.attr.fontPath)
70+
.addCustomViewWithSetTypeface(CustomViewWithTypefaceSupport.class)
71+
.addCustomStyle(TextField.class, R.attr.textFieldStyle)
72+
.build());
73+
new android.support.v7.app.AlertDialog.Builder(calligraphyContext)
74+
.setTitle(R.string.dialog_non_default_config_title)
75+
.setView(R.layout.dialog_non_default_config)
76+
.show();
77+
}
6078
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<ScrollView
2+
xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools"
4+
android:layout_width="match_parent"
5+
android:layout_height="match_parent"
6+
android:fillViewport="true">
7+
8+
<LinearLayout
9+
android:layout_width="match_parent"
10+
android:layout_height="wrap_content"
11+
android:orientation="vertical"
12+
android:paddingBottom="@dimen/activity_vertical_margin"
13+
android:paddingLeft="@dimen/activity_horizontal_margin"
14+
android:paddingRight="@dimen/activity_horizontal_margin"
15+
android:paddingTop="@dimen/activity_vertical_margin"
16+
tools:context="uk.co.chrisjenx.calligraphy.sample.PlaceholderFragment"
17+
tools:ignore="MissingPrefix">
18+
19+
<TextView
20+
android:layout_width="wrap_content"
21+
android:layout_height="wrap_content"
22+
android:textSize="18sp"
23+
android:text="@string/dialog_non_default_config_message"/>
24+
25+
<TextView
26+
android:layout_width="wrap_content"
27+
android:layout_height="wrap_content"
28+
android:text="@string/default_theme"/>
29+
30+
<TextView
31+
fontPath="fonts/Roboto-Bold.ttf"
32+
android:layout_width="wrap_content"
33+
android:layout_height="wrap_content"
34+
android:text="@string/defined_fontpath_view"/>
35+
36+
<TextView
37+
fontPath="fonts/Roboto-None.ttf"
38+
android:layout_width="wrap_content"
39+
android:layout_height="wrap_content"
40+
android:text="@string/defined_incorrect"/>
41+
42+
<TextView
43+
style="@style/AppTheme.Widget.TextView.Style"
44+
android:layout_width="wrap_content"
45+
android:layout_height="wrap_content"
46+
android:text="@string/defined_in_style"/>
47+
48+
<TextView
49+
style="@style/AppTheme.Widget.TextViewAppearanceStyle"
50+
android:layout_width="wrap_content"
51+
android:layout_height="wrap_content"
52+
android:text="@string/defined_in_appears_style"/>
53+
54+
<TextView
55+
android:layout_width="wrap_content"
56+
android:layout_height="wrap_content"
57+
android:text="@string/defined_in_appears"
58+
android:textAppearance="@style/TextAppearance.FontPathView"/>
59+
60+
<TextView
61+
android:layout_width="wrap_content"
62+
android:layout_height="wrap_content"
63+
android:ellipsize="end"
64+
android:singleLine="true"
65+
android:text="@string/defined_in_appears"
66+
android:textAppearance="@style/TextAppearance.FontPathView"/>
67+
68+
<TextView
69+
android:layout_width="wrap_content"
70+
android:layout_height="wrap_content"
71+
android:text="@string/defined_in_appears_caps"
72+
android:textAllCaps="true"
73+
android:textAppearance="@style/TextAppearance.FontPathView"/>
74+
75+
<uk.co.chrisjenx.calligraphy.sample.CustomTextView
76+
fontPath="fonts/Oswald-Stencbab.ttf"
77+
android:layout_width="wrap_content"
78+
android:layout_height="wrap_content"
79+
android:text="@string/defined_custom_view"/>
80+
81+
<uk.co.chrisjenx.calligraphy.sample.CustomViewWithTypefaceSupport
82+
fontPath="fonts/Oswald-Stencbab.ttf"
83+
android:layout_width="wrap_content"
84+
android:layout_height="wrap_content" />
85+
86+
<CheckBox
87+
fontPath="fonts/Oswald-Stencbab.ttf"
88+
android:layout_width="match_parent"
89+
android:layout_height="wrap_content"
90+
android:layout_marginBottom="16dp"
91+
android:layout_marginTop="16dp"
92+
android:text="@string/checkbox_custom"/>
93+
94+
<EditText
95+
android:id="@+id/edit_text"
96+
fontPath="fonts/Roboto-Bold.ttf"
97+
android:layout_width="match_parent"
98+
android:layout_height="wrap_content"
99+
android:layout_marginBottom="16dp"
100+
android:layout_marginTop="16dp"
101+
android:hint="@string/edit_text_hint"/>
102+
103+
<uk.co.chrisjenx.calligraphy.sample.TextField
104+
android:layout_width="match_parent"
105+
android:layout_height="wrap_content"
106+
android:text="@string/custom_view_style_text"/>
107+
108+
</LinearLayout>
109+
</ScrollView>

CalligraphySample/src/main/res/layout/fragment_main.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,5 +128,14 @@
128128
android:layout_marginTop="12dp"
129129
android:text="@string/button_defined"/>
130130

131+
<Button
132+
android:id="@+id/button_non_default_config"
133+
fontPath="fonts/Roboto-Bold.ttf"
134+
android:layout_width="wrap_content"
135+
android:layout_height="wrap_content"
136+
android:layout_gravity="center_horizontal"
137+
android:layout_marginTop="12dp"
138+
android:text="@string/button_non_default_config"/>
139+
131140
</LinearLayout>
132141
</ScrollView>

CalligraphySample/src/main/res/values/strings.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,8 @@
2222

2323
<string name="button_default">Default Font (show dialog)</string>
2424
<string name="button_defined">Bold Button (show toast)</string>
25+
<string name="button_non_default_config">Context specific Calligraphy config (show dialog)</string>
26+
<string name="dialog_non_default_config_title">Context specific Calligraphy config</string>
27+
<string name="dialog_non_default_config_message">\nUsing non-global Calligraphy config for this dialog with Oswald as the default font.\n</string>
2528

2629
</resources>

calligraphy/src/main/java/uk/co/chrisjenx/calligraphy/CalligraphyConfig.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package uk.co.chrisjenx.calligraphy;
22

3+
import android.content.Context;
34
import android.os.Build;
45
import android.text.TextUtils;
56
import android.view.View;
@@ -74,7 +75,7 @@ public static void initDefault(CalligraphyConfig calligraphyConfig) {
7475
}
7576

7677
/**
77-
* The current Calligraphy Config.
78+
* The default Calligraphy config.
7879
* If not set it will create a default config.
7980
*/
8081
public static CalligraphyConfig get() {
@@ -83,6 +84,19 @@ public static CalligraphyConfig get() {
8384
return sInstance;
8485
}
8586

87+
/**
88+
* Obtains the CalligraphyConfig from the given context.
89+
*/
90+
static CalligraphyConfig from(Context context) {
91+
//noinspection ResourceType
92+
final CalligraphyConfig config = (CalligraphyConfig) context
93+
.getSystemService(CalligraphyContextWrapper.CALLIGRAPHY_CONFIG_SERVICE);
94+
if (config == null) {
95+
throw new AssertionError("CalligraphyConfig not found.");
96+
}
97+
return config;
98+
}
99+
86100
/**
87101
* Is a default font set?
88102
*/

calligraphy/src/main/java/uk/co/chrisjenx/calligraphy/CalligraphyContextWrapper.java

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,38 @@
1313
*/
1414
public class CalligraphyContextWrapper extends ContextWrapper {
1515

16+
static final String CALLIGRAPHY_CONFIG_SERVICE = CalligraphyConfig.class.getName();
17+
1618
private CalligraphyLayoutInflater mInflater;
1719

1820
private final int mAttributeId;
21+
private final CalligraphyConfig mCalligraphyConfig;
1922

2023
/**
21-
* Uses the default configuration from {@link uk.co.chrisjenx.calligraphy.CalligraphyConfig}
24+
* Convenience for calling {@link #wrap(Context, CalligraphyConfig)} with the
25+
* {@linkplain CalligraphyConfig#get default configuration}.
2226
*
2327
* Remember if you are defining default in the
2428
* {@link uk.co.chrisjenx.calligraphy.CalligraphyConfig} make sure this is initialised before
2529
* the activity is created.
26-
*
27-
* @param base ContextBase to Wrap.
28-
* @return ContextWrapper to pass back to the activity.
2930
*/
3031
public static ContextWrapper wrap(Context base) {
31-
return new CalligraphyContextWrapper(base);
32+
return wrap(base, CalligraphyConfig.get());
33+
}
34+
35+
/**
36+
* Configures Calligraphy to be used in the {@code context} with the provided {@code config}.
37+
*
38+
* <p>You would rarely need to use this method directly, so unless you need a different
39+
* configuration in multiple contexts in you app, prefer defining a
40+
* {@linkplain CalligraphyConfig#initDefault default configuration} and use
41+
* {@link #wrap(Context)} instead.
42+
*
43+
* @return Context to use as the {@linkplain Activity#attachBaseContext base context} of your
44+
* Activity or for initializing a view hierarchy.
45+
*/
46+
public static ContextWrapper wrap(Context base, CalligraphyConfig config) {
47+
return new CalligraphyContextWrapper(base, config);
3248
}
3349

3450
/**
@@ -72,18 +88,10 @@ static CalligraphyActivityFactory get(Activity activity) {
7288
return (CalligraphyActivityFactory) activity.getLayoutInflater();
7389
}
7490

75-
/**
76-
* Uses the default configuration from {@link uk.co.chrisjenx.calligraphy.CalligraphyConfig}
77-
*
78-
* Remember if you are defining default in the
79-
* {@link uk.co.chrisjenx.calligraphy.CalligraphyConfig} make sure this is initialised before
80-
* the activity is created.
81-
*
82-
* @param base ContextBase to Wrap
83-
*/
84-
CalligraphyContextWrapper(Context base) {
91+
CalligraphyContextWrapper(Context base, CalligraphyConfig config) {
8592
super(base);
86-
mAttributeId = CalligraphyConfig.get().getAttrId();
93+
mAttributeId = config.getAttrId();
94+
mCalligraphyConfig = config;
8795
}
8896

8997
/**
@@ -102,6 +110,7 @@ static CalligraphyActivityFactory get(Activity activity) {
102110
public CalligraphyContextWrapper(Context base, int attributeId) {
103111
super(base);
104112
mAttributeId = attributeId;
113+
mCalligraphyConfig = null;
105114
}
106115

107116
@Override
@@ -112,6 +121,9 @@ public Object getSystemService(String name) {
112121
}
113122
return mInflater;
114123
}
124+
if (CALLIGRAPHY_CONFIG_SERVICE.equals(name)) {
125+
return mCalligraphyConfig != null ? mCalligraphyConfig : CalligraphyConfig.get();
126+
}
115127
return super.getSystemService(name);
116128
}
117129

calligraphy/src/main/java/uk/co/chrisjenx/calligraphy/CalligraphyFactory.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,10 @@ protected static int[] getStyleForTextView(TextView view) {
3636
styleIds[1] = android.R.attr.subtitleTextStyle;
3737
}
3838
if (styleIds[0] == -1) {
39+
final CalligraphyConfig config = CalligraphyConfig.from(view.getContext());
3940
// Use TextAppearance as default style
40-
styleIds[0] = CalligraphyConfig.get().getClassStyles().containsKey(view.getClass())
41-
? CalligraphyConfig.get().getClassStyles().get(view.getClass())
41+
styleIds[0] = config.getClassStyles().containsKey(view.getClass())
42+
? config.getClassStyles().get(view.getClass())
4243
: android.R.attr.textAppearance;
4344
}
4445
return styleIds;
@@ -117,6 +118,7 @@ public View onViewCreated(View view, Context context, AttributeSet attrs) {
117118
}
118119

119120
void onViewCreatedInternal(View view, final Context context, AttributeSet attrs) {
121+
final CalligraphyConfig config = CalligraphyConfig.from(context);
120122
if (view instanceof TextView) {
121123
// Fast path the setting of TextView's font, means if we do some delayed setting of font,
122124
// which has already been set by use we skip this TextView (mainly for inflating custom,
@@ -142,7 +144,7 @@ void onViewCreatedInternal(View view, final Context context, AttributeSet attrs)
142144
// Still need to defer the Native action bar, appcompat-v7:21+ uses the Toolbar underneath. But won't match these anyway.
143145
final boolean deferred = matchesResourceIdName(view, ACTION_BAR_TITLE) || matchesResourceIdName(view, ACTION_BAR_SUBTITLE);
144146

145-
CalligraphyUtils.applyFontToTextView(context, (TextView) view, CalligraphyConfig.get(), textViewFont, deferred);
147+
CalligraphyUtils.applyFontToTextView(context, (TextView) view, config, textViewFont, deferred);
146148
}
147149

148150
// AppCompat API21+ The ActionBar doesn't inflate default Title/SubTitle, we need to scan the
@@ -178,7 +180,7 @@ public void onGlobalLayout() {
178180
if (typeface != null) {
179181
((HasTypeface) view).setTypeface(typeface);
180182
}
181-
} else if (CalligraphyConfig.get().isCustomViewTypefaceSupport() && CalligraphyConfig.get().isCustomViewHasTypeface(view)) {
183+
} else if (config.isCustomViewTypefaceSupport() && config.isCustomViewHasTypeface(view)) {
182184
final Method setTypeface = ReflectionUtils.getMethod(view.getClass(), "setTypeface");
183185
String fontPath = resolveFontPath(context, attrs);
184186
Typeface typeface = getDefaultTypeface(context, fontPath);
@@ -190,7 +192,7 @@ public void onGlobalLayout() {
190192

191193
private Typeface getDefaultTypeface(Context context, String fontPath) {
192194
if (TextUtils.isEmpty(fontPath)) {
193-
fontPath = CalligraphyConfig.get().getFontPath();
195+
fontPath = CalligraphyConfig.from(context).getFontPath();
194196
}
195197
if (!TextUtils.isEmpty(fontPath)) {
196198
return TypefaceUtils.load(context.getAssets(), fontPath);

calligraphy/src/main/java/uk/co/chrisjenx/calligraphy/CalligraphyLayoutInflater.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import android.content.Context;
55
import android.os.Build;
66
import android.util.AttributeSet;
7+
import android.util.Log;
78
import android.view.LayoutInflater;
89
import android.view.View;
910
import android.view.ViewGroup;
@@ -26,6 +27,7 @@ class CalligraphyLayoutInflater extends LayoutInflater implements CalligraphyAct
2627

2728
private final int mAttributeId;
2829
private final CalligraphyFactory mCalligraphyFactory;
30+
private final CalligraphyConfig mCalligraphyConfig;
2931
// Reflection Hax
3032
private boolean mSetPrivateFactory = false;
3133
private Field mConstructorArgs = null;
@@ -34,12 +36,14 @@ protected CalligraphyLayoutInflater(Context context, int attributeId) {
3436
super(context);
3537
mAttributeId = attributeId;
3638
mCalligraphyFactory = new CalligraphyFactory(attributeId);
39+
mCalligraphyConfig = CalligraphyConfig.from(context);
3740
setUpLayoutFactories(false);
3841
}
3942

4043
protected CalligraphyLayoutInflater(LayoutInflater original, Context newContext, int attributeId, final boolean cloned) {
4144
super(original, newContext);
4245
mAttributeId = attributeId;
46+
mCalligraphyConfig = CalligraphyConfig.from(newContext);
4347
mCalligraphyFactory = new CalligraphyFactory(attributeId);
4448
setUpLayoutFactories(cloned);
4549
}
@@ -105,7 +109,7 @@ private void setPrivateFactoryInternal() {
105109
// Already tried to set the factory.
106110
if (mSetPrivateFactory) return;
107111
// Reflection (Or Old Device) skip.
108-
if (!CalligraphyConfig.get().isReflection()) return;
112+
if (!mCalligraphyConfig.isReflection()) return;
109113
// Skip if not attached to an activity.
110114
if (!(getContext() instanceof Factory2)) {
111115
mSetPrivateFactory = true;
@@ -195,7 +199,7 @@ private View createCustomViewInternal(View parent, View view, String name, Conte
195199
// significant difference to performance on Android 4.0+.
196200

197201
// If CustomViewCreation is off skip this.
198-
if (!CalligraphyConfig.get().isCustomViewCreation()) return view;
202+
if (!mCalligraphyConfig.isCustomViewCreation()) return view;
199203
if (view == null && name.indexOf('.') > -1) {
200204
if (mConstructorArgs == null)
201205
mConstructorArgs = ReflectionUtils.getField(LayoutInflater.class, "mConstructorArgs");

0 commit comments

Comments
 (0)