1

How can I programmatically produce an image containing custom text (in Kotlin)?

The following picture is an example:

enter image description here

All text here should be editable programmatically - In other words, I'd like a programmatically editable template that can be saved as an image.

I'd also like to be able to set the width of the image (while maintaining quality and aspect ratio).

I explored many answers to similar questions on SO but they are outdated/deprecated or are not elegant enough, so please do not mark this question as duplicate. I'm open to using libraries from GitHub.

I tried drawing my text to a Bitmap-backed Canvas, but the text's position slightly differs depending on the device, which is not good.

iamhere
  • 1
  • 1
  • 11
  • 1
    Draw your text and images to a `Bitmap`-backed `Canvas`. – CommonsWare Feb 19 '22 at 16:18
  • @CommonsWare I tried this but the issue is that the text's position slightly differs depending on the device. – iamhere Feb 20 '22 at 02:44
  • 1
    "I tried this" -- then you should be asking a question for help on your implementation, with a [mcve] showing what you tried and showing the results that are not to your liking. – CommonsWare Feb 20 '22 at 12:18

3 Answers3

0

Just using a bitmap is 100% pixel perfect. You could include additional fonts to force it to be the same on all device types. It will be a picture independent off any platform environment.

Milo van der Zee
  • 1,031
  • 11
  • 30
0

Use the Following Method on the XML file on a TextView

use the android:drawableTop parameter

<TextView
    android:id="@+id/textView20"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:drawableTop="@android:mipmap/sym_def_app_icon"
    android:text="TextView"
    android:gravity="center"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

To Put an Image on Top

To Put an Image on Side

You can just use the .setText method to change the text automatically

Aishik kirtaniya
  • 478
  • 5
  • 19
0

There is a trick for what you wanna do, follow these steps:

  1. create an XML layout for your image that you wanna save, this will be your editable output image data, for example:

Note: View Binding is used in this method, however, you can use other methods to access XML layout views

layout_data.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto">

  <FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="@dimen/custom_padding">

      <ImageView
        android:id="@+id/ivBackground"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

      <TextView
        android:id="@+id/tvCenterText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center" />

  </FrameLayout>

</layout>
  1. Access, Edit and save the screenshot of your layout in your fragment:
    private fun fillDataAndGetBitmap(image: Bitmap, title: String): Bitmap {
        val layoutInflater: LayoutInflater = LayoutInflater.from(requireContext())
        val layoutDataBinding = LayoutDatatBinding.inflate(layoutInflater, null, false)
        
        // Fill in your image data into layout
        layoutDataBinding.ivBackground.setImageBitmap(image)
        layoutDataBinding.tvCenterText.text = title

        // Get Bitmap of your layout
        val outputBitmap = gettBitmapFromView(layoutDataBinding.root)
        return outputBitmap
    }

    fun gettBitmapFromView(layout: View): Bitmap {
        layout.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED))
        layout.layout(0, 0, layout.measuredWidth, layout.measuredHeight)
        val bitmap = Bitmap.createBitmap(layout.measuredWidth, layout.measuredHeight, Bitmap.Config.ARGB_8888)

        val canvas = Canvas(bitmap)
        layout.layout(layout.left, layout.top, layout.right, layout.bottom)
        layout.draw(canvas)
        return bitmap
    }
  1. Now you have a bitmap of your layout, you can share it via intent or save it to the user's device. Also, you can change the quality and aspect ratio of your bitmap, but that is out of the scope of this question, you can check Scaled Bitmap maintaining aspect ratio.
Milad Mohammadi
  • 40
  • 1
  • 2
  • 6