diff options
author | p4r4n01d <p4r4n01d42@gmail.com> | 2013-11-16 13:47:34 +1100 |
---|---|---|
committer | Adnan Begovic <adnan@cyngn.com> | 2015-10-29 17:36:29 -0700 |
commit | af88d809c0354ef2551050b2ea74cb85dc8ef056 (patch) | |
tree | e2550c435d4255d3e720b8590232b5781ad451bd | |
parent | e0c17471b56570ca7c65527345d2b97331204b50 (diff) | |
download | packages_apps_Settings-af88d809c0354ef2551050b2ea74cb85dc8ef056.zip packages_apps_Settings-af88d809c0354ef2551050b2ea74cb85dc8ef056.tar.gz packages_apps_Settings-af88d809c0354ef2551050b2ea74cb85dc8ef056.tar.bz2 |
Display Settings: Better font size control
Use a SeekBar instead of a list/spinner to determine the font scaling.
For consistency, an approximate size (small, normal, etc.)
and the exact percentage are displayed.
Show a preview of the selected font size immediately
Ported from CM 10.2, squashed commits 46678 and 49167.
Credit to Veeti Paaananen for the latter commit.
Change-Id: I754d7fdcaf27c23dfccf9d56291956e70b23f63e
-rw-r--r-- | res/layout/preference_dialog_fontsize.xml | 54 | ||||
-rw-r--r-- | res/values/attrs.xml | 7 | ||||
-rw-r--r-- | res/values/cm_strings.xml | 4 | ||||
-rw-r--r-- | res/xml/display_settings.xml | 4 | ||||
-rw-r--r-- | src/com/android/settings/Display.java | 138 | ||||
-rw-r--r-- | src/com/android/settings/DisplaySettings.java | 51 | ||||
-rw-r--r-- | src/com/android/settings/FontDialogPreference.java | 156 | ||||
-rw-r--r-- | src/com/android/settings/IntervalSeekBar.java | 87 |
8 files changed, 327 insertions, 174 deletions
diff --git a/res/layout/preference_dialog_fontsize.xml b/res/layout/preference_dialog_fontsize.xml new file mode 100644 index 0000000..f209d46 --- /dev/null +++ b/res/layout/preference_dialog_fontsize.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2008 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:settings="http://schemas.android.com/apk/res/com.android.settings" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:padding="12dp"> + + <!-- Static height enough to accommodate the text views in their biggest possible size, + without having the dialog resize itself at any point. --> + <LinearLayout android:id="@+id/container" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="64dp" + android:gravity="center_horizontal|center_vertical"> + + <TextView android:id="@+id/description" + android:text="@string/font_size_sample" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:textAppearanceLarge" /> + + <TextView android:id="@+id/percentage" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:textAppearanceSmall" /> + + </LinearLayout> + + <com.android.settings.IntervalSeekBar android:id="@+id/font_size" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:padding="8dp" + android:layout_below="@+id/container" + settings:min="0.85" + settings:max="1.30" + settings:defaultValue="1.00" + settings:digits="2" /> + +</RelativeLayout> diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 4b607be..d774622 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -118,4 +118,11 @@ <attr name="android:entries" /> <attr name="android:entryValues" /> </declare-styleable> + + <declare-styleable name="IntervalSeekBar"> + <attr name="min" format="float" /> + <attr name="max" format="float" /> + <attr name="defaultValue" format="float" /> + <attr name="digits" format="integer" /> + </declare-styleable> </resources> diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml index 49672e2..329f657 100644 --- a/res/values/cm_strings.xml +++ b/res/values/cm_strings.xml @@ -417,4 +417,8 @@ <!-- Turn on display when power connected; turn off display when power disconnected --> <string name="wake_when_plugged_or_unplugged_title">Wake on plug</string> <string name="wake_when_plugged_or_unplugged_summary">Turn the screen on when connecting or disconnecting a power source</string> + + <!-- Font size sample text. This needs to be a very short string, as it is shown in + multiple font sizes in a limited amount of space. --> + <string name="font_size_sample">Sample</string> </resources> diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml index 3912d37..1963055 100644 --- a/res/xml/display_settings.xml +++ b/res/xml/display_settings.xml @@ -79,13 +79,11 @@ android:summary="@string/tap_to_wake_summary" android:persistent="false" /> - <com.android.settings.WarnedListPreference + <com.android.settings.FontDialogPreference android:key="font_size" android:title="@string/title_font_size" settings:keywords="@string/keywords_display_font_size" android:summary="@string/summary_font_size" - android:entries="@array/entries_font_size" - android:entryValues="@array/entryvalues_font_size" android:dialogTitle="@string/dialog_title_font_size" /> <com.android.settings.DropDownPreference diff --git a/src/com/android/settings/Display.java b/src/com/android/settings/Display.java deleted file mode 100644 index fa29318..0000000 --- a/src/com/android/settings/Display.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings; - -import android.app.Activity; -import android.app.ActivityManagerNative; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.os.Bundle; -import android.os.RemoteException; -import android.util.DisplayMetrics; -import android.util.TypedValue; -import android.view.View; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.Spinner; -import android.widget.TextView; - - -public class Display extends Activity implements View.OnClickListener { - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - - setContentView(R.layout.display); - - mFontSize = (Spinner) findViewById(R.id.fontSize); - mFontSize.setOnItemSelectedListener(mFontSizeChanged); - String[] states = new String[3]; - Resources r = getResources(); - states[0] = r.getString(R.string.small_font); - states[1] = r.getString(R.string.medium_font); - states[2] = r.getString(R.string.large_font); - ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, - android.R.layout.simple_spinner_item, states); - adapter.setDropDownViewResource( - android.R.layout.simple_spinner_dropdown_item); - mFontSize.setAdapter(adapter); - - mPreview = (TextView) findViewById(R.id.preview); - mPreview.setText(r.getText(R.string.font_size_preview_text)); - - Button save = (Button) findViewById(R.id.save); - save.setText(r.getText(R.string.font_size_save)); - save.setOnClickListener(this); - - mTextSizeTyped = new TypedValue(); - TypedArray styledAttributes = - obtainStyledAttributes(android.R.styleable.TextView); - styledAttributes.getValue(android.R.styleable.TextView_textSize, - mTextSizeTyped); - - DisplayMetrics metrics = getResources().getDisplayMetrics(); - mDisplayMetrics = new DisplayMetrics(); - mDisplayMetrics.density = metrics.density; - mDisplayMetrics.heightPixels = metrics.heightPixels; - mDisplayMetrics.scaledDensity = metrics.scaledDensity; - mDisplayMetrics.widthPixels = metrics.widthPixels; - mDisplayMetrics.xdpi = metrics.xdpi; - mDisplayMetrics.ydpi = metrics.ydpi; - - styledAttributes.recycle(); - } - - @Override - public void onResume() { - super.onResume(); - try { - mCurConfig.updateFrom( - ActivityManagerNative.getDefault().getConfiguration()); - } catch (RemoteException e) { - } - if (mCurConfig.fontScale < 1) { - mFontSize.setSelection(0); - } else if (mCurConfig.fontScale > 1) { - mFontSize.setSelection(2); - } else { - mFontSize.setSelection(1); - } - updateFontScale(); - } - - private void updateFontScale() { - mDisplayMetrics.scaledDensity = mDisplayMetrics.density * - mCurConfig.fontScale; - - float size = mTextSizeTyped.getDimension(mDisplayMetrics); - mPreview.setTextSize(TypedValue.COMPLEX_UNIT_PX, size); - } - - public void onClick(View v) { - try { - ActivityManagerNative.getDefault().updatePersistentConfiguration(mCurConfig); - } catch (RemoteException e) { - } - finish(); - } - - private Spinner.OnItemSelectedListener mFontSizeChanged - = new Spinner.OnItemSelectedListener() { - public void onItemSelected(android.widget.AdapterView av, View v, - int position, long id) { - if (position == 0) { - mCurConfig.fontScale = .75f; - } else if (position == 2) { - mCurConfig.fontScale = 1.25f; - } else { - mCurConfig.fontScale = 1.0f; - } - - updateFontScale(); - } - - public void onNothingSelected(android.widget.AdapterView av) { - } - }; - - private Spinner mFontSize; - private TextView mPreview; - private TypedValue mTextSizeTyped; - private DisplayMetrics mDisplayMetrics; - private Configuration mCurConfig = new Configuration(); -} diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java index 01eed08..66af458 100644 --- a/src/com/android/settings/DisplaySettings.java +++ b/src/com/android/settings/DisplaySettings.java @@ -88,7 +88,7 @@ public class DisplaySettings extends SettingsPreferenceFragment implements private static final int DLG_GLOBAL_CHANGE_WARNING = 1; - private WarnedListPreference mFontSizePref; + private FontDialogPreference mFontSizePref; private final Configuration mCurConfig = new Configuration(); @@ -130,7 +130,7 @@ public class DisplaySettings extends SettingsPreferenceFragment implements disableUnusableTimeouts(mScreenTimeoutPreference); updateTimeoutPreferenceDescription(currentTimeout); - mFontSizePref = (WarnedListPreference) findPreference(KEY_FONT_SIZE); + mFontSizePref = (FontDialogPreference) findPreference(KEY_FONT_SIZE); mFontSizePref.setOnPreferenceChangeListener(this); mFontSizePref.setOnPreferenceClickListener(this); @@ -312,37 +312,6 @@ public class DisplaySettings extends SettingsPreferenceFragment implements screenTimeoutPreference.setEnabled(revisedEntries.size() > 0); } - int floatToIndex(float val) { - String[] indices = getResources().getStringArray(R.array.entryvalues_font_size); - float lastVal = Float.parseFloat(indices[0]); - for (int i=1; i<indices.length; i++) { - float thisVal = Float.parseFloat(indices[i]); - if (val < (lastVal + (thisVal-lastVal)*.5f)) { - return i-1; - } - lastVal = thisVal; - } - return indices.length-1; - } - - public void readFontSizePreference(ListPreference pref) { - try { - mCurConfig.updateFrom(ActivityManagerNative.getDefault().getConfiguration()); - } catch (RemoteException e) { - Log.w(TAG, "Unable to retrieve font size"); - } - - // mark the appropriate item in the preferences list - int index = floatToIndex(mCurConfig.fontScale); - pref.setValueIndex(index); - - // report the current size in the summary text - final Resources res = getResources(); - String[] fontSizeNames = res.getStringArray(R.array.entries_font_size); - pref.setSummary(String.format(res.getString(R.string.summary_font_size), - fontSizeNames[index])); - } - @Override public void onResume() { super.onResume(); @@ -422,6 +391,22 @@ public class DisplaySettings extends SettingsPreferenceFragment implements } } + /** + * Reads the current font size and sets the value in the summary text + */ + public void readFontSizePreference(Preference pref) { + try { + mCurConfig.updateFrom(ActivityManagerNative.getDefault().getConfiguration()); + } catch (RemoteException e) { + Log.w(TAG, "Unable to retrieve font size"); + } + + // report the current size in the summary text + final Resources res = getResources(); + String fontDesc = FontDialogPreference.getFontSizeDescription(res, mCurConfig.fontScale); + pref.setSummary(getString(R.string.summary_font_size, fontDesc)); + } + public void writeFontSizePreference(Object objValue) { try { mCurConfig.fontScale = Float.parseFloat(objValue.toString()); diff --git a/src/com/android/settings/FontDialogPreference.java b/src/com/android/settings/FontDialogPreference.java new file mode 100644 index 0000000..e9906e0 --- /dev/null +++ b/src/com/android/settings/FontDialogPreference.java @@ -0,0 +1,156 @@ +package com.android.settings; + +import android.app.ActivityManagerNative; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.os.RemoteException; +import android.preference.DialogPreference; +import android.preference.Preference; +import android.provider.Settings; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.util.Log; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.SeekBar; +import android.widget.TextView; + +public class FontDialogPreference extends DialogPreference + implements SeekBar.OnSeekBarChangeListener { + + private TextView mDescriptionText; + private TextView mPercentageText; + private IntervalSeekBar mSeekBar; + + private DisplayMetrics mDisplayMetrics; + private int mLargeTextSp; + private int mSmallTextSp; + + public FontDialogPreference(Context context, AttributeSet attrs) { + super(context, attrs); + + setPositiveButtonText(android.R.string.ok); + setNegativeButtonText(android.R.string.cancel); + + initDisplayMetrics(); + + setDialogLayoutResource(R.layout.preference_dialog_fontsize); + setDialogTitle(null); // Hide the title bar + } + + @Override + protected View onCreateDialogView() { + LayoutInflater inflater = + (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View view = inflater.inflate(R.layout.preference_dialog_fontsize, null); + + mDescriptionText = (TextView) view.findViewById(R.id.description); + mPercentageText = (TextView) view.findViewById(R.id.percentage); + + // Calculate original sp sizes for the text views + mLargeTextSp = Math.round(mDescriptionText.getTextSize() / mDisplayMetrics.scaledDensity); + mSmallTextSp = Math.round(mPercentageText.getTextSize() / mDisplayMetrics.scaledDensity); + + mSeekBar = (IntervalSeekBar) view.findViewById(R.id.font_size); + + String strFontSize = getPersistedString(String.valueOf(mSeekBar.getDefault())); + float fontSize = Float.parseFloat(strFontSize); + + mSeekBar.setProgressFloat(fontSize); + mSeekBar.setOnSeekBarChangeListener(this); + + setPrompt(fontSize); + + return view; + } + + private void initDisplayMetrics() { + DisplayMetrics metrics = getContext().getResources().getDisplayMetrics(); + mDisplayMetrics = new DisplayMetrics(); + mDisplayMetrics.density = metrics.density; + mDisplayMetrics.heightPixels = metrics.heightPixels; + mDisplayMetrics.scaledDensity = metrics.scaledDensity; + mDisplayMetrics.widthPixels = metrics.widthPixels; + mDisplayMetrics.xdpi = metrics.xdpi; + mDisplayMetrics.ydpi = metrics.ydpi; + } + + @Override + protected void onDialogClosed(boolean positiveResult) { + if (positiveResult) { + // Notify the Display settings screen (parent) that the font size + // is about to change. This can determine whether to persist the + // current value + if (callChangeListener(mSeekBar.getProgressFloat())) { + // Originally font scaling was a float stored as a String, + // so using persistFloat raises a ClassCastException + persistString(Float.toString(mSeekBar.getProgressFloat())); + } + } + } + + @Override + protected void onClick() { + // Ignore this until an explicit call to click() + } + + public void click() { + super.onClick(); + } + + /** + * Get an approximate description for the font size scale. + * Assumes that the string arrays entries_font_size and + * entryvalues_font_size have the same length and correspond to each other + * i.e. they are in the same order. + */ + static String getFontSizeDescription(Resources r, float val) { + String[] names = r.getStringArray(R.array.entries_font_size); + String[] indices = r.getStringArray(R.array.entryvalues_font_size); + + float lastVal = Float.parseFloat(indices[0]); + for (int i = 1; i < indices.length; i++) { + float thisVal = Float.parseFloat(indices[i]); + if (val < (lastVal + (thisVal-lastVal)*.5f)) { + return names[i - 1]; + } + lastVal = thisVal; + } + return names[indices.length - 1]; + } + + /** + * Set the TextView indicating the font scaling + */ + private void setPrompt(float fontScaling) { + // Update the preview text + String percentage = Math.round(fontScaling * 100) + "%"; + mPercentageText.setText(percentage); + + // Update the preview sizes + mDisplayMetrics.scaledDensity = mDisplayMetrics.density * fontScaling; + float largeSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, mLargeTextSp, + mDisplayMetrics); + float smallSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, mSmallTextSp, + mDisplayMetrics); + mDescriptionText.setTextSize(TypedValue.COMPLEX_UNIT_PX, largeSize); + mPercentageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, smallSize); + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + setPrompt(mSeekBar.getProgressFloat()); + } + + // Not used + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + } +} diff --git a/src/com/android/settings/IntervalSeekBar.java b/src/com/android/settings/IntervalSeekBar.java new file mode 100644 index 0000000..5fbdb81 --- /dev/null +++ b/src/com/android/settings/IntervalSeekBar.java @@ -0,0 +1,87 @@ +package com.android.settings; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.util.Log; +import android.widget.SeekBar; + +/** + * Custom SeekBar that allows setting both a minimum and maximum value. + * This also handles floating point values (to 2 decimal places) through + * integer conversions. + */ +public class IntervalSeekBar extends SeekBar { + private float mMin; + private float mMax; + private float mDefault; + private float mMultiplier; + + public IntervalSeekBar(Context context, AttributeSet attrs) { + super(context, attrs); + + TypedArray seekBarType = context.obtainStyledAttributes(attrs, + R.styleable.IntervalSeekBar, 0, 0); + + mMax = seekBarType.getFloat(R.styleable.IntervalSeekBar_max, 1.5f); + mMin = seekBarType.getFloat(R.styleable.IntervalSeekBar_min, 0.5f); + mDefault = seekBarType.getFloat(R.styleable.IntervalSeekBar_defaultValue, 1.0f); + + int digits = seekBarType.getInt(R.styleable.IntervalSeekBar_digits, 0); + mMultiplier = (float) Math.pow(10, digits); + + if (mMin > mMax) { + float temp = mMax; + mMax = mMin; + mMin = temp; + } + + setMax(convertFloatToProgress(mMax)); + setProgressFloat(mDefault); + + seekBarType.recycle(); + } + + /* + * Converts from SeekBar units (which the SeekBar uses), to scale units + * (which are saved). + * This operation is the inverse of setFontScaling. + */ + public float getProgressFloat() { + return (getProgress() / mMultiplier) + mMin; + } + + /* + * Converts from scale units (which are saved), to SeekBar units + * (which the SeekBar uses). This also sets the SeekBar progress. + * This operation is the inverse of getProgressFloat. + */ + public void setProgressFloat(float progress) { + setProgress(convertFloatToProgress(progress)); + } + + private int convertFloatToProgress(float value) { + return Math.round((value - mMin) * mMultiplier); + } + + public float getMinimum() { + return mMin; + } + + public float getMaximum() { + return mMax; + } + + public float getDefault() { + return mDefault; + } + + public void setMaximum(float max) { + mMax = max; + setMax(convertFloatToProgress(mMax)); + } + + public void setMinimum(float min) { + mMin = min; + } +} |