Search code examples
androidandroid-fragmentsimageswitcher

ImageSwitcher in fragment throws illegalstateexception but works in an activity


My code works when in an Activity. However, I decided to change it into a fragment, and it now throws an illegalstateexception from the viewswitcher. Can't figure out what is wrong. In summary, I have some images I use as placeholders. When the upload image button is clicked, it fetches the uri from the returned path and uses that to replace the placeholder image in the imageSwitcher.

Here's the code:

private Button buttonUpload;
private ImageSwitcher imageSwitcher;
private ImageButton imageButton0;
private ImageButton imageButton1;
private ImageButton imageButton2;
private ImageButton imageButton3;
private ImageButton imageButton4;
private ArrayList<String> photoArray;
int counter = 0;
private static int LOAD_IMAGE_RESULTS=1;
private static int PLACEHOLDER_IMAGE = R.drawable.placeholder_2;
int[] imgs = {R.drawable.pic1, R.drawable.pic2, R.drawable.pic3,R.drawable.pic4,R.drawable.pic5};


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
    // TODO Auto-generated method stub

    View rootView = inflater.inflate(R.layout.new_item_fragment_1, container,false);
    return rootView;
}


public void onStart() {
    // TODO Auto-generated method stub
    super.onStart();

    //initialize variables and set default photos
    initVariables();
}




private void initVariables(){   
    //photo array
    photoArray = new ArrayList<String>();

    buttonUpload = (Button) getActivity().findViewById(R.id.button_upload_ni);
    buttonUpload.setOnClickListener(this);

    //image Buttons
    imageButton0 = (ImageButton) getActivity().findViewById(R.id.imageButton0);
    imageButton0.setImageResource(imgs[0]);
    imageButton0.setOnClickListener(this);
    imageButton1 = (ImageButton) getActivity().findViewById(R.id.imageButton1);
    imageButton1.setImageResource(imgs[1]);
    imageButton1.setOnClickListener(this);
    imageButton2 = (ImageButton) getActivity().findViewById(R.id.imageButton2);
    imageButton2.setOnClickListener(this);
    imageButton3 = (ImageButton) getActivity().findViewById(R.id.imageButton3);
    imageButton3.setOnClickListener(this);
    imageButton4 = (ImageButton) getActivity().findViewById(R.id.imageButton4);
    imageButton4.setOnClickListener(this);

    imageSwitcher = (ImageSwitcher) getActivity().findViewById(R.id.image_main_previewer);
    imageSwitcher.setFactory(this);

    //Add animation to the preview
    imageSwitcher.setInAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.abc_fade_in));
    imageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(getActivity(), R.anim.abc_fade_out));

    //set a default placeholder
    imageSwitcher.setImageResource(PLACEHOLDER_IMAGE);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
     super.onActivityResult(requestCode, resultCode, data);
     System.out.println("Got to beginning of onAct");

    // Here we need to check if the activity that was triggers was the Image Gallery.
    // If it is the requestCode will match the LOAD_IMAGE_RESULTS value.
    // If the resultCode is RESULT_OK and there is some data we know that an image was picked.
    if (requestCode == LOAD_IMAGE_RESULTS && resultCode == Activity.RESULT_OK && data != null) {
        // Let's read picked image data - its URI
        Uri pickedImageUri = data.getData();
        // Let's read picked image path using content resolver
    //    String[] filePath = { MediaStore.Images.Media.DATA };
    //    Cursor cursor = getContentResolver().query(pickedImage, filePath, null, null, null);
   //     cursor.moveToFirst();
   //     String imagePath = cursor.getString(cursor.getColumnIndex(filePath[0]));

        // Now we need to set the GUI ImageView data with data read from the picked file.
     //   uploadView.setImageBitmap(BitmapFactory.decodeFile(imagePath));
        //setNewImage(pickedImageUri);

        String finalPath = getFinalFilePath(pickedImageUri);
        setNewImage(pickedImageUri, finalPath);

        // At the end remember to close the cursor or you will end with the RuntimeException!
 //       cursor.close();

        System.out.println("Got to end of onAct");

    }
}



