From dd478bfd67c371ce67bf09a02ca41af5473baaea Mon Sep 17 00:00:00 2001 From: Eric Denman Date: Fri, 20 Jul 2018 10:08:30 -0700 Subject: [PATCH] Add headingTypeface, headingTextSizes to SpannableTheme (#51) * Add headingTypeface to SpannableTheme, use a custom heading typeface in the sample app * Add headingTextSizes * Switching to headingTextSizeMultipliers, adding validating annotations, adding example * Consolidate logic, add crash if header index is out of bounds --- .../noties/markwon/spans/SpannableTheme.java | 48 ++++++++++++++++++- .../sample/extension/MainActivity.java | 11 ++++- .../src/main/res/layout/activity_main.xml | 3 +- .../src/main/res/values/strings.xml | 1 + 4 files changed, 59 insertions(+), 4 deletions(-) diff --git a/library/src/main/java/ru/noties/markwon/spans/SpannableTheme.java b/library/src/main/java/ru/noties/markwon/spans/SpannableTheme.java index 0701ed39..678cf1ab 100644 --- a/library/src/main/java/ru/noties/markwon/spans/SpannableTheme.java +++ b/library/src/main/java/ru/noties/markwon/spans/SpannableTheme.java @@ -12,9 +12,13 @@ import android.support.annotation.FloatRange; import android.support.annotation.IntRange; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.annotation.Size; import android.text.TextPaint; import android.util.TypedValue; +import java.util.Arrays; +import java.util.Locale; + @SuppressWarnings("WeakerAccess") public class SpannableTheme { @@ -173,6 +177,13 @@ public class SpannableTheme { // by default, text color with `HEADING_DEF_BREAK_COLOR_ALPHA` applied alpha protected final int headingBreakColor; + // by default, whatever typeface is set on the TextView + protected final Typeface headingTypeface; + + // by default, we use standard multipliers from the HTML spec (see HEADING_SIZES for values). + // this library supports 6 heading sizes, so make sure the array you pass here has 6 elements. + protected final float[] headingTextSizeMultipliers; + // by default `SCRIPT_DEF_TEXT_SIZE_RATIO` protected final float scriptTextSizeRatio; @@ -214,6 +225,8 @@ public class SpannableTheme { this.codeTextSize = builder.codeTextSize; this.headingBreakHeight = builder.headingBreakHeight; this.headingBreakColor = builder.headingBreakColor; + this.headingTypeface = builder.headingTypeface; + this.headingTextSizeMultipliers = builder.headingTextSizeMultipliers; this.scriptTextSizeRatio = builder.scriptTextSizeRatio; this.thematicBreakColor = builder.thematicBreakColor; this.thematicBreakHeight = builder.thematicBreakHeight; @@ -368,8 +381,23 @@ public class SpannableTheme { } public void applyHeadingTextStyle(@NonNull Paint paint, @IntRange(from = 1, to = 6) int level) { - paint.setFakeBoldText(true); - paint.setTextSize(paint.getTextSize() * HEADING_SIZES[level - 1]); + if (headingTypeface == null) { + paint.setFakeBoldText(true); + } else { + paint.setTypeface(headingTypeface); + } + final float[] textSizes = headingTextSizeMultipliers != null + ? headingTextSizeMultipliers + : HEADING_SIZES; + + if (textSizes != null && textSizes.length >= level) { + paint.setTextSize(paint.getTextSize() * textSizes[level - 1]); + } else { + throw new IllegalStateException(String.format( + Locale.US, + "Supplied heading level: %d is invalid, where configured heading sizes are: `%s`", + level, Arrays.toString(textSizes))); + } } public void applyHeadingBreakStyle(@NonNull Paint paint) { @@ -491,6 +519,8 @@ public class SpannableTheme { private int codeTextSize; private int headingBreakHeight = -1; private int headingBreakColor; + private Typeface headingTypeface; + private float[] headingTextSizeMultipliers; private float scriptTextSizeRatio; private int thematicBreakColor; private int thematicBreakHeight = -1; @@ -520,6 +550,8 @@ public class SpannableTheme { this.codeTextSize = theme.codeTextSize; this.headingBreakHeight = theme.headingBreakHeight; this.headingBreakColor = theme.headingBreakColor; + this.headingTypeface = theme.headingTypeface; + this.headingTextSizeMultipliers = theme.headingTextSizeMultipliers; this.scriptTextSizeRatio = theme.scriptTextSizeRatio; this.thematicBreakColor = theme.thematicBreakColor; this.thematicBreakHeight = theme.thematicBreakHeight; @@ -634,6 +666,18 @@ public class SpannableTheme { return this; } + @NonNull + public Builder headingTypeface(@NonNull Typeface headingTypeface) { + this.headingTypeface = headingTypeface; + return this; + } + + @NonNull + public Builder headingTextSizeMultipliers(@Size(6) @NonNull float[] headingTextSizeMultipliers) { + this.headingTextSizeMultipliers = headingTextSizeMultipliers; + return this; + } + @NonNull public Builder scriptTextSizeRatio(@FloatRange(from = .0F, to = Float.MAX_VALUE) float scriptTextSizeRatio) { this.scriptTextSizeRatio = scriptTextSizeRatio; diff --git a/sample-custom-extension/src/main/java/ru/noties/markwon/sample/extension/MainActivity.java b/sample-custom-extension/src/main/java/ru/noties/markwon/sample/extension/MainActivity.java index a81f8eb0..19a69704 100644 --- a/sample-custom-extension/src/main/java/ru/noties/markwon/sample/extension/MainActivity.java +++ b/sample-custom-extension/src/main/java/ru/noties/markwon/sample/extension/MainActivity.java @@ -1,6 +1,7 @@ package ru.noties.markwon.sample.extension; import android.app.Activity; +import android.graphics.Typeface; import android.os.Bundle; import android.widget.TextView; @@ -13,6 +14,7 @@ import java.util.Arrays; import ru.noties.markwon.SpannableBuilder; import ru.noties.markwon.SpannableConfiguration; +import ru.noties.markwon.spans.SpannableTheme; import ru.noties.markwon.tasklist.TaskListExtension; public class MainActivity extends Activity { @@ -50,9 +52,16 @@ public class MainActivity extends Activity { // better to provide a valid fallback option final IconSpanProvider spanProvider = IconSpanProvider.create(this, 0); + final float[] textSizeMultipliers = new float[]{3f, 2f, 1.5f, 1f, .5f, .25f}; + SpannableConfiguration configuration = SpannableConfiguration.builder(this) + .theme(SpannableTheme.builder() + .headingTypeface(Typeface.MONOSPACE) + .headingTextSizeMultipliers(textSizeMultipliers) + .build()) + .build(); // create an instance of visitor to process parsed markdown final IconVisitor visitor = new IconVisitor( - SpannableConfiguration.create(this), + configuration, builder, spanProvider ); diff --git a/sample-custom-extension/src/main/res/layout/activity_main.xml b/sample-custom-extension/src/main/res/layout/activity_main.xml index 439dac71..e4f2a936 100644 --- a/sample-custom-extension/src/main/res/layout/activity_main.xml +++ b/sample-custom-extension/src/main/res/layout/activity_main.xml @@ -11,6 +11,7 @@ android:layout_height="wrap_content" android:padding="8dip" android:textAppearance="?android:attr/textAppearanceMedium" + android:textSize="15sp" tools:text="@string/input"/> - \ No newline at end of file + diff --git a/sample-custom-extension/src/main/res/values/strings.xml b/sample-custom-extension/src/main/res/values/strings.xml index 7dc177e7..fdc01039 100644 --- a/sample-custom-extension/src/main/res/values/strings.xml +++ b/sample-custom-extension/src/main/res/values/strings.xml @@ -6,6 +6,7 @@ # Hello! @ic-android-black-24\n\n Home 36 black: @ic-home-black-36\n\n Memory 48 black: @ic-memory-black-48\n\n + ### I AM ANOTHER HEADER\n\n Sentiment Satisfied 64 red: @ic-sentiment_satisfied-red-64 ]]>