diff --git a/res/layout/slider_preference_dialog.xml b/res/layout/slider_preference_dialog.xml
new file mode 100644
index 000000000..7e2eafce6
--- /dev/null
+++ b/res/layout/slider_preference_dialog.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index dc108fa98..fb1e59c2f 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -55,4 +55,8 @@
+
+
+
+
diff --git a/res/xml/font_preferences.xml b/res/xml/font_preferences.xml
index c0486e64a..cce4a7007 100644
--- a/res/xml/font_preferences.xml
+++ b/res/xml/font_preferences.xml
@@ -153,6 +153,12 @@
android:entryValues="@array/font_values_webview"
android:dialogTitle="@string/font_size_message_view_content" />
+
+
= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+ ((PreferenceGroup) findPreference(PREFERENCE_SCREEN_MESSAGE_VIEW_FONTS)).
+ removePreference(mMessageViewContent);
+ } else {
+ ((PreferenceGroup) findPreference(PREFERENCE_SCREEN_MESSAGE_VIEW_FONTS)).
+ removePreference(mMessageViewContentSlider);
+ }
+
mMessageComposeInput = setupListPreference(
PREFERENCE_MESSAGE_COMPOSE_INPUT_FONT,
Integer.toString(fontSizes.getMessageComposeInput()));
@@ -150,6 +190,10 @@ public class FontSizeSettings extends K9PreferenceActivity {
fontSizes.setMessageViewSubject(Integer.parseInt(mMessageViewSubject.getValue()));
fontSizes.setMessageViewDate(Integer.parseInt(mMessageViewDate.getValue()));
fontSizes.setMessageViewContent(Integer.parseInt(mMessageViewContent.getValue()));
+ // Scale from [0, 1]
+ fontSizes.setMessageViewContentAsPercent((int)(FONT_PERCENT_MIN +
+ mMessageViewContentSlider.getValue() *
+ (FONT_PERCENT_MAX - FONT_PERCENT_MIN)));
fontSizes.setMessageComposeInput(Integer.parseInt(mMessageComposeInput.getValue()));
diff --git a/src/com/fsck/k9/activity/setup/SliderPreference.java b/src/com/fsck/k9/activity/setup/SliderPreference.java
new file mode 100644
index 000000000..3342138c2
--- /dev/null
+++ b/src/com/fsck/k9/activity/setup/SliderPreference.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2012 Jay Weisskopf
+ *
+ * Licensed under the MIT License (see LICENSE.txt)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Source: https://github.com/jayschwa/AndroidSliderPreference
+ */
+
+package com.fsck.k9.activity.setup;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.preference.DialogPreference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.SeekBar;
+import com.fsck.k9.*;
+
+
+/**
+ * @author Jay Weisskopf
+ */
+public class SliderPreference extends DialogPreference {
+
+ protected final static int SEEKBAR_RESOLUTION = 10000;
+
+ protected float mValue;
+ protected int mSeekBarValue;
+ protected CharSequence[] mSummaries;
+
+ /**
+ * @param context
+ * @param attrs
+ */
+ public SliderPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setup(context, attrs);
+ }
+
+ /**
+ * @param context
+ * @param attrs
+ * @param defStyle
+ */
+ public SliderPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ setup(context, attrs);
+ }
+
+ private void setup(Context context, AttributeSet attrs) {
+ setDialogLayoutResource(R.layout.slider_preference_dialog);
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SliderPreference);
+ try {
+ setSummary(a.getTextArray(R.styleable.SliderPreference_android_summary));
+ } catch (Exception e) {
+ // Do nothing
+ }
+ a.recycle();
+ }
+
+ @Override
+ protected Object onGetDefaultValue(TypedArray a, int index) {
+ return a.getFloat(index, 0);
+ }
+
+ @Override
+ protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+ setValue(restoreValue ? getPersistedFloat(mValue) : (Float) defaultValue);
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ if (mSummaries != null && mSummaries.length > 0) {
+ int index = (int) (mValue * mSummaries.length);
+ index = Math.min(index, mSummaries.length - 1);
+ return mSummaries[index];
+ } else {
+ return super.getSummary();
+ }
+ }
+
+ public void setSummary(CharSequence[] summaries) {
+ mSummaries = summaries;
+ }
+
+ @Override
+ public void setSummary(CharSequence summary) {
+ super.setSummary(summary);
+ mSummaries = null;
+ }
+
+ @Override
+ public void setSummary(int summaryResId) {
+ try {
+ setSummary(getContext().getResources().getStringArray(summaryResId));
+ } catch (Exception e) {
+ super.setSummary(summaryResId);
+ }
+ }
+
+ public float getValue() {
+ return mValue;
+ }
+
+ public void setValue(float value) {
+ value = Math.max(0, Math.min(value, 1)); // clamp to [0, 1]
+ if (shouldPersist()) {
+ persistFloat(value);
+ }
+ if (value != mValue) {
+ mValue = value;
+ notifyChanged();
+ }
+ }
+
+ @Override
+ protected View onCreateDialogView() {
+ mSeekBarValue = (int) (mValue * SEEKBAR_RESOLUTION);
+ View view = super.onCreateDialogView();
+ SeekBar seekbar = (SeekBar) view.findViewById(R.id.slider_preference_seekbar);
+ seekbar.setMax(SEEKBAR_RESOLUTION);
+ seekbar.setProgress(mSeekBarValue);
+ seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (fromUser) {
+ SliderPreference.this.mSeekBarValue = progress;
+ callChangeListener((float) SliderPreference.this.mSeekBarValue / SEEKBAR_RESOLUTION);
+ }
+ }
+ });
+ return view;
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ final float newValue = (float) mSeekBarValue / SEEKBAR_RESOLUTION;
+ if (positiveResult && callChangeListener(newValue)) {
+ setValue(newValue);
+ } else {
+ callChangeListener(mValue);
+ }
+ super.onDialogClosed(positiveResult);
+ }
+
+ // TODO: Save and restore preference state.
+}
diff --git a/src/com/fsck/k9/view/MessageWebView.java b/src/com/fsck/k9/view/MessageWebView.java
index 95aada387..192165dcd 100644
--- a/src/com/fsck/k9/view/MessageWebView.java
+++ b/src/com/fsck/k9/view/MessageWebView.java
@@ -109,7 +109,11 @@ public class MessageWebView extends RigidWebView {
disableOverscrolling();
- webSettings.setTextSize(K9.getFontSizes().getMessageViewContent());
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+ webSettings.setTextZoom(K9.getFontSizes().getMessageViewContentAsPercent());
+ } else {
+ webSettings.setTextSize(K9.getFontSizes().getMessageViewContent());
+ }
// Disable network images by default. This is overridden by preferences.
blockNetworkData(true);