- Created clickable behaviour for images.
- Clicks can be consumed with ImageClickResolver
This commit is contained in:
parent
18938a1aa2
commit
30b6c01601
@ -0,0 +1,13 @@
|
||||
package ru.noties.markwon;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* @author pa.gulko zTrap (25.10.2017)
|
||||
* @since 1.0.1
|
||||
*/
|
||||
public interface ImageClickResolver {
|
||||
|
||||
void resolve(View view, @NonNull String link);
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package ru.noties.markwon;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.provider.Browser;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* @author pa.gulko zTrap (25.10.2017)
|
||||
* @since 1.0.1
|
||||
*/
|
||||
public class ImageClickResolverDef implements ImageClickResolver {
|
||||
|
||||
@Override
|
||||
public void resolve(View view, @NonNull String link) {
|
||||
final Uri uri = Uri.parse(link);
|
||||
final Context context = view.getContext();
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||
intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
|
||||
try {
|
||||
context.startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Log.w("LinkResolverDef", "Actvity was not found for intent, " + intent.toString());
|
||||
}
|
||||
}
|
||||
}
|
@ -26,6 +26,7 @@ public class SpannableConfiguration {
|
||||
private final LinkSpan.Resolver linkResolver;
|
||||
private final UrlProcessor urlProcessor;
|
||||
private final SpannableHtmlParser htmlParser;
|
||||
private final ImageClickResolver imageClickResolver;
|
||||
|
||||
private SpannableConfiguration(Builder builder) {
|
||||
this.theme = builder.theme;
|
||||
@ -34,6 +35,7 @@ public class SpannableConfiguration {
|
||||
this.linkResolver = builder.linkResolver;
|
||||
this.urlProcessor = builder.urlProcessor;
|
||||
this.htmlParser = builder.htmlParser;
|
||||
this.imageClickResolver = builder.imageClickResolver;
|
||||
}
|
||||
|
||||
public SpannableTheme theme() {
|
||||
@ -60,6 +62,10 @@ public class SpannableConfiguration {
|
||||
return htmlParser;
|
||||
}
|
||||
|
||||
public ImageClickResolver imageClickResolver() {
|
||||
return imageClickResolver;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private final Context context;
|
||||
@ -69,6 +75,7 @@ public class SpannableConfiguration {
|
||||
private LinkSpan.Resolver linkResolver;
|
||||
private UrlProcessor urlProcessor;
|
||||
private SpannableHtmlParser htmlParser;
|
||||
private ImageClickResolver imageClickResolver;
|
||||
|
||||
Builder(Context context) {
|
||||
this.context = context;
|
||||
@ -104,6 +111,11 @@ public class SpannableConfiguration {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setImageClickResolver(ImageClickResolver imageClickResolver) {
|
||||
this.imageClickResolver = imageClickResolver;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SpannableConfiguration build() {
|
||||
if (theme == null) {
|
||||
theme = SpannableTheme.create(context);
|
||||
@ -120,8 +132,12 @@ public class SpannableConfiguration {
|
||||
if (urlProcessor == null) {
|
||||
urlProcessor = new UrlProcessorNoOp();
|
||||
}
|
||||
if (imageClickResolver == null) {
|
||||
imageClickResolver = new ImageClickResolverDef();
|
||||
}
|
||||
if (htmlParser == null) {
|
||||
htmlParser = SpannableHtmlParser.create(theme, asyncDrawableLoader, urlProcessor, linkResolver);
|
||||
htmlParser = SpannableHtmlParser.create(theme, asyncDrawableLoader, urlProcessor,
|
||||
linkResolver, imageClickResolver);
|
||||
}
|
||||
return new SpannableConfiguration(this);
|
||||
}
|
||||
|
@ -4,7 +4,9 @@ import android.support.annotation.NonNull;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.text.style.StrikethroughSpan;
|
||||
import android.view.View;
|
||||
|
||||
import org.commonmark.ext.gfm.strikethrough.Strikethrough;
|
||||
import org.commonmark.ext.gfm.tables.TableBody;
|
||||
@ -431,8 +433,12 @@ public class SpannableMarkdownVisitor extends AbstractVisitor {
|
||||
)
|
||||
);
|
||||
|
||||
// todo, maybe, if image is not inside a link, we should make it clickable, so
|
||||
// user can open it in external viewer?
|
||||
setSpan(length, new ClickableSpan() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
configuration.imageClickResolver().resolve(view, destination);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -4,9 +4,12 @@ import android.support.annotation.NonNull;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import ru.noties.markwon.ImageClickResolver;
|
||||
import ru.noties.markwon.UrlProcessor;
|
||||
import ru.noties.markwon.spans.AsyncDrawable;
|
||||
import ru.noties.markwon.spans.AsyncDrawableSpan;
|
||||
@ -17,14 +20,17 @@ class ImageProviderImpl implements SpannableHtmlParser.ImageProvider {
|
||||
private final SpannableTheme theme;
|
||||
private final AsyncDrawable.Loader loader;
|
||||
private final UrlProcessor urlProcessor;
|
||||
private final ImageClickResolver imageClickResolver;
|
||||
|
||||
ImageProviderImpl(
|
||||
@NonNull SpannableTheme theme,
|
||||
@NonNull AsyncDrawable.Loader loader,
|
||||
@NonNull UrlProcessor urlProcessor) {
|
||||
@NonNull UrlProcessor urlProcessor,
|
||||
@NonNull ImageClickResolver imageClickResolver) {
|
||||
this.theme = theme;
|
||||
this.loader = loader;
|
||||
this.urlProcessor = urlProcessor;
|
||||
this.imageClickResolver = imageClickResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -53,6 +59,14 @@ class ImageProviderImpl implements SpannableHtmlParser.ImageProvider {
|
||||
final SpannableString string = new SpannableString(replacement);
|
||||
string.setSpan(span, 0, string.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
final ClickableSpan clickableSpan = new ClickableSpan() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
imageClickResolver.resolve(view, destination);
|
||||
}
|
||||
};
|
||||
string.setSpan(clickableSpan, 0, string.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
spanned = string;
|
||||
} else {
|
||||
spanned = null;
|
||||
|
@ -10,6 +10,8 @@ import android.text.Spanned;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import ru.noties.markwon.ImageClickResolver;
|
||||
import ru.noties.markwon.ImageClickResolverDef;
|
||||
import ru.noties.markwon.LinkResolverDef;
|
||||
import ru.noties.markwon.UrlProcessor;
|
||||
import ru.noties.markwon.UrlProcessorNoOp;
|
||||
@ -25,7 +27,8 @@ public class SpannableHtmlParser {
|
||||
@NonNull SpannableTheme theme,
|
||||
@NonNull AsyncDrawable.Loader loader
|
||||
) {
|
||||
return builderWithDefaults(theme, loader, null, null)
|
||||
return builderWithDefaults(theme, loader, null, null,
|
||||
null)
|
||||
.build();
|
||||
}
|
||||
|
||||
@ -33,9 +36,10 @@ public class SpannableHtmlParser {
|
||||
@NonNull SpannableTheme theme,
|
||||
@NonNull AsyncDrawable.Loader loader,
|
||||
@NonNull UrlProcessor urlProcessor,
|
||||
@NonNull LinkSpan.Resolver resolver
|
||||
@NonNull LinkSpan.Resolver linkResolver,
|
||||
@NonNull ImageClickResolver imageClickResolver
|
||||
) {
|
||||
return builderWithDefaults(theme, loader, urlProcessor, resolver)
|
||||
return builderWithDefaults(theme, loader, urlProcessor, linkResolver, imageClickResolver)
|
||||
.build();
|
||||
}
|
||||
|
||||
@ -44,22 +48,28 @@ public class SpannableHtmlParser {
|
||||
}
|
||||
|
||||
public static Builder builderWithDefaults(@NonNull SpannableTheme theme) {
|
||||
return builderWithDefaults(theme, null, null, null);
|
||||
return builderWithDefaults(theme, null, null, null,
|
||||
null);
|
||||
}
|
||||
|
||||
public static Builder builderWithDefaults(
|
||||
@NonNull SpannableTheme theme,
|
||||
@Nullable AsyncDrawable.Loader asyncDrawableLoader,
|
||||
@Nullable UrlProcessor urlProcessor,
|
||||
@Nullable LinkSpan.Resolver resolver
|
||||
@Nullable LinkSpan.Resolver linkResolver,
|
||||
@Nullable ImageClickResolver imageClickResolver
|
||||
) {
|
||||
|
||||
if (urlProcessor == null) {
|
||||
urlProcessor = new UrlProcessorNoOp();
|
||||
}
|
||||
|
||||
if (resolver == null) {
|
||||
resolver = new LinkResolverDef();
|
||||
if (linkResolver == null) {
|
||||
linkResolver = new LinkResolverDef();
|
||||
}
|
||||
|
||||
if (imageClickResolver == null) {
|
||||
imageClickResolver = new ImageClickResolverDef();
|
||||
}
|
||||
|
||||
final BoldProvider boldProvider = new BoldProvider();
|
||||
@ -68,7 +78,8 @@ public class SpannableHtmlParser {
|
||||
|
||||
final ImageProvider imageProvider;
|
||||
if (asyncDrawableLoader != null) {
|
||||
imageProvider = new ImageProviderImpl(theme, asyncDrawableLoader, urlProcessor);
|
||||
imageProvider = new ImageProviderImpl(theme, asyncDrawableLoader, urlProcessor,
|
||||
imageClickResolver);
|
||||
} else {
|
||||
imageProvider = null;
|
||||
}
|
||||
@ -86,7 +97,7 @@ public class SpannableHtmlParser {
|
||||
.simpleTag("del", strikeProvider)
|
||||
.simpleTag("s", strikeProvider)
|
||||
.simpleTag("strike", strikeProvider)
|
||||
.simpleTag("a", new LinkProvider(theme, urlProcessor, resolver))
|
||||
.simpleTag("a", new LinkProvider(theme, urlProcessor, linkResolver))
|
||||
.imageProvider(imageProvider);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user