0

I am making a meme creator app. I will load memes from firebase database and the user will select one of the meme templates and will start editting it. For entering text in the memes i am using the github library implementation 'com.github.hantrungkien:Awesome-Input-Layout:1.0.0' It allows the user to rotate the textview, move it with finger and all. But the problem is i am very new to android dev. I dont know how to save the background meme image plus the text entered by user in the user's device or gallery. Please tell me detailed steps as i am pretty new. Every help is appreciated.

My Meme editting activity code

package com.example.memecreator

import android.app.Activity
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.Button
import android.widget.RelativeLayout
import com.squareup.picasso.Picasso
import htkien.awesome_input.AwesomeInputLayout
import kotlinx.android.synthetic.main.activity_meme.*


class MemeActivity : AppCompatActivity() {

    val TAG = MainActivity::class.java.simpleName

    var mLayoutRoot: RelativeLayout? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_meme)
        setSupportActionBar(meme_toolbar)
        supportActionBar!!.setDisplayHomeAsUpEnabled(true)
        meme_toolbar.setNavigationOnClickListener {
            finish()
        }

//I am passing intent from last activity and using picasso to load images. Its working fine.


        val intent=intent
        val memeImage=intent.getStringExtra("image")
        Picasso.get().load(memeImage).into(meme_image)
        mLayoutRoot=findViewById<RelativeLayout>(R.id.rl_meme)
        val added=findViewById<Button>(R.id.btn_add_text)
        added.setOnClickListener {
            onClickBtnAddText()
        }
    }



    override fun onBackPressed() {
        if (!mLayoutRoot!!.isFocused) {
            mLayoutRoot!!.requestFocus()
            mLayoutRoot!!.requestFocusFromTouch()
        } else {
            super.onBackPressed()
        }
    }

    private fun onClickBtnAddText() {
        val awesomeLayout = LayoutInflater.from(this).inflate(
            R.layout.layout_awesome_input,
            mLayoutRoot,
            false
        ) as AwesomeInputLayout
        mLayoutRoot?.addView(awesomeLayout)
        awesomeLayout.post {
            val w = mLayoutRoot!!.width
            val h = mLayoutRoot!!.height
            awesomeLayout.x = w / 2 - awesomeLayout.width / 2.toFloat()
            awesomeLayout.y = h / 2 - awesomeLayout.height / 2.toFloat()
            awesomeLayout.requestLayout()
            awesomeLayout.visibility = View.VISIBLE
            showKeyboard(this@MemeActivity)
        }
        awesomeLayout.setDeleteViewListener { awesomeLayout ->
            hideKeyboard(awesomeLayout)
            mLayoutRoot!!.requestFocus()
            mLayoutRoot!!.requestFocusFromTouch()
            try {
                mLayoutRoot!!.removeView(awesomeLayout)
            } catch (e: IndexOutOfBoundsException) {
                Log.e(TAG, "onDeleteView: ", e)
            }
        }
    }

    private fun hideKeyboard(view: View) {
        val imm =
            view.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.toggleSoftInput(
            InputMethodManager.HIDE_IMPLICIT_ONLY,
            0
        ) // hide
    }

    private fun showKeyboard(activity: Activity) {
        val imm = activity.getSystemService(
            Activity.INPUT_METHOD_SERVICE
        ) as InputMethodManager
        imm.toggleSoftInput(
            0,
            InputMethodManager.HIDE_IMPLICIT_ONLY
        ) // show
    }
}

My Meme editting xml code

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rl_meme"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MemeActivity">
    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/app_bar_layout_meme"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_marginStart="0dp"
        android:layout_marginTop="0dp"
        android:background="@android:color/white">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/meme_toolbar"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:background="@color/colorDarkGrey">

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <TextView
                    android:id="@+id/app_name"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Meme"
                    android:textSize="20sp"
                    android:maxLines="1"
                    android:textStyle="bold"
                    android:textColor="@android:color/white"
                    android:layout_centerVertical="true"/>


            </RelativeLayout>

        </androidx.appcompat.widget.Toolbar>
    </com.google.android.material.appbar.AppBarLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/meme_image"
            android:layout_width="match_parent"
            android:layout_height="420dp"
            android:layout_marginTop="152dp"
            android:scaleType="fitXY"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/btn_add_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_above="@id/meme_image"
            android:text="Add Text"
            android:layout_marginStart="40dp"
            android:layout_marginEnd="40dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/meme_image" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</RelativeLayout>

