0

I'm making a notepad type of app in which the user can take and place pictures in between the text as he is typing it.

In my app I have a button , editText and imageView. When it starts, there is only the button and an editText. The user types into the editText and when he presses the button, the camera opens. The taken picture gets placed right under the editText (under the last line entered by the user). Under the picture a new editText appears and the user can enter text into this. When he presses the button again another picture gets taken, placed below the second editText and a third editText is available to the user to enter text.

So each time the user takes a picture by pressing the button, a new editText appears under the image. This keeps looping, allowing the user to enter both text and images, as many images and paragraphs as he wants.

But this isn't happening. I'm only able to enter text once and take 1 picture. No second editText ever appears. What's going wrong here.

The code for alternating editText and imageView is located in onActivityResult()

mainActivity.java

package com.example.nirvan.cameraexample3;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.media.Image;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MainActivity extends AppCompatActivity
{


ImageView myImage;
EditText textVar;
int flag=0;             //flag==0 means place img below text, ==1 means below textVar

private String pictureImagePath = "";
Uri outputFileUri;
@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button imgButton=(Button) findViewById(R.id.imgButton);


    View.OnClickListener imgButtonClickListener=new View.OnClickListener()
    {
        @Override
        public void onClick(View view)
        {
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
            String imageFileName = timeStamp + ".jpg";
            File storageDir = Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_PICTURES);
            pictureImagePath = storageDir.getAbsolutePath() + "/" + imageFileName;
            File file = new File(pictureImagePath);
            outputFileUri = Uri.fromFile(file);
            Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
            startActivityForResult(cameraIntent, 1);
        }
    };
    imgButton.setOnClickListener(imgButtonClickListener);


}



protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    Log.d("TAG","CUSTOOOM");
    RelativeLayout relativeLayout=(RelativeLayout) findViewById(R.id.relativeLayout);
    myImage=new ImageView(this);
    myImage.setId(+1);




    if (requestCode == 1 && resultCode == RESULT_OK)
    {
        File imgFile = new File(pictureImagePath);
       if (imgFile.exists())
        {
            Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
           // myImage = (ImageView) findViewById(R.id.imageViewTest);

            //this code ensures the imageView is placed below the editText
            RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams
                    (RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);

            if(flag==0)
               {
                   relativeParams.addRule(RelativeLayout.BELOW, R.id.text);
                   flag=1;
               }
            else if(flag==1)
                relativeParams.addRule(RelativeLayout.BELOW, textVar.getId());

            //myImage.setLayoutParams(relativeParams);
            relativeLayout.addView(myImage,relativeParams);
            //
            myImage.setImageBitmap(myBitmap);


            //place the new editText below the imgaeView just placed
            relativeParams = new RelativeLayout.LayoutParams
                    (RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
            relativeParams.addRule(RelativeLayout.BELOW, myImage.getId());
            textVar=new EditText(this);
            textVar.setId(+2    );
            relativeLayout.addView(textVar,relativeParams);
            textVar.setText("NEW");

        }
    }//






}



}

mainActivity.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:id="@+id/relativeLayout"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.nirvan.cameraexample3.MainActivity">





<Button
    style="?android:attr/buttonStyleSmall"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="IMG"
    android:id="@+id/imgButton"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true" />

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/text"
    android:layout_below="@id/imgButton"
    />

</RelativeLayout>

UPDATE- Taking Petrumo's suggestions I have revised the code. Although it's still not working the way it should. After taking the first image, a second editText is not being displayed under the image. I have made sure that the ids for the textView and imageView are different for each iteration of the method.

onActivityResult() updated

protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    Log.d("TAG","CUSTOOOM");
    RelativeLayout relativeLayout=(RelativeLayout) findViewById(R.id.relativeLayout);
    myImage=new ImageView(this);
    myImage.setId(id1++);
    textVar.setId(id2++);




    if (requestCode == 1 && resultCode == RESULT_OK)
    {
        File imgFile = new File(pictureImagePath);
       if (imgFile.exists())
        {
            Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
           // myImage = (ImageView) findViewById(R.id.imageViewTest);

            //this code ensures the imageView is placed below the editText
            RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams
                    (RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);

            if(flag==0)
               {
                   relativeParams.addRule(RelativeLayout.BELOW, R.id.text);
                   flag=1;
               }
            else if(flag==1)
                relativeParams.addRule(RelativeLayout.BELOW, textVar.getId());




            //myImage.setLayoutParams(relativeParams);
            relativeLayout.addView(myImage,relativeParams);
            //
            myImage.setImageBitmap(myBitmap);


            //place the new editText below the imgaeView just placed
            relativeParams = new RelativeLayout.LayoutParams
                    (RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
            relativeParams.addRule(RelativeLayout.BELOW, myImage.getId());
            textVar=new EditText(this);
            //textVar.setId(id2++);

            relativeLayout.addView(textVar,relativeParams);
            textVar.setText("NEW");

        }
    }//






}

UPDATE2: So I simply replaced my code inside onActivityResult with Petrumo's ..and it works. The editTexts appear one below the other. But when I insert the imageView code , the app crashes right after taking the picture.

protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    RelativeLayout relativeLayout=(RelativeLayout) findViewById(R.id.relativeLayout);
    RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams
            (RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
    if(textVar != null)
    {
        relativeParams.addRule(RelativeLayout.BELOW, textVar.getId());
    }
    else
    {
        relativeParams.addRule(RelativeLayout.BELOW, R.id.text);
    }

    myImage=new ImageView(this);
    myImage.setId(id1++);
    //set image

        File imgFile = new File(pictureImagePath);
        if (imgFile.exists() && requestCode == 1 && resultCode == RESULT_OK)
        {
            Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
            relativeLayout.addView(myImage, relativeParams);
            myImage.setImageBitmap(myBitmap);


        }

    //



    textVar=new EditText(MainActivity.this);
    textVar.setId(id2++);
    relativeParams.addRule(RelativeLayout.BELOW, myImage.getId());
    relativeLayout.addView(textVar, relativeParams);
    textVar.setText("NEW");
    relativeLayout.addView(textVar, relativeParams);




}

Log

 FATAL EXCEPTION: main
                                                                               Process: com.example.nirvan.cameraexample3, PID: 27598
                                                                               java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=null} to activity {com.example.nirvan.cameraexample3/com.example.nirvan.cameraexample3.MainActivity}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
                                                                                   at android.app.ActivityThread.deliverResults(ActivityThread.java:3432)
                                                                                   at android.app.ActivityThread.handleSendResult(ActivityThread.java:3475)
                                                                                   at android.app.ActivityThread.access$1300(ActivityThread.java:139)
                                                                                   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1258)
                                                                                   at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                   at android.os.Looper.loop(Looper.java:136)
                                                                                   at android.app.ActivityThread.main(ActivityThread.java:5086)
                                                                                   at java.lang.reflect.Method.invokeNative(Native Method)
                                                                                   at java.lang.reflect.Method.invoke(Method.java:515)
                                                                                   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
                                                                                   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
                                                                                   at dalvik.system.NativeStart.main(Native Method)
                                                                                Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
                                                                                   at android.view.ViewGroup.addViewInner(ViewGroup.java:3564)
                                                                                   at android.view.ViewGroup.addView(ViewGroup.java:3417)
                                                                                   at android.view.ViewGroup.addView(ViewGroup.java:3393)
                                                                                   at com.example.nirvan.cameraexample3.MainActivity.onActivityResult(MainActivity.java:105)
                                                                                   at android.app.Activity.dispatchActivityResult(Activity.java:5446)
                                                                                   at android.app.ActivityThread.deliverResults(ActivityThread.java:3428)
                                                                                   at android.app.ActivityThread.handleSendResult(ActivityThread.java:3475) 
                                                                                   at android.app.ActivityThread.access$1300(ActivityThread.java:139) 
                                                                                   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1258) 
                                                                                   at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                                   at android.os.Looper.loop(Looper.java:136) 
                                                                                   at android.app.ActivityThread.main(ActivityThread.java:5086) 
                                                                                   at java.lang.reflect.Method.invokeNative(Native Method) 
                                                                                       at java.lang.reflect.Method.invoke(Method.java:515)
Nirvan
  • 81
  • 1
  • 10
  • 1
    What about creating a list with an adapter and adding a new empty row every time the user adds a new photo? You will have to save the new row only if there is datas in it and you're done :) – Pier Giorgio Misley Jan 03 '17 at 14:49
  • @PierGiorgioMisley At this stage I'm not concerned with saving the data, only with displaying it. Since there's no way of knowing beforehand how many images the user will take and hence how many imageViews are required, I'm adding the imageViews dynamically. – Nirvan Jan 03 '17 at 15:49
  • you don't need to save datas to use my solution, you will simply have a list where everything is stored and then you will add an empty entry on save to show the empty line :) – Pier Giorgio Misley Jan 03 '17 at 15:52

1 Answers1

0

There are several problems with the code used:

  • using of the same id textVar.setId(+2 );

this should be something

textVar.setId(id++);

where id is a global variable

  • the same needs to be applied to the image id, it needs to be unique and used by the next one if you want to place it bellow

I simplified your solution and made it working, you can use it as a base and add your image in between:

RelativeLayout relativeLayout=(RelativeLayout) findViewById(R.id.relativeLayout);
RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams
 (RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
  if(textVar != null)
  {
    relativeParams.addRule(RelativeLayout.BELOW, textVar.getId());
  } else {
    relativeParams.addRule(RelativeLayout.BELOW, R.id.text);
  }

  textVar=new EditText(MainActivity.this);
  textVar.setId(id++);
  textVar.setText("NEW");


 relativeLayout.addView(textVar, relativeParams);

A simpler way, if you only want to add them below is to use LinearLayout with orientation vertical, or a more elegant solution to change it to a list with adapter as suggested in the comment.

petrumo
  • 1,116
  • 9
  • 18
  • I have implemented your suggestions, but the code still doesn't seem to be working like it should. I have updated my question to include the revised code as per your answer. Please have a look. – Nirvan Jan 03 '17 at 17:22
  • try to use the textVar.setId(id2++); where you commented it out instead, also if you noticed, I used (RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT); otherwise the MATCH_PARENT for the height it will use the entire screen. If you still can't make it work, try to start from my example and add it there, or switch to LinearLayout – petrumo Jan 03 '17 at 17:39
  • Okay I copied your code and added the imageView code to it. Although now it crashes as soon as I take a picture. I've checked it multiple times and I can't figure out where the problem is. Please help. – Nirvan Jan 04 '17 at 06:48
  • I have added it now. – Nirvan Jan 04 '17 at 09:29
  • maybe because you are adding the same item twice? relativeLayout.addView(textVar, relativeParams); textVar.setText("NEW"); relativeLayout.addView(textVar, relativeParams); – petrumo Jan 04 '17 at 09:36