Is it possible to make an application-wide setting for the font-size to be used by all views displaying text? I would like to provide a Preference to the user which should
Yes, it's possible. To do that you need to:
TextView
Like:
public class SimpleTextView extends TextView
{
private static final float DEFAULT_TEXT_SIZE=12.0;
private static float textSize=DEFAULT_TEXT_SIZE;
public SimpleTextView(Context context)
{
super(context);
this.setTextSize(textSize);
}
public SimpleTextView(Context context, AttributeSet attrs)
{
super(context, attrs);
this.setTextSize(textSize);
}
public SimpleTextView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
this.setTextSize(textSize);
}
public static void setGlobalSize(float size)
{
textSize=size;
}
public static float getGlobalSize()
{
return textSize;
}
}
And now whereever you're you can globally change all text sizes to 20 in all textviews just calling:
SimpleTextView.setGlobalTextSize(20);
For those who have problems with inflating views with custom attributes from @mixels answer.
If your views are in fragment, you need to apply FontStyle also in fragment's onCreateView()
or set values of these attributes in application's theme.
For more detailes see my aswer here.
Shooting from the hip here's idea to consider (no custom TextView implementation required)
onCreate
method of each of your Activities get value of that property and save as a fieldAlong the same lines, say you want to make this to work dynamically? Create a simple class (say TextSetter) that holds internal list and have 3 methods: add, remove and setSize
Activity#onCreate
identify each control you want to adjust and use TextSetter#set
to add it to the listHere it's how I made it for my app.
In a few words - in Activity.onCreate()
you get resource id of style with specific set of font sizes and apply this style to theme of activity. Then with preferences activity you can switch between these sets.
First of all in values/attrs.xml declare attributes for set of font sizes:
<declare-styleable name="FontStyle">
<attr name="font_small" format="dimension" />
<attr name="font_medium" format="dimension" />
<attr name="font_large" format="dimension" />
<attr name="font_xlarge" format="dimension" />
</declare-styleable>
Then in values/styles.xml declare few sets of font sizes:
<style name="FontStyle">
</style>
<style name="FontStyle.Small">
<item name="font_small">14sp</item>
<item name="font_medium">16sp</item>
<item name="font_large">18sp</item>
<item name="font_xlarge">20sp</item>
</style>
<style name="FontStyle.Medium">
<item name="font_small">18sp</item>
<item name="font_medium">20sp</item>
<item name="font_large">22sp</item>
<item name="font_xlarge">24sp</item>
</style>
<style name="FontStyle.Large">
<item name="font_small">26sp</item>
<item name="font_medium">28sp</item>
<item name="font_large">30sp</item>
<item name="font_xlarge">32sp</item>
</style>
Then in onCreate()
method of every activity add:
getTheme().applyStyle(new Preferences(this).getFontStyle().getResId(), true);
where Preferences
is a facade to SharedPreferences
object:
public class Preferences {
private final static String FONT_STYLE = "FONT_STYLE";
private final Context context;
public Preferences(Context context) {
this.context = context;
}
protected SharedPreferences open() {
return context.getSharedPreferences("prefs", Context.MODE_PRIVATE);
}
protected Editor edit() {
return open().edit();
}
public FontStyle getFontStyle() {
return FontStyle.valueOf(open().getString(FONT_STYLE,
FontStyle.Medium.name()));
}
public void setFontStyle(FontStyle style) {
edit().putString(FONT_STYLE, style.name()).commit();
}
}
and FontStyle is:
public enum FontStyle {
Small(R.style.FontStyle_Small, "Small"),
Medium(R.style.FontStyle_Medium, "Medium"),
Large(R.style.FontStyle_Large, "Large");
private int resId;
private String title;
public int getResId() {
return resId;
}
public String getTitle() {
return title;
}
FontStyle(int resId, String title) {
this.resId = resId;
this.title = title;
}
}
And FontStyle.values()
is used as items for Spinner
in your PreferencesActivity
.
That's how mine looks like:
public class PreferencesActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
getTheme().applyStyle(new Preferences(this).getFontStyle().getResId(), true);
super.onCreate(savedInstanceState);
setContentView(R.layout.preferences);
Preferences prefs = new Preferences(this);
Spinner fontStylesView = (Spinner) findViewById(R.id.font_styles);
FontStylesAdapter adapter = new FontStylesAdapter(this,
R.layout.font_styles_row, FontStyle.values());
fontStylesView.setAdapter(adapter);
fontStylesView.setSelection(prefs.getFontStyle().ordinal());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.preferences, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_done:
onMenuDone();
finish();
return true;
case R.id.menu_cancel:
finish();
return true;
default:
return false;
}
}
private void onMenuDone() {
Preferences prefs = new Preferences(this);
Spinner fontStylesView = (Spinner) findViewById(R.id.font_styles);
prefs.setFontStyle((FontStyle) fontStylesView.getSelectedItem());
}
}
And finally you can use your font size preferences:
<TextView android:textSize="?attr/font_large" />
Or I prefer using styles, in values/styles.xml add:
<style name="Label" parent="@android:style/Widget.TextView">
<item name="android:textSize">?attr/font_medium</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
</style>
<style name="Label.XLarge">
<item name="android:textSize">?attr/font_xlarge</item>
</style>
And you can use it in this way:
<TextView style="@style/Label.XLarge" />
I hope my answer will help you.