and finally the design of the edittext which i used from the github library

<?xml version="1.0" encoding="utf-8"?>
<htkien.awesome_input.AwesomeInputLayout
    xmlns:autofit="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="100dp"
    android:layout_height="50dp"
    android:layout_marginTop="152dp"
    android:background="@drawable/button_black_background"
    android:orientation="vertical"
    android:visibility="invisible">

    <ImageButton
        android:id="@+id/button_delete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:background="@android:color/transparent"
        android:scaleType="fitXY"
        android:src="@drawable/ic_cross" />

    <EditText
        android:id="@+id/edit_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_margin="10dp"
        android:hint="Type"
        android:imeOptions="flagNoExtractUi"
        android:textColor="@color/colorDark"
        android:textColorHint="@color/colorDark"
        android:textSize="16sp" />

</htkien.awesome_input.AwesomeInputLayout>

This is a screenshot image of my edit meme activity screen. I want to save this in the device

  • Does this answer your question? [Convert view to bitmap on Android](https://stackoverflow.com/questions/5536066/convert-view-to-bitmap-on-android) – AgentP May 27 '20 at 07:20
  • Check out this [link](https://dev.to/pranavpandey/android-create-bitmap-from-a-view-3lck) – Hussain May 27 '20 at 07:22
  • I didn't understand most of it. Can you explain in context of my code. what changes i have to make or what stuffs i must write to achieve that in my case plus in kotlin @PraveenSP – Vipul Sharma May 27 '20 at 07:22
  • @Hussain i dont understand java – Vipul Sharma May 27 '20 at 07:24
  • Well sorry Vipul I haven't started with kotlin yet... I have heard the ide is capable of converting kotlin to java and vise versa give it a shot.. – AgentP May 27 '20 at 07:26
  • If you using android ktx library, you can simply call `drawToBitmap()` on the layout which you have attached above then save the bitmap as image file. – Hussain May 27 '20 at 07:32
  • i used the first answer in this link https://stackoverflow.com/questions/36624756/how-to-save-bitmap-to-android-gallery , but as i passed the imageview in it and converted it to bitmap by drawToBitmap(), it only saved my previous imageView without any new edit texts over it. How can i save both imageView and edittext together . @Hussain – Vipul Sharma May 27 '20 at 08:06

1 Answers1

0

Let's modify the ConstraintLayout inside activity_meme layout a little bit,

...
...

<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@+id/meme_container"
        android:layout_width="match_parent"
        android:layout_height="420dp"
        android:layout_marginTop="152dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/meme_image"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="fitXY" />

    </FrameLayout>

    <Button
        android:id="@+id/btn_add_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/meme_container"
        android:layout_marginStart="40dp"
        android:layout_marginEnd="40dp"
        android:text="Add Text"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/meme_container" />

</androidx.constraintlayout.widget.ConstraintLayout>

...
...

Inside onCreate, replace

 mLayoutRoot = findViewById<RelativeLayout>(R.id.rl_meme)

with

mLayoutRoot = findViewById<FrameLayout>(R.id.meme_container)

This layout will now contain the meme image with text. Hence we call drawToBitmap on mLayoutRoot and save the image.

Hussain
  • 1,243
  • 12
  • 21
  • Just tried it. but it didnt work. still not saving the text – Vipul Sharma May 27 '20 at 10:07
  • Are you adding `AwesomeInputLayout` to `meme_container` FrameLayout? – Hussain May 27 '20 at 10:14
  • maybe its because the edittext layout is in a different xml file. thats why its not able to save it as bitmap image. got any idea how to change the framework so that it starts reading it. the only thing to remember is i want to get a new edittext when a user taps the 'add text' button – Vipul Sharma May 27 '20 at 10:15
  • no. AwesomeInputLayout is being inflated by code in MemeActivity.kt . as you asked, i only put the imageview in framelayout. you can see in the question. i put it there. – Vipul Sharma May 27 '20 at 10:35