diff --git a/app/build.gradle b/app/build.gradle index a8154b4a..0869e5e5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -36,7 +36,6 @@ dependencies { implementation it['okhttp'] implementation it['prism4j'] implementation it['debug'] - implementation it['better-link-movement'] implementation it['dagger'] } diff --git a/app/src/main/java/ru/noties/markwon/MainActivity.java b/app/src/main/java/ru/noties/markwon/MainActivity.java index 19882a74..3bf49109 100644 --- a/app/src/main/java/ru/noties/markwon/MainActivity.java +++ b/app/src/main/java/ru/noties/markwon/MainActivity.java @@ -11,7 +11,6 @@ import android.widget.TextView; import javax.inject.Inject; -import me.saket.bettermovementmethod.BetterLinkMovementMethod; import ru.noties.debug.Debug; public class MainActivity extends Activity { @@ -71,7 +70,7 @@ public class MainActivity extends Activity { @Override public void onMarkdownReady(CharSequence markdown) { - Markwon.setText(textView, markdown, BetterLinkMovementMethod.getInstance()); + Markwon.setText(textView, markdown); gifProcessor.process(textView); diff --git a/build.gradle b/build.gradle index f177c38a..4e69d605 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ task clean(type: Delete) { } task wrapper(type: Wrapper) { - gradleVersion '4.8.1' + gradleVersion '4.10.2' distributionType 'all' } @@ -64,7 +64,6 @@ ext { 'okhttp' : 'com.squareup.okhttp3:okhttp:3.9.0', 'prism4j' : 'ru.noties:prism4j:1.1.0', 'debug' : 'ru.noties:debug:3.0.0@jar', - 'better-link-movement' : 'me.saket:better-link-movement-method:2.2.0', 'dagger' : "com.google.dagger:dagger:$daggerVersion" ] diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a5fe1cb9..758de960 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index bb5158de..d76b502e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-all.zip diff --git a/markwon/src/main/java/ru/noties/markwon/Markwon.java b/markwon/src/main/java/ru/noties/markwon/Markwon.java index 01273b78..6ecb9ca8 100644 --- a/markwon/src/main/java/ru/noties/markwon/Markwon.java +++ b/markwon/src/main/java/ru/noties/markwon/Markwon.java @@ -15,6 +15,7 @@ import org.commonmark.parser.Parser; import java.util.Arrays; import ru.noties.markwon.renderer.SpannableRenderer; +import ru.noties.markwon.spans.OrderedListItemSpan; import ru.noties.markwon.tasklist.TaskListExtension; @SuppressWarnings({"WeakerAccess", "unused"}) @@ -100,6 +101,12 @@ public abstract class Markwon { unscheduleDrawables(view); unscheduleTableRows(view); + // @since 2.0.1 we must measure ordered-list-item-spans before applying text to a TextView. + // if markdown has a lot of ordered list items (or text size is relatively big, or block-margin + // is relatively small) then this list won't be rendered properly: it will take correct + // layout (width and margin) but will be clipped if margin is not _consistent_ between calls. + OrderedListItemSpan.measure(view, text); + // update movement method (for links to be clickable) view.setMovementMethod(movementMethod); view.setText(text); diff --git a/markwon/src/main/java/ru/noties/markwon/spans/OrderedListItemSpan.java b/markwon/src/main/java/ru/noties/markwon/spans/OrderedListItemSpan.java index 29f68e9e..1db29e1a 100644 --- a/markwon/src/main/java/ru/noties/markwon/spans/OrderedListItemSpan.java +++ b/markwon/src/main/java/ru/noties/markwon/spans/OrderedListItemSpan.java @@ -4,10 +4,44 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.support.annotation.NonNull; import android.text.Layout; +import android.text.Spanned; +import android.text.TextPaint; import android.text.style.LeadingMarginSpan; +import android.widget.TextView; public class OrderedListItemSpan implements LeadingMarginSpan { + /** + * Process supplied `text` argument and supply TextView paint to all OrderedListItemSpans + * in order for them to measure number. + *

+ * NB, this method must be called before setting text to a TextView (`TextView#setText` + * internally can trigger new Layout creation which will ask for leading margins right away) + * + * @param textView to which markdown will be applied + * @param text parsed markdown to process + * @since 2.0.1 + */ + public static void measure(@NonNull TextView textView, @NonNull CharSequence text) { + + if (!(text instanceof Spanned)) { + // nothing to do here + return; + } + + final OrderedListItemSpan[] spans = ((Spanned) text).getSpans( + 0, + text.length(), + OrderedListItemSpan.class); + + if (spans != null) { + final TextPaint paint = textView.getPaint(); + for (OrderedListItemSpan span : spans) { + span.margin = (int) (paint.measureText(span.number) + .5F); + } + } + } + private final SpannableTheme theme; private final String number; private final Paint paint = ObjectsPool.paint(); @@ -27,8 +61,8 @@ public class OrderedListItemSpan implements LeadingMarginSpan { @Override public int getLeadingMargin(boolean first) { - // @since 1.0.3 - return margin > 0 ? margin : theme.getBlockMargin(); + // @since 2.0.1 we return maximum value of both (now we should measure number before) + return Math.max(margin, theme.getBlockMargin()); } @Override @@ -44,11 +78,16 @@ public class OrderedListItemSpan implements LeadingMarginSpan { theme.applyListItemStyle(paint); - final int numberWidth = (int) (p.measureText(number) + .5F); + // if we could force usage of #measure method then we might want skip this measuring here + // but this won't hold against new values that a TextView can receive (new text size for + // example...) + final int numberWidth = (int) (paint.measureText(number) + .5F); // @since 1.0.3 int width = theme.getBlockMargin(); if (numberWidth > width) { + // let's keep this logic here in case a user decided not to call #measure and is fine + // with current implementation width = numberWidth; margin = numberWidth; } else {