Sample, anchor links

This commit is contained in:
Dimitry Ivanov 2020-03-16 10:30:44 +03:00
parent c425773c84
commit 815f733892
4 changed files with 197 additions and 31 deletions

View File

@ -3,8 +3,12 @@ package io.noties.markwon.sample.basicplugins;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.text.Spannable;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.view.View;
import android.widget.ScrollView;
import android.widget.TextView;
import androidx.annotation.NonNull;
@ -19,6 +23,7 @@ import java.util.Collections;
import io.noties.markwon.AbstractMarkwonPlugin;
import io.noties.markwon.BlockHandlerDef;
import io.noties.markwon.LinkResolverDef;
import io.noties.markwon.Markwon;
import io.noties.markwon.MarkwonConfiguration;
import io.noties.markwon.MarkwonSpansFactory;
@ -26,6 +31,7 @@ import io.noties.markwon.MarkwonVisitor;
import io.noties.markwon.SoftBreakAddsNewLinePlugin;
import io.noties.markwon.core.CoreProps;
import io.noties.markwon.core.MarkwonTheme;
import io.noties.markwon.core.spans.HeadingSpan;
import io.noties.markwon.core.spans.LastLineSpacingSpan;
import io.noties.markwon.image.ImageItem;
import io.noties.markwon.image.ImagesPlugin;
@ -39,6 +45,7 @@ import io.noties.markwon.sample.R;
public class BasicPluginsActivity extends ActivityWithMenuOptions {
private TextView textView;
private ScrollView scrollView;
@NonNull
@Override
@ -54,7 +61,8 @@ public class BasicPluginsActivity extends ActivityWithMenuOptions {
.add("additionalSpacing", this::additionalSpacing)
.add("headingNoSpace", this::headingNoSpace)
.add("headingNoSpaceBlockHandler", this::headingNoSpaceBlockHandler)
.add("allBlocksNoForcedLine", this::allBlocksNoForcedLine);
.add("allBlocksNoForcedLine", this::allBlocksNoForcedLine)
.add("anchor", this::anchor);
}
@Override
@ -63,6 +71,7 @@ public class BasicPluginsActivity extends ActivityWithMenuOptions {
setContentView(R.layout.activity_text_view);
textView = findViewById(R.id.text_view);
scrollView = findViewById(R.id.scroll_view);
paragraphSpan();
//
@ -403,4 +412,96 @@ public class BasicPluginsActivity extends ActivityWithMenuOptions {
// rendering lifecycle (before/after)
// renderProps
// process
private static class AnchorSpan {
final String anchor;
AnchorSpan(@NonNull String anchor) {
this.anchor = anchor;
}
}
@NonNull
private String createAnchor(@NonNull CharSequence content) {
return String.valueOf(content)
.replaceAll("[^\\w]", "")
.toLowerCase();
}
private static class AnchorLinkResolver extends LinkResolverDef {
interface ScrollTo {
void scrollTo(@NonNull View view, int top);
}
private final ScrollTo scrollTo;
AnchorLinkResolver(@NonNull ScrollTo scrollTo) {
this.scrollTo = scrollTo;
}
@Override
public void resolve(@NonNull View view, @NonNull String link) {
if (link.startsWith("#")) {
final TextView textView = (TextView) view;
final Spanned spanned = (Spannable) textView.getText();
final AnchorSpan[] spans = spanned.getSpans(0, spanned.length(), AnchorSpan.class);
if (spans != null) {
final String anchor = link.substring(1);
for (AnchorSpan span: spans) {
if (anchor.equals(span.anchor)) {
final int start = spanned.getSpanStart(span);
final int line = textView.getLayout().getLineForOffset(start);
final int top = textView.getLayout().getLineTop(line);
scrollTo.scrollTo(textView, top);
return;
}
}
}
}
super.resolve(view, link);
}
}
private void anchor() {
final String lorem = getString(R.string.lorem);
final String md = "" +
"Hello [there](#there)!\n\n\n" +
lorem + "\n\n" +
"# There!\n\n" +
lorem;
final Markwon markwon = Markwon.builder(this)
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) {
builder.linkResolver(new AnchorLinkResolver((view, top) -> {
scrollView.smoothScrollTo(0, top);
}));
}
@Override
public void afterSetText(@NonNull TextView textView) {
final Spannable spannable = (Spannable) textView.getText();
// obtain heading spans
final HeadingSpan[] spans = spannable.getSpans(0, spannable.length(), HeadingSpan.class);
if (spans != null) {
for (HeadingSpan span : spans) {
final int start = spannable.getSpanStart(span);
final int end = spannable.getSpanEnd(span);
final int flags = spannable.getSpanFlags(span);
spannable.setSpan(
new AnchorSpan(createAnchor(spannable.subSequence(start, end))),
start,
end,
flags
);
}
}
}
})
.build();
markwon.setMarkdown(textView, md);
}
}

