I am using a custom TextView that draws the text vertical, a graph from MPAndroidCharts library and a textview on top of the graph. While it looks great on the screen, when I try to get a Bitmap of it so it can be shared as an image, the vertical text views get are not drawn completely.
My XML of the View is the following:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:id="@+id/clWeatherCharts">
<TextView
android:id="@+id/txtWeatherTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_margin="@dimen/margin_16dp"
android:text="@string/temperature_registers"
android:textAlignment="center"/>
<com.shadows.naylapp.utils.VerticalTextView
android:id="@+id/llYEnvironment"
android:textColor="@color/colorBlack"
android:textSize="14sp"
android:layout_width="20dp"
android:layout_height="0dp"
android:text="Temperatura Superficial del Mar (Cº)"
android:layout_margin="@dimen/padding_8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/lineWeatherChart"
app:layout_constraintBottom_toBottomOf="@id/lineWeatherChart"
/>
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/lineWeatherChart"
android:layout_marginTop="@dimen/margin_16dp"
android:layout_width="0dp"
android:layout_height="300dp"
app:layout_constraintEnd_toStartOf="@id/llYWindEnvironment"
app:layout_constraintStart_toEndOf="@id/llYEnvironment"
app:layout_constraintTop_toBottomOf="@id/txtWeatherTitle" />
<LinearLayout
android:id="@+id/llYWindEnvironment"
android:layout_width="20dp"
android:layout_height="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/lineWeatherChart"
app:layout_constraintBottom_toBottomOf="@id/lineWeatherChart">
<com.shadows.naylapp.utils.VerticalTextView
android:textColor="@color/colorBlack"
android:textSize="14sp"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="Velocidad del Viento (Km/hr)"
/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
I am using an extension function to create the bitmap which is the following:
fun View.getBitmapFromView(): Bitmap? {
val bitmap = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
canvas.drawColor(Color.WHITE)
this.draw(canvas)
return bitmap
}
and I call it like this: clWeatherCharts.getBitmapFromView()
the following is an image of the screen on the app
And the following is the bitmap which gets the vertical textviews cropped:
The code for the vertical text view is the following:
class VerticalTextView(context: Context, attrs: AttributeSet) : AppCompatTextView(context, attrs) {
private val topDown = gravity.let { g ->
!(Gravity.isVertical(g) && g.and(Gravity.VERTICAL_GRAVITY_MASK) == Gravity.TOP)
}
private val metrics = BoringLayout.Metrics()
private var padLeft = 0
private var padTop = 0
private var layout1: Layout? = null
override fun setText(text: CharSequence, type: BufferType) {
super.setText(text, type)
layout1 = null
}
private fun makeLayout(): Layout {
if (layout1 == null) {
metrics.width = height
paint.color = currentTextColor
paint.drawableState = drawableState
layout1 = BoringLayout.make(text, paint, metrics.width, Layout.Alignment.ALIGN_NORMAL, 2f, 0f, metrics, false, TextUtils.TruncateAt.MIDDLE, height - compoundPaddingLeft - compoundPaddingRight)
padLeft = compoundPaddingLeft
padTop = extendedPaddingTop
}
return layout1!!
}
override fun onDraw(c: Canvas) {
// c.drawColor(0xffffff80); // TEST
if (layout == null)
return
c.withSave {
if (topDown) {
val fm = paint.fontMetrics
translate(textSize - (fm.bottom + fm.descent), 0f)
rotate(90f)
} else {
translate(textSize, height.toFloat())
rotate(-90f)
}
translate(padLeft.toFloat(), padTop.toFloat())
makeLayout().draw(this)
}
}
}
I have already tried putting some padding on the textviews, or centering the text and it gets even more cropped when getting the bitmap.
Any help is appreciated!
Solution
You can go through each child in a ConstraintLayout, then draw the child's content by using Bitmap.drawBitmap(Bitmap, int, int, Paint).
// Get bitmap from a View
fun View.getBitmapFromView(): Bitmap? {
val bitmap = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
draw(canvas)
return bitmap
}
// Get bitmap from a ConstraintLayout
fun ConstraintLayout.getBitmapFromView(): Bitmap {
val bitmap = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
canvas.drawColor(Color.WHITE)
for (i in 0 until childCount) {
val child = getChildAt(i)
val childBitmap = child.getBitmapFromView()
if (childBitmap != null) {
canvas.drawBitmap(childBitmap, child.left.toFloat(), child.top.toFloat(), null)
}
}
return bitmap
}
Using from the code
clWeatherCharts.getBitmapFromView()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With