Implement configuration for image loading

We support just two variables in the configuration: gravity and width.
Image will be place left, center or right aligned, and width will be
WRAP_CONTENT or MATCH_PARENT
This commit is contained in:
Daniel Leal 2017-12-19 19:18:31 +01:00
parent 23d7c09f27
commit a77c84a30c
3 changed files with 93 additions and 17 deletions

View File

@ -36,6 +36,7 @@ import okhttp3.Response;
import okhttp3.ResponseBody;
import pl.droidsonroids.gif.GifDrawable;
import ru.noties.markwon.spans.AsyncDrawable;
import ru.noties.markwon.spans.configuration.image.ImageConfig;
public class AsyncDrawableLoader implements AsyncDrawable.Loader {
@ -58,6 +59,7 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
private final ExecutorService executorService;
private final Handler mainThread;
private final Drawable errorDrawable;
private final ImageConfig imageConfig;
private final Map<String, Future<?>> requests;
@ -67,6 +69,7 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
this.executorService = builder.executorService;
this.mainThread = new Handler(Looper.getMainLooper());
this.errorDrawable = builder.errorDrawable;
this.imageConfig = builder.imageConfig;
this.requests = new HashMap<>(3);
}
@ -146,7 +149,7 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
public void run() {
final AsyncDrawable asyncDrawable = reference.get();
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 ExecutorService executorService;
private Drawable errorDrawable;
private ImageConfig imageConfig;
public Builder client(@NonNull OkHttpClient client) {
this.client = client;
@ -366,6 +370,11 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
return this;
}
public Builder imageConfig(ImageConfig imageConfig) {
this.imageConfig = imageConfig;
return this;
}
public AsyncDrawableLoader build() {
if (client == null) {
client = new OkHttpClient();
@ -377,6 +386,9 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
// we will use executor from okHttp
executorService = client.dispatcher().executorService();
}
if(imageConfig == null){
imageConfig = new ImageConfig();
}
return new AsyncDrawableLoader(this);
}
}

View File

@ -12,25 +12,26 @@ import android.support.annotation.Nullable;
import ru.noties.markwon.renderer.html.ImageSize;
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 interface Loader {
void load(@NonNull String destination, @NonNull AsyncDrawable drawable);
void cancel(@NonNull String destination);
}
private final String destination;
private final Loader loader;
private final ImageSize imageSize;
private final ImageSizeResolver imageSizeResolver;
private Drawable result;
private Callback callback;
private int canvasWidth;
private float textSize;
public AsyncDrawable(@NonNull String destination, @NonNull 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 (this.result != null) {
@ -101,7 +102,7 @@ public class AsyncDrawable extends Drawable {
this.result = result;
this.result.setCallback(callback);
final Rect bounds = resolveBounds();
final Rect bounds = resolveBounds(imageConfig);
result.setBounds(bounds);
setBounds(bounds);
@ -168,10 +169,11 @@ public class AsyncDrawable extends Drawable {
}
/**
* @param imageConfig
* @since 1.0.1
*/
@NonNull
private Rect resolveBounds() {
private Rect resolveBounds(@NonNull ImageConfig imageConfig) {
final Rect rect;
if (imageSizeResolver == null
|| imageSize == null) {
@ -179,6 +181,43 @@ public class AsyncDrawable extends Drawable {
} else {
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 aspectRatio = (float) bounds.width() / bounds.height();
bounds.left = 0;
bounds.right = canvasWidth;
bounds.bottom = (int) (bounds.top + bounds.height() * aspectRatio);
} 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);
}
}

View File

@ -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
}