View File

@ -1,6 +1,5 @@
package io.noties.markwon.sample.html;
import android.app.Activity;
import android.os.Bundle;
import android.text.Layout;
import android.text.TextUtils;
@ -27,9 +26,22 @@ import io.noties.markwon.html.HtmlTag;
import io.noties.markwon.html.MarkwonHtmlRenderer;
import io.noties.markwon.html.TagHandler;
import io.noties.markwon.html.tag.SimpleTagHandler;
import io.noties.markwon.sample.ActivityWithMenuOptions;
import io.noties.markwon.sample.MenuOptions;
import io.noties.markwon.sample.R;
public class HtmlActivity extends Activity {
public class HtmlActivity extends ActivityWithMenuOptions {
@NonNull
@Override
public MenuOptions menuOptions() {
return MenuOptions.create()
.add("align", this::align)
.add("randomCharSize", this::randomCharSize)
.add("enhance", this::enhance);
}
private TextView textView;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@ -39,35 +51,9 @@ public class HtmlActivity extends Activity {
// let's define some custom tag-handlers
final TextView textView = findViewById(R.id.text_view);
textView = findViewById(R.id.text_view);
final Markwon markwon = Markwon.builder(this)
.usePlugin(HtmlPlugin.create())
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configure(@NonNull Registry registry) {
registry.require(HtmlPlugin.class, htmlPlugin -> htmlPlugin
.addHandler(new AlignTagHandler())
.addHandler(new RandomCharSize(new Random(42L), textView.getTextSize()))
.addHandler(new EnhanceTagHandler((int) (textView.getTextSize() * 2 + .05F))));
}
})
.build();
final String markdown = "# Hello, HTML\n" +
"\n" +
"<align center>We are centered</align>\n" +
"\n" +
"<align end>We are at the end</align>\n" +
"\n" +
"<align>We should be at the start</align>\n" +
"\n" +
"<random-char-size>\n" +
"This message should have a jumpy feeling because of different sizes of characters\n" +
"</random-char-size>\n\n" +
"<enhance start=\"5\" end=\"12\">This is text that must be enhanced, at least a part of it</enhance>";
markwon.setMarkdown(textView, markdown);
align();
}
// we can use `SimpleTagHandler` for _simple_ cases (when the whole tag content
@ -105,6 +91,31 @@ public class HtmlActivity extends Activity {
}
}
private void align() {
final String md = "" +
"<align center>We are centered</align>\n" +
"\n" +
"<align end>We are at the end</align>\n" +
"\n" +
"<align>We should be at the start</align>\n" +
"\n";
final Markwon markwon = Markwon.builder(this)
.usePlugin(HtmlPlugin.create())
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configure(@NonNull Registry registry) {
registry.require(HtmlPlugin.class, htmlPlugin -> htmlPlugin
.addHandler(new AlignTagHandler()));
}
})
.build();
markwon.setMarkdown(textView, md);
}
// each character will have random size
private static class RandomCharSize extends TagHandler {
@ -139,6 +150,27 @@ public class HtmlActivity extends Activity {
}
}
private void randomCharSize() {
final String md = "" +
"<random-char-size>\n" +
"This message should have a jumpy feeling because of different sizes of characters\n" +
"</random-char-size>\n\n";
final Markwon markwon = Markwon.builder(this)
.usePlugin(HtmlPlugin.create())
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configure(@NonNull Registry registry) {
registry.require(HtmlPlugin.class, htmlPlugin -> htmlPlugin
.addHandler(new RandomCharSize(new Random(42L), textView.getTextSize())));
}
})
.build();
markwon.setMarkdown(textView, md);
}
private static class EnhanceTagHandler extends TagHandler {
private final int enhanceTextSize;
@ -187,4 +219,24 @@ public class HtmlActivity extends Activity {
return position;
}
}
private void enhance() {
final String md = "" +
"<enhance start=\"5\" end=\"12\">This is text that must be enhanced, at least a part of it</enhance>";
final Markwon markwon = Markwon.builder(this)
.usePlugin(HtmlPlugin.create())
.usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configure(@NonNull Registry registry) {
registry.require(HtmlPlugin.class, htmlPlugin -> htmlPlugin
.addHandler(new EnhanceTagHandler((int) (textView.getTextSize() * 2 + .05F))));
}
})
.build();
markwon.setMarkdown(textView, md);
}
}

