noties / Markwon

Android markdown library (no WebView)
https://noties.io/Markwon/
Apache License 2.0
2.79k stars 314 forks source link

Can't display image in TextView and MarkwonView #43

Closed thawatchai closed 6 years ago

thawatchai commented 6 years ago

I couldn't find a way to display an image in TextView using Markwon. The README says "Images (requires special handling)" but I couldn't find the doc on that.

Currently, in place of an image, it only shows the alternate text of the image.

Please help. Thank you very much.

noties commented 6 years ago

Hey @thawatchai !

Yeah, image loading is implementaed in a different artifact (it's far from perfect, but it does support GIF & SVG):

compile 'ru.noties:markwon-image-loader:1.0.5'

Sample application uses it, so you can use it for a reference. The key is the provide AsyncDrawableLoader during SpannableConfiguration creation:

final SpannableConfiguration configuration = SpannableConfiguration.builder(context)
        .asyncDrawableLoader(loader)
        .build();

Which can be created like this:

AsyncDrawableLoader.builder()
    .client(OkHttpClient)
    .executorService(ExecutorService)
    .resources(Resources)
    .build();
thawatchai commented 6 years ago

Hi @noties. It works now. This is what I use in my Kotlin code

            val loader =
                AsyncDrawableLoader.builder().client(OkHttpClient())
                    .executorService(Executors.newCachedThreadPool())
                    .resources(Resources.getSystem()).build()
            val configuration = SpannableConfiguration.builder(act)
                .asyncDrawableLoader(loader)
                .build()

            Markwon.setMarkdown(contentTextView, configuration, markdown)

Do I use the correct executor and resource?

BTW, is there a way that I can make the image resize to the full width of the TextView?

noties commented 6 years ago

Hey @thawatchai !

Yeah, they should be fine although I would recommend using your application's resources (it is used to determine the density when displaying Bitmaps).

To control the size of an image there 2 ways:

public class ImageSizeResolverFitWidth extends ImageSizeResolverDef {

    @NonNull
    @Override
    public Rect resolveImageSize(
            @Nullable ImageSize imageSize,
            @NonNull Rect imageBounds,
            int canvasWidth,
            float textSize
    ) {
        return imageSize == null
                ? fitWidth(imageBounds, canvasWidth)
                : super.resolveImageSize(imageSize, imageBounds, canvasWidth, textSize);
    }

    @NonNull
    private Rect fitWidth(@NonNull Rect imageBounds, int canvasWidth) {
        final float ratio = (float) imageBounds.width() / imageBounds.height();
        final int height = (int) (canvasWidth / ratio + .5F);
        return new Rect(0, 0, canvasWidth, height);
    }
}

Hope this helps! 🙌

thawatchai commented 6 years ago

Hi @noties,

I try as follows:

    fun buildSpannableConfiguration(): SpannableConfiguration {
        val loader = AsyncDrawableLoader.builder().client(OkHttpClient())
            .executorService(Executors.newCachedThreadPool()).resources(application.resources)
            .build()
        return SpannableConfiguration.builder(act).asyncDrawableLoader(loader)
            .imageSizeResolver(ImageSizeResolverFitWidth()).build()
    }

    inner class ImageSizeResolverFitWidth : ImageSizeResolverDef() {
        override fun resolveImageSize(
            imageSize: ImageSize?,
            imageBounds: Rect,
            canvasWidth: Int,
            textSize: Float
        ): Rect {
            Log.wtf("g2k", canvasWidth.toString())
            val ratio = imageBounds.width() / imageBounds.height()
            val height = (canvasWidth / ratio + .5f).toInt()
            return Rect(0, 0, canvasWidth, height)
        }
    }

However, checking from logcat, the custom resolveImageSize() doesn't seem to be called. What would I should do to fix this?

noties commented 6 years ago

Hey @thawatchai !

Yeah, looks like the solution that I have mentioned works only for HTML images. I will update library to work with markdown images also

thawatchai commented 6 years ago

@noties, thanks you very much 👍

noties commented 6 years ago

@thawatchai I did update the snapshot artifact, can you please check if it's working as expected for you? It can be found here: https://github.com/noties/Markwon/tree/v1.0.6#snapshot

thawatchai commented 6 years ago

@noties, it seems that the following imports can't be resolved.

import ru.noties.markwon.renderer.html.ImageSize
import ru.noties.markwon.renderer.html.ImageSizeResolverDef

even in build.gradle, I added the following implementation

implementation 'ru.noties:markwon:1.0.6-SNAPSHOT'
implementation 'ru.noties:markwon-image-loader:1.0.6-SNAPSHOT'
implementation 'ru.noties:markwon-view:1.0.6-SNAPSHOT'
noties commented 6 years ago

@thawatchai I did move them one level up, so they can found at:

import ru.noties.markwon.renderer.ImageSize
import ru.noties.markwon.renderer.ImageSizeResolverDef
thawatchai commented 6 years ago

@noties It works perfectly now. Thank you very much for this wonderful library. 👍