Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fragment flips and losses Image

I've completely re-wrote the question to single down the scope.

I have Two Fragments that Flip around like a card(Left, Right). When the front fragment disappears flips it shows the back. Once the button is clicked again it flips to the front again but the ImageView on the front fragment is gone.

I have tried different methods of saving the data of the Image picked.

  1. Saving the Fragment onSaveInstanceState

This gives me a Null Pointer, so I figured I needed something more constant once being created.

  1. So now I save the image to SDCard once Picked

This I figured would work and just check the path and grab it if its flipped to the front or the activity is recreated.

Here is some Code

onCreate():

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.new_postcard_activity);
        //UI call
        frontImageView = (ImageView) findViewById(R.id.imageView);
        Log.d(tag, "onCreate() Instance:" + savedInstanceState);
        //fragment start
          if (savedInstanceState == null) {
              Log.d(tag,"Instance Null");
                getFragmentManager()
                        .beginTransaction()
                        .add(R.id.postcardFrame, new CardFrontFragment())
                        .commit();
                if(!mShowingBack){
                    Log.d(tag,"Not showing back");
                    if(newPath != null && newPath != ""){
                        Log.d(tag, "entered new path, not empty");
                        Drawable drawable = Drawable.createFromPath(newPath);
                        Log.d(tag, "Should be setting saved image.");
                        frontImageView.setImageDrawable(drawable);
                    }
                  }  
            } 
          else 
          {
                mShowingBack = (getFragmentManager().getBackStackEntryCount() > 0);
                Log.d(tag, "Instance is not Null");
          }

Flip Button Click Listener

