Merge 4b01d37f3098cb781bad7761f38455943585400b into 9bdcf8551c60de116d0a035fd9d812218777da1e
This commit is contained in:
commit
73d7e00a36
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
# Markwon
|
# Markwon
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
[](http://search.maven.org/#search|ga|1|g%3A%22ru.noties%22%20AND%20a%3A%markwon%22)
|
[](http://search.maven.org/#search|ga|1|g%3A%22ru.noties%22%20AND%20a%3A%markwon%22)
|
||||||
[](http://search.maven.org/#search|ga|1|g%3A%22ru.noties%22%20AND%20a%3A%markwon-image-loader%22)
|
[](http://search.maven.org/#search|ga|1|g%3A%22ru.noties%22%20AND%20a%3A%markwon-image-loader%22)
|
||||||
[](http://search.maven.org/#search|ga|1|g%3A%22ru.noties%22%20AND%20a%3A%markwon-view%22)
|
[](http://search.maven.org/#search|ga|1|g%3A%22ru.noties%22%20AND%20a%3A%markwon-view%22)
|
||||||
|
@ -36,4 +36,6 @@ dependencies {
|
|||||||
|
|
||||||
compile 'com.google.dagger:dagger:2.10'
|
compile 'com.google.dagger:dagger:2.10'
|
||||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.10'
|
annotationProcessor 'com.google.dagger:dagger-compiler:2.10'
|
||||||
|
|
||||||
|
implementation "com.android.support:appcompat-v7:27.0.2"
|
||||||
}
|
}
|
||||||
|
5
app/proguard.pro
vendored
5
app/proguard.pro
vendored
@ -1,5 +0,0 @@
|
|||||||
-dontwarn okhttp3.**
|
|
||||||
-dontwarn okio.**
|
|
||||||
|
|
||||||
-keep class com.caverock.androidsvg.** { *; }
|
|
||||||
-dontwarn com.caverock.androidsvg.**
|
|
@ -16,6 +16,9 @@ import okhttp3.Cache;
|
|||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import ru.noties.markwon.il.AsyncDrawableLoader;
|
import ru.noties.markwon.il.AsyncDrawableLoader;
|
||||||
import ru.noties.markwon.spans.AsyncDrawable;
|
import ru.noties.markwon.spans.AsyncDrawable;
|
||||||
|
import ru.noties.markwon.spans.configuration.image.ImageConfig;
|
||||||
|
import ru.noties.markwon.spans.configuration.image.ImageGravity;
|
||||||
|
import ru.noties.markwon.spans.configuration.image.ImageWidth;
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
class AppModule {
|
class AppModule {
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
package ru.noties.markwon;
|
package ru.noties.markwon;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Typeface;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
import android.support.annotation.FontRes;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v4.content.res.ResourcesCompat;
|
||||||
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
@ -14,13 +18,14 @@ import javax.inject.Inject;
|
|||||||
|
|
||||||
import ru.noties.debug.Debug;
|
import ru.noties.debug.Debug;
|
||||||
import ru.noties.markwon.spans.AsyncDrawable;
|
import ru.noties.markwon.spans.AsyncDrawable;
|
||||||
|
import ru.noties.markwon.spans.SpannableTheme;
|
||||||
|
import ru.noties.markwon.spans.configuration.heading.HeadingConfig;
|
||||||
|
import ru.noties.markwon.spans.configuration.heading.HeadingTypeConfig;
|
||||||
|
|
||||||
@ActivityScope
|
@ActivityScope
|
||||||
public class MarkdownRenderer {
|
public class MarkdownRenderer {
|
||||||
|
|
||||||
interface MarkdownReadyListener {
|
private final Context context;
|
||||||
void onMarkdownReady(CharSequence markdown);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
AsyncDrawable.Loader loader;
|
AsyncDrawable.Loader loader;
|
||||||
@ -34,14 +39,15 @@ public class MarkdownRenderer {
|
|||||||
private Future<?> task;
|
private Future<?> task;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
MarkdownRenderer() {
|
MarkdownRenderer(Context context) {
|
||||||
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render(
|
public void render(
|
||||||
@NonNull final Context context,
|
@NonNull final Context context,
|
||||||
@Nullable final Uri uri,
|
@Nullable final Uri uri,
|
||||||
@NonNull final String markdown,
|
@NonNull final String markdown,
|
||||||
@NonNull final MarkdownReadyListener listener) {
|
@NonNull final MarkdownReadyListener listener) {
|
||||||
cancel();
|
cancel();
|
||||||
task = service.submit(new Runnable() {
|
task = service.submit(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@ -55,9 +61,10 @@ public class MarkdownRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final SpannableConfiguration configuration = SpannableConfiguration.builder(context)
|
final SpannableConfiguration configuration = SpannableConfiguration.builder(context)
|
||||||
.asyncDrawableLoader(loader)
|
.theme(getSpannableTheme())
|
||||||
.urlProcessor(urlProcessor)
|
.asyncDrawableLoader(loader)
|
||||||
.build();
|
.urlProcessor(urlProcessor)
|
||||||
|
.build();
|
||||||
|
|
||||||
final long start = SystemClock.uptimeMillis();
|
final long start = SystemClock.uptimeMillis();
|
||||||
|
|
||||||
@ -92,4 +99,25 @@ public class MarkdownRenderer {
|
|||||||
private boolean isCancelled() {
|
private boolean isCancelled() {
|
||||||
return task == null || task.isCancelled();
|
return task == null || task.isCancelled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private HeadingConfig getHeadingConfig() {
|
||||||
|
final HeadingTypeConfig h1 = new HeadingTypeConfig(-1, Color.RED, getTypeface(R.font.opensans_semibold));
|
||||||
|
final HeadingTypeConfig h2 = new HeadingTypeConfig(-1, Color.BLUE, getTypeface(R.font.opensans_regular));
|
||||||
|
|
||||||
|
return new HeadingConfig(h1, h2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SpannableTheme getSpannableTheme() {
|
||||||
|
return SpannableTheme.builderWithDefaults(context)
|
||||||
|
.headingConfig(getHeadingConfig(), context.getResources().getDisplayMetrics().density)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Typeface getTypeface(@FontRes int font){
|
||||||
|
return ResourcesCompat.getFont(context, font);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MarkdownReadyListener {
|
||||||
|
void onMarkdownReady(CharSequence markdown);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
25
app/src/main/res/font/app_font.xml
Normal file
25
app/src/main/res/font/app_font.xml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<font-family
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<!-- Regular -->
|
||||||
|
<font
|
||||||
|
android:font="@font/opensans_regular"
|
||||||
|
android:fontStyle="normal"
|
||||||
|
android:fontWeight="400"
|
||||||
|
|
||||||
|
app:font="@font/opensans_regular"
|
||||||
|
app:fontStyle="normal"
|
||||||
|
app:fontWeight="400"/>
|
||||||
|
|
||||||
|
<!-- Semi-bold -->
|
||||||
|
<font
|
||||||
|
android:font="@font/opensans_semibold"
|
||||||
|
android:fontStyle="normal"
|
||||||
|
android:fontWeight="700"
|
||||||
|
|
||||||
|
app:font="@font/opensans_semibold"
|
||||||
|
app:fontStyle="normal"
|
||||||
|
app:fontWeight="700"/>
|
||||||
|
</font-family>
|
BIN
app/src/main/res/font/opensans_regular.ttf
Executable file
BIN
app/src/main/res/font/opensans_regular.ttf
Executable file
Binary file not shown.
BIN
app/src/main/res/font/opensans_semibold.ttf
Normal file
BIN
app/src/main/res/font/opensans_semibold.ttf
Normal file
Binary file not shown.
44
artifactory-mvn-push.gradle
Normal file
44
artifactory-mvn-push.gradle
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
apply plugin: 'com.jfrog.artifactory'
|
||||||
|
apply plugin: 'digital.wup.android-maven-publish'
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
aar(MavenPublication) {
|
||||||
|
groupId "${GROUP}.auto1"
|
||||||
|
version VERSION_NAME
|
||||||
|
artifactId POM_ARTIFACT_ID
|
||||||
|
|
||||||
|
from components.android
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
artifactory {
|
||||||
|
contextUrl = artifactory_repository_url
|
||||||
|
publish {
|
||||||
|
repository {
|
||||||
|
repoKey = artifactory_repository_name
|
||||||
|
|
||||||
|
username = artifactory_username
|
||||||
|
password = artifactory_password
|
||||||
|
}
|
||||||
|
defaults {
|
||||||
|
publications('aar')
|
||||||
|
publishArtifacts = true
|
||||||
|
|
||||||
|
properties = ['qa.level': 'basic', 'q.os': 'android', 'dev.team': 'mobile-android']
|
||||||
|
publishPom = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
task cleanBuildPublish {
|
||||||
|
dependsOn 'clean'
|
||||||
|
dependsOn 'assembleRelease'
|
||||||
|
dependsOn 'artifactoryPublish'
|
||||||
|
tasks.findByName('assembleRelease').mustRunAfter 'clean'
|
||||||
|
tasks.findByName('artifactoryPublish').dependsOn 'generatePomFileForAarPublication'
|
||||||
|
tasks.findByName('artifactoryPublish').mustRunAfter 'assembleRelease'
|
||||||
|
}
|
||||||
|
}
|
11
build.gradle
11
build.gradle
@ -1,10 +1,14 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
|
ext.kotlin_version = '1.2.10'
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
google()
|
google()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:2.3.3'
|
classpath 'com.android.tools.build:gradle:3.0.1'
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.4.12"
|
||||||
|
classpath 'digital.wup:android-maven-publish:3.1.1'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,14 +31,13 @@ task wrapper(type: Wrapper) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
|
|
||||||
// Config
|
// Config
|
||||||
BUILD_TOOLS = '26.0.3'
|
BUILD_TOOLS = '27.0.1'
|
||||||
TARGET_SDK = 26
|
TARGET_SDK = 26
|
||||||
MIN_SDK = 16
|
MIN_SDK = 16
|
||||||
|
|
||||||
// Dependencies
|
// Dependencies
|
||||||
final def supportVersion = '26.1.0'
|
final def supportVersion = '27.0.2'
|
||||||
SUPPORT_ANNOTATIONS = "com.android.support:support-annotations:$supportVersion"
|
SUPPORT_ANNOTATIONS = "com.android.support:support-annotations:$supportVersion"
|
||||||
SUPPORT_APP_COMPAT = "com.android.support:appcompat-v7:$supportVersion"
|
SUPPORT_APP_COMPAT = "com.android.support:appcompat-v7:$supportVersion"
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ android {
|
|||||||
targetSdkVersion TARGET_SDK
|
targetSdkVersion TARGET_SDK
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName version
|
versionName version
|
||||||
|
|
||||||
|
consumerProguardFiles 'lib-proguard-rules.pro'
|
||||||
}
|
}
|
||||||
|
|
||||||
lintOptions {
|
lintOptions {
|
||||||
@ -19,12 +21,10 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(':library')
|
implementation project(':library')
|
||||||
compile ANDROID_SVG
|
implementation ANDROID_SVG
|
||||||
compile ANDROID_GIF
|
implementation ANDROID_GIF
|
||||||
compile OK_HTTP
|
implementation OK_HTTP
|
||||||
}
|
}
|
||||||
|
|
||||||
if (project.hasProperty('release')) {
|
apply from: '../artifactory-mvn-push.gradle'
|
||||||
apply from: 'https://raw.githubusercontent.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle'
|
|
||||||
}
|
|
5
library-image-loader/lib-proguard-rules.pro
Normal file
5
library-image-loader/lib-proguard-rules.pro
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
-dontwarn okhttp3.**
|
||||||
|
-dontwarn okio.**
|
||||||
|
|
||||||
|
-keep class com.caverock.androidsvg.** { *; }
|
||||||
|
-dontwarn com.caverock.androidsvg.**
|
@ -36,6 +36,7 @@ import okhttp3.Response;
|
|||||||
import okhttp3.ResponseBody;
|
import okhttp3.ResponseBody;
|
||||||
import pl.droidsonroids.gif.GifDrawable;
|
import pl.droidsonroids.gif.GifDrawable;
|
||||||
import ru.noties.markwon.spans.AsyncDrawable;
|
import ru.noties.markwon.spans.AsyncDrawable;
|
||||||
|
import ru.noties.markwon.spans.configuration.image.ImageConfig;
|
||||||
|
|
||||||
public class AsyncDrawableLoader implements AsyncDrawable.Loader {
|
public class AsyncDrawableLoader implements AsyncDrawable.Loader {
|
||||||
|
|
||||||
@ -58,6 +59,7 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
|
|||||||
private final ExecutorService executorService;
|
private final ExecutorService executorService;
|
||||||
private final Handler mainThread;
|
private final Handler mainThread;
|
||||||
private final Drawable errorDrawable;
|
private final Drawable errorDrawable;
|
||||||
|
private final ImageConfig imageConfig;
|
||||||
|
|
||||||
private final Map<String, Future<?>> requests;
|
private final Map<String, Future<?>> requests;
|
||||||
|
|
||||||
@ -67,6 +69,7 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
|
|||||||
this.executorService = builder.executorService;
|
this.executorService = builder.executorService;
|
||||||
this.mainThread = new Handler(Looper.getMainLooper());
|
this.mainThread = new Handler(Looper.getMainLooper());
|
||||||
this.errorDrawable = builder.errorDrawable;
|
this.errorDrawable = builder.errorDrawable;
|
||||||
|
this.imageConfig = builder.imageConfig;
|
||||||
this.requests = new HashMap<>(3);
|
this.requests = new HashMap<>(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +149,7 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
|
|||||||
public void run() {
|
public void run() {
|
||||||
final AsyncDrawable asyncDrawable = reference.get();
|
final AsyncDrawable asyncDrawable = reference.get();
|
||||||
if (asyncDrawable != null && asyncDrawable.isAttached()) {
|
if (asyncDrawable != null && asyncDrawable.isAttached()) {
|
||||||
asyncDrawable.setResult(out);
|
asyncDrawable.setResult(out, imageConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -345,6 +348,7 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
|
|||||||
private Resources resources;
|
private Resources resources;
|
||||||
private ExecutorService executorService;
|
private ExecutorService executorService;
|
||||||
private Drawable errorDrawable;
|
private Drawable errorDrawable;
|
||||||
|
private ImageConfig imageConfig;
|
||||||
|
|
||||||
public Builder client(@NonNull OkHttpClient client) {
|
public Builder client(@NonNull OkHttpClient client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
@ -366,6 +370,11 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder imageConfig(ImageConfig imageConfig) {
|
||||||
|
this.imageConfig = imageConfig;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public AsyncDrawableLoader build() {
|
public AsyncDrawableLoader build() {
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
client = new OkHttpClient();
|
client = new OkHttpClient();
|
||||||
@ -377,6 +386,9 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
|
|||||||
// we will use executor from okHttp
|
// we will use executor from okHttp
|
||||||
executorService = client.dispatcher().executorService();
|
executorService = client.dispatcher().executorService();
|
||||||
}
|
}
|
||||||
|
if(imageConfig == null){
|
||||||
|
imageConfig = new ImageConfig();
|
||||||
|
}
|
||||||
return new AsyncDrawableLoader(this);
|
return new AsyncDrawableLoader(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
apply plugin: 'com.android.library'
|
apply plugin: 'com.android.library'
|
||||||
|
apply plugin: 'kotlin-android'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|
||||||
@ -11,15 +12,24 @@ android {
|
|||||||
versionCode 1
|
versionCode 1
|
||||||
versionName version
|
versionName version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
libraryVariants.all { variant ->
|
||||||
|
variant.outputs.all {
|
||||||
|
outputFileName = "${POM_ARTIFACT_ID}-release.aar"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile SUPPORT_ANNOTATIONS
|
api SUPPORT_ANNOTATIONS
|
||||||
compile COMMON_MARK
|
implementation COMMON_MARK
|
||||||
compile COMMON_MARK_STRIKETHROUGHT
|
implementation COMMON_MARK_STRIKETHROUGHT
|
||||||
compile COMMON_MARK_TABLE
|
implementation COMMON_MARK_TABLE
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (project.hasProperty('release')) {
|
repositories {
|
||||||
apply from: 'https://raw.githubusercontent.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle'
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apply from: '../artifactory-mvn-push.gradle'
|
@ -12,25 +12,26 @@ import android.support.annotation.Nullable;
|
|||||||
|
|
||||||
import ru.noties.markwon.renderer.html.ImageSize;
|
import ru.noties.markwon.renderer.html.ImageSize;
|
||||||
import ru.noties.markwon.renderer.html.ImageSizeResolver;
|
import ru.noties.markwon.renderer.html.ImageSizeResolver;
|
||||||
|
import ru.noties.markwon.spans.configuration.image.ImageConfig;
|
||||||
|
import ru.noties.markwon.spans.configuration.image.ImageGravity;
|
||||||
|
import ru.noties.markwon.spans.configuration.image.ImageWidth;
|
||||||
|
|
||||||
public class AsyncDrawable extends Drawable {
|
public class AsyncDrawable extends Drawable {
|
||||||
|
|
||||||
public interface Loader {
|
|
||||||
|
|
||||||
void load(@NonNull String destination, @NonNull AsyncDrawable drawable);
|
|
||||||
|
|
||||||
void cancel(@NonNull String destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final String destination;
|
private final String destination;
|
||||||
|
|
||||||
private final Loader loader;
|
private final Loader loader;
|
||||||
|
|
||||||
private final ImageSize imageSize;
|
private final ImageSize imageSize;
|
||||||
|
|
||||||
private final ImageSizeResolver imageSizeResolver;
|
private final ImageSizeResolver imageSizeResolver;
|
||||||
|
|
||||||
private Drawable result;
|
private Drawable result;
|
||||||
|
|
||||||
private Callback callback;
|
private Callback callback;
|
||||||
|
|
||||||
private int canvasWidth;
|
private int canvasWidth;
|
||||||
|
|
||||||
private float textSize;
|
private float textSize;
|
||||||
|
|
||||||
public AsyncDrawable(@NonNull String destination, @NonNull Loader loader) {
|
public AsyncDrawable(@NonNull String destination, @NonNull Loader loader) {
|
||||||
@ -41,10 +42,10 @@ public class AsyncDrawable extends Drawable {
|
|||||||
* @since 1.0.1
|
* @since 1.0.1
|
||||||
*/
|
*/
|
||||||
public AsyncDrawable(
|
public AsyncDrawable(
|
||||||
@NonNull String destination,
|
@NonNull String destination,
|
||||||
@NonNull Loader loader,
|
@NonNull Loader loader,
|
||||||
@Nullable ImageSizeResolver imageSizeResolver,
|
@Nullable ImageSizeResolver imageSizeResolver,
|
||||||
@Nullable ImageSize imageSize
|
@Nullable ImageSize imageSize
|
||||||
) {
|
) {
|
||||||
this.destination = destination;
|
this.destination = destination;
|
||||||
this.loader = loader;
|
this.loader = loader;
|
||||||
@ -91,7 +92,7 @@ public class AsyncDrawable extends Drawable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setResult(@NonNull Drawable result) {
|
public void setResult(@NonNull Drawable result, @NonNull ImageConfig imageConfig) {
|
||||||
|
|
||||||
// if we have previous one, detach it
|
// if we have previous one, detach it
|
||||||
if (this.result != null) {
|
if (this.result != null) {
|
||||||
@ -101,7 +102,7 @@ public class AsyncDrawable extends Drawable {
|
|||||||
this.result = result;
|
this.result = result;
|
||||||
this.result.setCallback(callback);
|
this.result.setCallback(callback);
|
||||||
|
|
||||||
final Rect bounds = resolveBounds();
|
final Rect bounds = resolveBounds(imageConfig);
|
||||||
result.setBounds(bounds);
|
result.setBounds(bounds);
|
||||||
setBounds(bounds);
|
setBounds(bounds);
|
||||||
|
|
||||||
@ -168,17 +169,55 @@ public class AsyncDrawable extends Drawable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param imageConfig
|
||||||
* @since 1.0.1
|
* @since 1.0.1
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
private Rect resolveBounds() {
|
private Rect resolveBounds(@NonNull ImageConfig imageConfig) {
|
||||||
final Rect rect;
|
final Rect rect;
|
||||||
if (imageSizeResolver == null
|
if (imageSizeResolver == null
|
||||||
|| imageSize == null) {
|
|| imageSize == null) {
|
||||||
rect = result.getBounds();
|
rect = result.getBounds();
|
||||||
} else {
|
} else {
|
||||||
rect = imageSizeResolver.resolveImageSize(imageSize, result.getBounds(), canvasWidth, textSize);
|
rect = imageSizeResolver.resolveImageSize(imageSize, result.getBounds(), canvasWidth, textSize);
|
||||||
}
|
}
|
||||||
return rect;
|
return adjustBounds(rect, imageConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Rect adjustBounds(Rect bounds, ImageConfig imageConfig) {
|
||||||
|
final ImageGravity gravity = imageConfig.getGravity();
|
||||||
|
final ImageWidth imageWidth = imageConfig.getImageWidth();
|
||||||
|
|
||||||
|
if (imageWidth == ImageWidth.MatchParent) {
|
||||||
|
final float growthRatio = (float) canvasWidth / bounds.width();
|
||||||
|
bounds.left = 0;
|
||||||
|
bounds.right = canvasWidth;
|
||||||
|
bounds.bottom = (int) (bounds.top + bounds.height() * growthRatio);
|
||||||
|
} else {
|
||||||
|
switch (gravity) {
|
||||||
|
case Left:
|
||||||
|
//left is unchanged
|
||||||
|
break;
|
||||||
|
case Right:
|
||||||
|
bounds.left = canvasWidth - bounds.width();
|
||||||
|
bounds.right = canvasWidth;
|
||||||
|
break;
|
||||||
|
case Center:
|
||||||
|
final int center = canvasWidth / 2;
|
||||||
|
final int imageRadius = bounds.width() / 2;
|
||||||
|
bounds.left = center - imageRadius;
|
||||||
|
bounds.right = center + imageRadius;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Loader {
|
||||||
|
|
||||||
|
void load(@NonNull String destination, @NonNull AsyncDrawable drawable);
|
||||||
|
|
||||||
|
void cancel(@NonNull String destination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,14 @@ import android.text.TextPaint;
|
|||||||
import android.text.style.LeadingMarginSpan;
|
import android.text.style.LeadingMarginSpan;
|
||||||
import android.text.style.MetricAffectingSpan;
|
import android.text.style.MetricAffectingSpan;
|
||||||
|
|
||||||
|
import ru.noties.markwon.spans.configuration.heading.HeadingType;
|
||||||
|
|
||||||
public class HeadingSpan extends MetricAffectingSpan implements LeadingMarginSpan {
|
public class HeadingSpan extends MetricAffectingSpan implements LeadingMarginSpan {
|
||||||
|
|
||||||
private final SpannableTheme theme;
|
private final SpannableTheme theme;
|
||||||
private final Rect rect = ObjectsPool.rect();
|
private final Rect rect = ObjectsPool.rect();
|
||||||
private final Paint paint = ObjectsPool.paint();
|
private final Paint paint = ObjectsPool.paint();
|
||||||
private final int level;
|
@HeadingType private final int level;
|
||||||
|
|
||||||
public HeadingSpan(@NonNull SpannableTheme theme, @IntRange(from = 1, to = 6) int level) {
|
public HeadingSpan(@NonNull SpannableTheme theme, @IntRange(from = 1, to = 6) int level) {
|
||||||
this.theme = theme;
|
this.theme = theme;
|
||||||
|
@ -9,12 +9,15 @@ import android.support.annotation.AttrRes;
|
|||||||
import android.support.annotation.ColorInt;
|
import android.support.annotation.ColorInt;
|
||||||
import android.support.annotation.Dimension;
|
import android.support.annotation.Dimension;
|
||||||
import android.support.annotation.FloatRange;
|
import android.support.annotation.FloatRange;
|
||||||
import android.support.annotation.IntRange;
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.text.TextPaint;
|
import android.text.TextPaint;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
|
|
||||||
|
import ru.noties.markwon.spans.configuration.heading.HeadingConfig;
|
||||||
|
import ru.noties.markwon.spans.configuration.heading.HeadingType;
|
||||||
|
import ru.noties.markwon.spans.configuration.heading.HeadingTypeConfig;
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
public class SpannableTheme {
|
public class SpannableTheme {
|
||||||
|
|
||||||
@ -78,16 +81,16 @@ public class SpannableTheme {
|
|||||||
|
|
||||||
final Dip dip = new Dip(context);
|
final Dip dip = new Dip(context);
|
||||||
return new Builder()
|
return new Builder()
|
||||||
.linkColor(linkColor)
|
.linkColor(linkColor)
|
||||||
.codeMultilineMargin(dip.toPx(8))
|
.codeMultilineMargin(dip.toPx(8))
|
||||||
.blockMargin(dip.toPx(24))
|
.blockMargin(dip.toPx(24))
|
||||||
.blockQuoteWidth(dip.toPx(4))
|
.blockQuoteWidth(dip.toPx(4))
|
||||||
.bulletListItemStrokeWidth(dip.toPx(1))
|
.bulletListItemStrokeWidth(dip.toPx(1))
|
||||||
.headingBreakHeight(dip.toPx(1))
|
.headingConfig(new HeadingConfig(), dip.density)
|
||||||
.thematicBreakHeight(dip.toPx(4))
|
.thematicBreakHeight(dip.toPx(4))
|
||||||
.tableCellPadding(dip.toPx(4))
|
.tableCellPadding(dip.toPx(4))
|
||||||
.tableBorderWidth(dip.toPx(1))
|
.tableBorderWidth(dip.toPx(1))
|
||||||
.taskListDrawable(new TaskListDrawable(linkColor, linkColor, backgroundColor));
|
.taskListDrawable(new TaskListDrawable(linkColor, linkColor, backgroundColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int resolve(Context context, @AttrRes int attr) {
|
private static int resolve(Context context, @AttrRes int attr) {
|
||||||
@ -104,14 +107,15 @@ public class SpannableTheme {
|
|||||||
protected static final int BLOCK_QUOTE_DEF_COLOR_ALPHA = 25;
|
protected static final int BLOCK_QUOTE_DEF_COLOR_ALPHA = 25;
|
||||||
|
|
||||||
protected static final int CODE_DEF_BACKGROUND_COLOR_ALPHA = 25;
|
protected static final int CODE_DEF_BACKGROUND_COLOR_ALPHA = 25;
|
||||||
|
|
||||||
protected static final float CODE_DEF_TEXT_SIZE_RATIO = .87F;
|
protected static final float CODE_DEF_TEXT_SIZE_RATIO = .87F;
|
||||||
|
|
||||||
protected static final int HEADING_DEF_BREAK_COLOR_ALPHA = 75;
|
protected static final int HEADING_DEF_BREAK_COLOR_ALPHA = 75;
|
||||||
|
|
||||||
// taken from html spec (most browsers render headings like that)
|
// taken from html spec (most browsers render headings like that)
|
||||||
// is not exposed via protected modifier in order to disallow modification
|
// is not exposed via protected modifier in order to disallow modification
|
||||||
private static final float[] HEADING_SIZES = {
|
private static final float[] HEADING_SCALES = {
|
||||||
2.F, 1.5F, 1.17F, 1.F, .83F, .67F,
|
2.F, 1.5F, 1.17F, 1.F, .83F, .67F,
|
||||||
};
|
};
|
||||||
|
|
||||||
protected static final float SCRIPT_DEF_TEXT_SIZE_RATIO = .75F;
|
protected static final float SCRIPT_DEF_TEXT_SIZE_RATIO = .75F;
|
||||||
@ -159,11 +163,7 @@ public class SpannableTheme {
|
|||||||
// applied ONLY if default typeface was used, otherwise, not applied
|
// applied ONLY if default typeface was used, otherwise, not applied
|
||||||
protected final int codeTextSize;
|
protected final int codeTextSize;
|
||||||
|
|
||||||
// by default paint.getStrokeWidth
|
protected final HeadingConfig headingConfig;
|
||||||
protected final int headingBreakHeight;
|
|
||||||
|
|
||||||
// by default, text color with `HEADING_DEF_BREAK_COLOR_ALPHA` applied alpha
|
|
||||||
protected final int headingBreakColor;
|
|
||||||
|
|
||||||
// by default `SCRIPT_DEF_TEXT_SIZE_RATIO`
|
// by default `SCRIPT_DEF_TEXT_SIZE_RATIO`
|
||||||
protected final float scriptTextSizeRatio;
|
protected final float scriptTextSizeRatio;
|
||||||
@ -202,8 +202,7 @@ public class SpannableTheme {
|
|||||||
this.codeMultilineMargin = builder.codeMultilineMargin;
|
this.codeMultilineMargin = builder.codeMultilineMargin;
|
||||||
this.codeTypeface = builder.codeTypeface;
|
this.codeTypeface = builder.codeTypeface;
|
||||||
this.codeTextSize = builder.codeTextSize;
|
this.codeTextSize = builder.codeTextSize;
|
||||||
this.headingBreakHeight = builder.headingBreakHeight;
|
this.headingConfig = builder.headingConfig;
|
||||||
this.headingBreakColor = builder.headingBreakColor;
|
|
||||||
this.scriptTextSizeRatio = builder.scriptTextSizeRatio;
|
this.scriptTextSizeRatio = builder.scriptTextSizeRatio;
|
||||||
this.thematicBreakColor = builder.thematicBreakColor;
|
this.thematicBreakColor = builder.thematicBreakColor;
|
||||||
this.thematicBreakHeight = builder.thematicBreakHeight;
|
this.thematicBreakHeight = builder.thematicBreakHeight;
|
||||||
@ -214,7 +213,6 @@ public class SpannableTheme {
|
|||||||
this.taskListDrawable = builder.taskListDrawable;
|
this.taskListDrawable = builder.taskListDrawable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void applyLinkStyle(@NonNull Paint paint) {
|
public void applyLinkStyle(@NonNull Paint paint) {
|
||||||
paint.setUnderlineText(true);
|
paint.setUnderlineText(true);
|
||||||
if (linkColor != 0) {
|
if (linkColor != 0) {
|
||||||
@ -269,7 +267,7 @@ public class SpannableTheme {
|
|||||||
|
|
||||||
final int width;
|
final int width;
|
||||||
if (bulletWidth == 0
|
if (bulletWidth == 0
|
||||||
|| bulletWidth > min) {
|
|| bulletWidth > min) {
|
||||||
width = min;
|
width = min;
|
||||||
} else {
|
} else {
|
||||||
width = bulletWidth;
|
width = bulletWidth;
|
||||||
@ -322,13 +320,51 @@ public class SpannableTheme {
|
|||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyHeadingTextStyle(@NonNull Paint paint, @IntRange(from = 1, to = 6) int level) {
|
public void applyHeadingTextStyle(@NonNull Paint paint, @HeadingType int level) {
|
||||||
|
HeadingTypeConfig headingTypeConfig;
|
||||||
|
switch (level) {
|
||||||
|
case HeadingType.H1:
|
||||||
|
headingTypeConfig = headingConfig.getH1Config();
|
||||||
|
break;
|
||||||
|
case HeadingType.H2:
|
||||||
|
headingTypeConfig = headingConfig.getH2Config();
|
||||||
|
break;
|
||||||
|
case HeadingType.H3:
|
||||||
|
headingTypeConfig = headingConfig.getH3Config();
|
||||||
|
break;
|
||||||
|
case HeadingType.H4:
|
||||||
|
headingTypeConfig = headingConfig.getH4Config();
|
||||||
|
break;
|
||||||
|
case HeadingType.H5:
|
||||||
|
headingTypeConfig = headingConfig.getH5Config();
|
||||||
|
break;
|
||||||
|
case HeadingType.H6:
|
||||||
|
headingTypeConfig = headingConfig.getH6Config();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
headingTypeConfig = new HeadingTypeConfig();
|
||||||
|
}
|
||||||
|
|
||||||
paint.setFakeBoldText(true);
|
paint.setFakeBoldText(true);
|
||||||
paint.setTextSize(paint.getTextSize() * HEADING_SIZES[level - 1]);
|
|
||||||
|
final float textSize = headingTypeConfig.getTextScale() > 0 ?
|
||||||
|
headingTypeConfig.getTextScale() : HEADING_SCALES[level - 1];
|
||||||
|
paint.setTextSize(paint.getTextSize() * textSize);
|
||||||
|
|
||||||
|
final int textColor = headingTypeConfig.getTextColor();
|
||||||
|
if (textColor != -1) {
|
||||||
|
paint.setColor(textColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Typeface typeface = headingTypeConfig.getTypeface();
|
||||||
|
if(typeface != null){
|
||||||
|
paint.setTypeface(typeface);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyHeadingBreakStyle(@NonNull Paint paint) {
|
public void applyHeadingBreakStyle(@NonNull Paint paint) {
|
||||||
final int color;
|
final int color;
|
||||||
|
final int headingBreakColor = headingConfig.getHeadingBreakConfig().getHeadingBreakColor();
|
||||||
if (headingBreakColor != 0) {
|
if (headingBreakColor != 0) {
|
||||||
color = headingBreakColor;
|
color = headingBreakColor;
|
||||||
} else {
|
} else {
|
||||||
@ -336,6 +372,7 @@ public class SpannableTheme {
|
|||||||
}
|
}
|
||||||
paint.setColor(color);
|
paint.setColor(color);
|
||||||
paint.setStyle(Paint.Style.FILL);
|
paint.setStyle(Paint.Style.FILL);
|
||||||
|
final float headingBreakHeight = headingConfig.getHeadingBreakConfig().getHeadingBreakStrokeWidth();
|
||||||
if (headingBreakHeight >= 0) {
|
if (headingBreakHeight >= 0) {
|
||||||
//noinspection SuspiciousNameCombination
|
//noinspection SuspiciousNameCombination
|
||||||
paint.setStrokeWidth(headingBreakHeight);
|
paint.setStrokeWidth(headingBreakHeight);
|
||||||
@ -441,8 +478,7 @@ public class SpannableTheme {
|
|||||||
private int codeMultilineMargin;
|
private int codeMultilineMargin;
|
||||||
private Typeface codeTypeface;
|
private Typeface codeTypeface;
|
||||||
private int codeTextSize;
|
private int codeTextSize;
|
||||||
private int headingBreakHeight = -1;
|
private HeadingConfig headingConfig;
|
||||||
private int headingBreakColor;
|
|
||||||
private float scriptTextSizeRatio;
|
private float scriptTextSizeRatio;
|
||||||
private int thematicBreakColor;
|
private int thematicBreakColor;
|
||||||
private int thematicBreakHeight = -1;
|
private int thematicBreakHeight = -1;
|
||||||
@ -468,8 +504,7 @@ public class SpannableTheme {
|
|||||||
this.codeMultilineMargin = theme.codeMultilineMargin;
|
this.codeMultilineMargin = theme.codeMultilineMargin;
|
||||||
this.codeTypeface = theme.codeTypeface;
|
this.codeTypeface = theme.codeTypeface;
|
||||||
this.codeTextSize = theme.codeTextSize;
|
this.codeTextSize = theme.codeTextSize;
|
||||||
this.headingBreakHeight = theme.headingBreakHeight;
|
this.headingConfig = theme.headingConfig;
|
||||||
this.headingBreakColor = theme.headingBreakColor;
|
|
||||||
this.scriptTextSizeRatio = theme.scriptTextSizeRatio;
|
this.scriptTextSizeRatio = theme.scriptTextSizeRatio;
|
||||||
this.thematicBreakColor = theme.thematicBreakColor;
|
this.thematicBreakColor = theme.thematicBreakColor;
|
||||||
this.thematicBreakHeight = theme.thematicBreakHeight;
|
this.thematicBreakHeight = theme.thematicBreakHeight;
|
||||||
@ -553,14 +588,9 @@ public class SpannableTheme {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder headingBreakHeight(@Dimension int headingBreakHeight) {
|
public Builder headingConfig(HeadingConfig headingConfig, float density) {
|
||||||
this.headingBreakHeight = headingBreakHeight;
|
headingConfig.setDensityFactor(density);
|
||||||
return this;
|
this.headingConfig = headingConfig;
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public Builder headingBreakColor(@ColorInt int headingBreakColor) {
|
|
||||||
this.headingBreakColor = headingBreakColor;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -630,7 +660,7 @@ public class SpannableTheme {
|
|||||||
|
|
||||||
private static class Dip {
|
private static class Dip {
|
||||||
|
|
||||||
private final float density;
|
protected final float density;
|
||||||
|
|
||||||
Dip(@NonNull Context context) {
|
Dip(@NonNull Context context) {
|
||||||
this.density = context.getResources().getDisplayMetrics().density;
|
this.density = context.getResources().getDisplayMetrics().density;
|
||||||
|
@ -0,0 +1,80 @@
|
|||||||
|
package ru.noties.markwon.spans.configuration.heading
|
||||||
|
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.support.annotation.ColorInt
|
||||||
|
import android.support.annotation.Dimension
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration for heading type (H1, H2, ..., H6)
|
||||||
|
*
|
||||||
|
* Can define different configurations for all six types of headings,
|
||||||
|
* plus an extra configuration for the line breaks (only applies to H1 and H2)
|
||||||
|
*
|
||||||
|
* @property h1Config Config for H1 heading
|
||||||
|
* @property h2Config Config for H2 heading
|
||||||
|
* @property h3Config Config for H3 heading
|
||||||
|
* @property h4Config Config for H4 heading
|
||||||
|
* @property h5Config Config for H5 heading
|
||||||
|
* @property h6Config Config for H6 heading
|
||||||
|
* @property headingBreakConfig Config for line breaks (for H1 and H2)
|
||||||
|
*/
|
||||||
|
class HeadingConfig @JvmOverloads constructor(
|
||||||
|
val h1Config: HeadingTypeConfig = HeadingTypeConfig(),
|
||||||
|
val h2Config: HeadingTypeConfig = HeadingTypeConfig(),
|
||||||
|
val h3Config: HeadingTypeConfig = HeadingTypeConfig(),
|
||||||
|
val h4Config: HeadingTypeConfig = HeadingTypeConfig(),
|
||||||
|
val h5Config: HeadingTypeConfig = HeadingTypeConfig(),
|
||||||
|
val h6Config: HeadingTypeConfig = HeadingTypeConfig(),
|
||||||
|
val headingBreakConfig: HeadingBreakConfig = HeadingBreakConfig()
|
||||||
|
) {
|
||||||
|
fun setDensityFactor(factor: Float) {
|
||||||
|
h1Config.densityFactor = factor
|
||||||
|
h2Config.densityFactor = factor
|
||||||
|
h3Config.densityFactor = factor
|
||||||
|
h4Config.densityFactor = factor
|
||||||
|
h5Config.densityFactor = factor
|
||||||
|
h6Config.densityFactor = factor
|
||||||
|
headingBreakConfig.densityFactor = factor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration for given heading type (H1, H2, ..., H6)
|
||||||
|
*
|
||||||
|
* Can set text size, text color and font (typeface)
|
||||||
|
*
|
||||||
|
* @property textScale Text scale for heading
|
||||||
|
* @property textColor Text color for heading
|
||||||
|
* @property typeface Typeface for heading
|
||||||
|
*/
|
||||||
|
class HeadingTypeConfig @JvmOverloads constructor(
|
||||||
|
//Standard sizes available at #SpannableTheme.java:HEADING_SIZES
|
||||||
|
val textScale: Float = -1F,
|
||||||
|
|
||||||
|
@ColorInt val textColor: Int = -1,
|
||||||
|
|
||||||
|
val typeface: Typeface? = null
|
||||||
|
) {
|
||||||
|
internal var densityFactor: Float = -1F
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration for given heading type (H1, H2, ..., H6)
|
||||||
|
*
|
||||||
|
* Can set text size, text color and font (typeface)
|
||||||
|
*
|
||||||
|
* @property headingBreakStrokeWidth Stroke width for heading's line break
|
||||||
|
* @property headingBreakColor Color for heading's line break
|
||||||
|
*/
|
||||||
|
class HeadingBreakConfig @JvmOverloads constructor(
|
||||||
|
// by default paint.getStrokeWidth
|
||||||
|
@Dimension headingBreakStrokeWidth: Int = -1,
|
||||||
|
|
||||||
|
// by default, text color with `HEADING_DEF_BREAK_COLOR_ALPHA` applied alpha
|
||||||
|
@ColorInt val headingBreakColor: Int = 0
|
||||||
|
) {
|
||||||
|
internal var densityFactor: Float = -1F
|
||||||
|
|
||||||
|
val headingBreakStrokeWidth: Float = headingBreakStrokeWidth.toFloat()
|
||||||
|
get() = field * densityFactor
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package ru.noties.markwon.spans.configuration.heading;
|
||||||
|
|
||||||
|
import android.support.annotation.IntDef;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
import static ru.noties.markwon.spans.configuration.heading.HeadingType.H1;
|
||||||
|
import static ru.noties.markwon.spans.configuration.heading.HeadingType.H2;
|
||||||
|
import static ru.noties.markwon.spans.configuration.heading.HeadingType.H3;
|
||||||
|
import static ru.noties.markwon.spans.configuration.heading.HeadingType.H4;
|
||||||
|
import static ru.noties.markwon.spans.configuration.heading.HeadingType.H5;
|
||||||
|
import static ru.noties.markwon.spans.configuration.heading.HeadingType.H6;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by daniel.leal on 13.12.17.
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef({H1, H2, H3, H4, H5, H6})
|
||||||
|
public @interface HeadingType {
|
||||||
|
int H1 = 1;
|
||||||
|
int H2 = 2;
|
||||||
|
int H3 = 3;
|
||||||
|
int H4 = 4;
|
||||||
|
int H5 = 5;
|
||||||
|
int H6 = 6;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package ru.noties.markwon.spans.configuration.image
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration for images
|
||||||
|
*
|
||||||
|
* Can set two parameters: image width style and horizontal gravity
|
||||||
|
*
|
||||||
|
* @property imageWidth Width of the image to be displayed (WRAP_CONTENT or MATCH_PARENT)
|
||||||
|
* @property gravity Horizontal gravity (left, right or center)
|
||||||
|
*/
|
||||||
|
class ImageConfig @JvmOverloads constructor(
|
||||||
|
val imageWidth: ImageWidth = ImageWidth.Wrap,
|
||||||
|
val gravity: ImageGravity = ImageGravity.Left
|
||||||
|
)
|
||||||
|
|
||||||
|
enum class ImageGravity {
|
||||||
|
Left,
|
||||||
|
Center,
|
||||||
|
Right
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ImageWidth {
|
||||||
|
Wrap,
|
||||||
|
MatchParent
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user