View File

@ -1,5 +1,6 @@
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent">

View File

@ -12,4 +12,16 @@ Sentiment Satisfied 64 red: @ic-sentiment_satisfied-red-64
]]>
</string>
<string name="lorem"><![CDATA[
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis rutrum orci at aliquet dapibus. Quisque laoreet fermentum bibendum. Suspendisse euismod nisl vel sapien viverra faucibus. Nulla vel neque volutpat, egestas dui ac, consequat elit. Donec et interdum massa. Quisque porta ornare posuere. Nam at ante a felis facilisis tempus eu et erat. Curabitur auctor mauris eget purus iaculis vulputate.
Sed eu enim neque. Maecenas dictum faucibus ullamcorper. In ullamcorper orci in neque varius, nec rutrum nisl eleifend. Vestibulum tincidunt, ipsum at porta suscipit, est nibh commodo ex, et ultrices eros lacus vel neque. Praesent nulla velit, hendrerit sed sodales at, feugiat non lectus. Vivamus vel ultricies mi. Ut finibus commodo feugiat. Sed tempor lorem tortor, tempor sodales leo varius id. Curabitur rutrum sem at euismod rhoncus. Ut iaculis sem pharetra neque accumsan vestibulum. Nunc ultrices pharetra massa, at luctus nulla maximus et. Donec rhoncus in nisi eu pellentesque.
Sed consequat convallis massa quis bibendum. Phasellus vel suscipit velit. Pellentesque vel nisi at nisi facilisis condimentum. Cras feugiat magna ex, ut ultricies eros porttitor id. Quisque iaculis rutrum arcu eget placerat. Vestibulum pellentesque, urna eget consectetur commodo, est metus gravida nisl, id lacinia ligula ipsum porta nulla. Etiam aliquam convallis sollicitudin. Etiam sit amet mi aliquet purus faucibus hendrerit pharetra eu quam. Cras ut ornare sapien. Nam sapien diam, porttitor eu sagittis nec, vehicula nec mi. In fringilla turpis nec nisi fringilla, a facilisis eros ultrices. Proin eget arcu velit.
Sed gravida auctor malesuada. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus non justo sem. Donec dictum a elit quis pretium. Fusce accumsan sodales ornare. Nunc facilisis ligula eu ultrices faucibus. Proin vel molestie augue, ut convallis enim. Curabitur efficitur eget urna quis tempor. In non arcu non ex vulputate pulvinar. In laoreet aliquam mauris. Suspendisse vulputate magna at lorem bibendum, quis dapibus sapien malesuada. Curabitur at leo sit amet est egestas vestibulum. Sed hendrerit mi vel massa vestibulum, non semper nisl iaculis. Pellentesque feugiat at dolor a viverra. Sed ut consectetur tellus. Maecenas venenatis nunc a arcu convallis, at semper nulla cursus.
Curabitur placerat neque a congue pulvinar. Nulla non commodo est. Aenean nec gravida odio. Cras tincidunt accumsan pulvinar. Vestibulum non imperdiet velit. Sed ut mollis velit, vel ornare metus. Morbi consequat mi quis dui consectetur, sed condimentum lacus pulvinar.
]]></string>
</resources>