//flip card
final Button cardBackButton = (Button) findViewById(R.id.cardBackButton);
cardBackButton.setOnClickListener(new Button.OnClickListener(){

    @Override
    public void onClick(View v) {
        flipCard();
});

flipCard Method:

private void flipCard()
    {
        Log.d(tag2, "Log after flipCard:" + mShowingBack);
        if(mShowingBack)
        {
            //Flip to front
            flipFront();
             return;
        }
        // Flip to back
        flipBack();
    }

I set the Image onActivityResult from their PhotoGallery

protected void onActivityResult(int requestCode, int resultCode,
            Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);

        if (resultCode == RESULT_OK) {
            Uri photoUri = intent.getData();

            if (photoUri != null) {
                try {
                    ImageView setImage = (ImageView)findViewById(R.id.imageView);
                    frontImage = MediaStore.Images.Media.getBitmap(this
                        .getContentResolver(), photoUri);
                    imageSet = true;
                    //save image to SD
                    if(imageSet == true){
                        Log.d(tag, "Inside Image Set if Statement");
                    String path = getExternalCacheDir() + "Postcards.png";
                    if(path != null && path != ""){
                    Log.d(tag, "Path is:" + path);
                    File file = new File(path);
                    newPath = file.getAbsolutePath();
                    Log.d(tag, "New Path:" + newPath);
                    if(file.exists()){
                        Log.d(tag, "File Exists");
                        Drawable d = Drawable.createFromPath(newPath);
                        setImage.setImageDrawable(d);

                    }else{
                        try{
                            Log.d(tag,"File didnt exist");
                            FileOutputStream out = new FileOutputStream(file);
                            frontImage.compress(Bitmap.CompressFormat.PNG, 90, out);
                            if(file.exists()){
                                Log.d(tag, "file exists now");
                            newPath = file.getAbsolutePath();
                            Drawable b = Drawable.createFromPath(newPath);
                            setImage.setImageDrawable(b);
                            }
                        }catch(Exception e){
                            e.printStackTrace();
                        }
                    }
                }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

This is how I am accessing the image and trying to set it to my ImageView on Restart()

if(imageSet == true){
            if(newPath != null && newPath != ""){
                ImageView view = (ImageView) findViewById(R.id.imageView);
                Drawable drawable = Drawable.createFromPath(newPath);
                view.setImageDrawable(drawable);
            }
        }

This seems like the best route in getting the image and setting it but it wont work. What would be best practice and how can I get it to perform the way I need it to?

Much appreciated with any help!

like image 668
Keeano Avatar asked Aug 09 '13 04:08

Keeano


People also ask

How do you know if a fragment is destroyed?

Since all fragments are destroyed if the activity is destroyed, a simple answer could be calling getActivity(). isDestroyed() returning true if the activity is destroyed, therefore the fragment is destroyed.

How to set fragment on activity?

Add a fragment to an activity You can add your fragment to the activity's view hierarchy either by defining the fragment in your activity's layout file or by defining a fragment container in your activity's layout file and then programmatically adding the fragment from within your activity.

What are fragments in Android?

A Fragment represents a reusable portion of your app's UI. A fragment defines and manages its own layout, has its own lifecycle, and can handle its own input events. Fragments cannot live on their own--they must be hosted by an activity or another fragment.


1 Answers

savedInstanceState serves a different purpose.

onSaveInstanceState (Bundle): This method is called before an activity may be killed so that when it comes back some time in the future it can restore its state

And, in your particular case, it may not even be required. On button click, you are changing fragments, not restarting your app.

From what I can see, you are letting the user create a postcard: a picture on one side (say, Side A) and a message on flip-side (say, Side B). When the app starts, Side A is in view. In some manner, you let the user select an image from the gallery. I will assume that onActivityResult(int, int, Intent) works as expected, and sets the image to ImageView - R.id.imageView. When a button is clicked, the view is changed to Side B. And when the button is clicked again, the view changes to Side A, but the image selected by user is not there.

One thing you can do inside onActivityResult(int, int, Intent) is: save the path of the image in SharedPreferences.

SharedPreferences preferences;
final String PREFS = "your.application.name.prefs";

// Keyword to find the path
final String IMAGE_SELECTED_BY_USER = "image_selected_by_user";

// Use a default image when the user starts the app for the first time
// or if the retrieved path points to a deleted image etc.
final String PATH_TO_A_DEFAULT_IMAGE = "path_to_a_default_image"    

@Override
protected void onCreate(Bundle savedInstanceState) {

    ....
    ....
    preferences = getActivity().getSharedPreferences(PREFS, 0);
    imagePath = preferences.getString(IMAGE_SELECTED_BY_USER, PATH_TO_A_DEFAULT_IMAGE);

    frontImageView = (ImageView) findViewById(R.id.imageView);

    Drawable drawable = null;

    if (new File(imagePath).exists()) {
        drawable = Drawable.createFromPath(imagePath);
    } else {
        drawable = Drawable.createFromPath(PATH_TO_A_DEFAULT_IMAGE);
    }

    frontImageView.setImageDrawable(drawable);

    getFragmentManager()
        .beginTransaction()
        .add(R.id.postcardFrame, new CardFrontFragment())
        .commit();

    ....
    ....
}

In onActivityResult(int, int, Intent), save the image path:

if(file.exists()){
    Log.d(tag, "File Exists");
    Drawable d = Drawable.createFromPath(newPath);
    setImage.setImageDrawable(d);

    Editor editor = preferences.edit();
    editor.putString(IMAGE_SELECTED_BY_USER, newPath);
    editor.commit();
} else{
    try{
        Log.d(tag,"File didnt exist");
        FileOutputStream out = new FileOutputStream(file);
        frontImage.compress(Bitmap.CompressFormat.PNG, 90, out);
        if (file.exists()) { 
            Log.d(tag, "file exists now");
            newPath = file.getAbsolutePath();
            Drawable b = Drawable.createFromPath(newPath);
            setImage.setImageDrawable(b);

            Editor editor = preferences.edit();
            editor.putString(IMAGE_SELECTED_BY_USER, newPath);
            editor.commit();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

This way, when the user starts the app, he/she will see either the default image, or an image previously selected.

Where savedInstanceState would be useful: Let's say you give the user an option of writing a short message on Side B. Now, if while writing the message, the user rotates the device from Landscape to Portrait (or vice-versa), the message he/she wrote will be gone because the activity will be destroyed and recreated. To save the message, you would use onSaveInstanceState(Bundle):

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    outState.putString("Text_To_Save", someEditText.getText().toString());
}

On rotation, activity's onCreate(Bundle)' will be called. The bundle passed is the same one fromonSaveInstanceState(Bundle)`. To retrieve the text:

String savedString = "";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (savedInstanceState != null) {
        if (savedInstanceState.contains("Text_To_Save")) {
            savedString = savedInstanceState.getString("Text_To_Save");
        }
    }

    someEditText.setText(savedString);
}  
like image 111
Vikram Avatar answered Sep 18 '22 15:09

Vikram