private void setNewImage(Uri uri, String filePath){
    System.out.println("Got to beginning of setNewImage");

    imageSwitcher.setImageURI(uri);

    //also set the image for the thumb nail
    //int buttonId = getThumbButton();
//  ImageButton changeButton = (ImageButton) getActivity().findViewById(buttonId);
//  changeButton.setImageBitmap(decodeSampledBitmapFromFile(filePath,40,40));

    //finally save the Bitmap
    addPathToArray(filePath);
    System.out.println("Got to end of setNewImage");
}




private void addPathToArray(String filePath){
    //Bitmap tempItemImage = BitmapFactory.decodeFile(filePath);
    System.out.println("Entered addBit");
    photoArray.add(filePath);
    System.out.println("Exit addBit "+photoArray.size());
}




private int getThumbButton(){
    //get the size of the array
    int arraySize = photoArray.size();
    int buttonId = 0;
    System.out.println("Entered getThumb");
    //switch through to find button to change
    switch(arraySize){
    case 0:
        buttonId = R.id.imageButton0;
        break;
    case 1:
        buttonId = R.id.imageButton1;
        break;
    case 2:
        buttonId = R.id.imageButton2;
        break;
    case 3:
        buttonId = R.id.imageButton3;
        break;
    case 4:
        buttonId = R.id.imageButton4;
        break;
    default:;

    }

    return buttonId;
}




private String getFinalFilePath(Uri uri){
    String[] filePath = { MediaStore.Images.Media.DATA };
    Cursor cursor = getActivity().getContentResolver().query(uri, filePath, null, null, null);
    cursor.moveToFirst();
    String imagePath = cursor.getString(cursor.getColumnIndex(filePath[0]));
    cursor.close();

    //Now we need to set the GUI ImageView data with data read from the picked file.
      return imagePath;  
}




@Override
public void onClick(View view) {

    int viewId = view.getId();

    switch(viewId){
    case R.id.button_upload_ni:
        getImageFromGallery();
        break;
    case R.id.imageButton0:
        setImageAtPosition(0);
        break;
    case R.id.imageButton1:
        setImageAtPosition(1);
        break;
    case R.id.imageButton2:
        setImageAtPosition(2);
        break;
    case R.id.imageButton3:
        setImageAtPosition(3);
        break;
    case R.id.imageButton4:
        setImageAtPosition(4);
        break;
    default: //nothing here
        ;
    }

}




private void setImageAtPosition(int position){
//  imageSwitcher.setImageResource(imgs[position]);
//  imageSwitcher.setImageDrawable(Drawable.createFromPath(photoArray.get(position)));
}




private void getImageFromGallery(){
   // Create the Intent for Image Gallery.
   Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

   // Start new activity with the LOAD_IMAGE_RESULTS to handle back the results when image is picked from the Image Gallery.
   startActivityForResult(i, LOAD_IMAGE_RESULTS);   
}





@Override
public View makeView() {
    // create view
    System.out.println("Make view called");
    counter++;
    System.out.println("setNewImage counter= "+counter);
    ImageView view = new ImageView(getActivity());
    view.setScaleType(ImageView.ScaleType.FIT_CENTER);
    view.setLayoutParams(new ImageSwitcher.LayoutParams (android.view.ViewGroup.LayoutParams.MATCH_PARENT,android.view.ViewGroup.LayoutParams.MATCH_PARENT));
    view.setBackgroundColor(0xFF000000);
    System.out.println("Make view ending");
    return view;
}




public static Bitmap decodeSampledBitmapFromFile(String filePath, int reqWidth, int reqHeight){

    //first check dimensions with inJustDecodeBounds=true 
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(filePath,options);

    //calculate inSampledSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    //Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeFile(filePath, options);
}




public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight){
    //raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if(height>reqHeight || width > reqWidth){
        final int halfHeight = height/2;
        final int halfWidth = width/2;

        //calculate the highest insamplesize value...
        while((halfHeight/inSampleSize)>reqHeight && (halfWidth/inSampleSize)>reqWidth){
            inSampleSize *=2;
        }
    }
    return inSampleSize;
}

Solution

  • Finally figured it out. The fragment's OnStart() method is always called when the Activity gets focus again. Therefore, all the views get initialized again. The second time, the onActivityResult adds a third view instead of replacing one of the others and the illegalstateexception is thrown. To fix it, I simply initialized my views in the onActivityCreated() method instead of onStart();