2

I start the intent to pick an image from gallery, then scale the image and dinamically add ImageView to the layout.

I want this image to be reloaded on orientation change. I set setRetainInstance(true) in onCreate. However, after orientation change, when I try to get appropriate width for bitmap to be scaled to by calling getWidth() on FrameLayout which is supposed to be its container, I get 0.

public class NewWallpaper extends Fragment {
    private static final int PICK_BACKGROUND = 1;

    private BitmapFactory.Options bitmapFactoryOptions;

    // Data
    private Uri backgroundURI = null;
    private WeakReference<Bitmap> backgroundBitmap = null;

    // Views
    FrameLayout backgroundContainer;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.layout_new_wallpaper, container, false);

        // BitmapFactory options
        bitmapFactoryOptions = new BitmapFactory.Options();
        bitmapFactoryOptions.inPurgeable = true;

        Button pickBackground = (Button) view.findViewById(R.id.buttonPickBackground);
        pickBackground.setOnClickListener(pickBackgroundListener);

        backgroundContainer = (FrameLayout) view.findViewById(R.id.frameLayoutbackgroundContainer);

        if (backgroundURI != null)
            setBackgroundPreview();

        return view;
    }

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

        setRetainInstance(true);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
    }


    private Button.OnClickListener pickBackgroundListener = new Button.OnClickListener() {

        @Override
        public void onClick(View view) {
            Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("image/*");

            startActivityForResult(intent, PICK_BACKGROUND);
        }
    };

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode == PICK_BACKGROUND && resultCode == getActivity().RESULT_OK && data != null && data.getData() != null) {
            backgroundURI = data.getData();
            setBackgroundPreview();
        }

        super.onActivityResult(requestCode, resultCode, data);
    }

    private void setBackgroundPreview() {
        try {
            backgroundContainer.removeAllViews();

            Bitmap background = BitmapHelper.loadScaledBitmap(getActivity(), backgroundURI, backgroundContainer.getWidth());

            backgroundBitmap = new WeakReference<Bitmap>(background);

            // returns 0
            int containerWidth = backgroundContainer.getWidth();

            ImageView backgroundView = new ImageView(getActivity());
            backgroundView.setLayoutParams(new LinearLayout.LayoutParams(
                    backgroundContainer.getWidth(),
                    BitmapHelper.calculateHeight(
                            background.getWidth(),
                            background.getHeight(),
                            backgroundContainer.getWidth())
            ));
            backgroundView.setAdjustViewBounds(true);
            backgroundView.setScaleType(ImageView.ScaleType.FIT_XY);
            backgroundView.setImageBitmap(background);

            backgroundContainer.addView(backgroundView);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

I can't seem to find a way to repopulate views after orientation change. Could someone tell me what I'm doing wrong?

Martin
  • 1,877
  • 5
  • 21
  • 37

3 Answers3

1

Don't call setBackgroundPreview() from onCreateView. You can't measure the view if it hasn't finished being created.

Call setBackgroundPreview() in onActivityCreated instead.

Sound Conception
  • 5,263
  • 5
  • 30
  • 47
1

If you want pixel width you should call view.getMeasuredWidth() instead. getWidth() and getHeight() will give you

LayoutParams.WRAP_CONTENT | LayoutParams.MATCH_PARENT  //constants (1 or 0).

Still, to make sure you are getting the right value, call that method after @onDraw() callback of your view ( so override it) , or get viewTreeObserver and wait for onGlobalLayout() callback to call the methods.

<<<<< EDIT: >>>>>

Found one example with ViewTreeObserver:

ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
  viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
      view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
      viewWidth = mediaGallery.getMeasuredWidth();
      viewHeight = mediaGallery.getMeasuredHeight();
    }
  });
}

Removing the listener after the first callback makes sure to free up lot of process since we only need the measured params once.

SuppressWarnings
  • 4,134
  • 4
  • 25
  • 33
  • 1
    I can't believe I have to do this. I just want my ImageView to display the same image after orientation change. – Martin Dec 01 '13 at 18:37
  • Well, when you change orientation @onCreate() gets called again, aswell as the other activity regular callbacks and lifecycle. If you need to recalculate a view's size every orientation change, just make sure to recalculate viewWidth and viewHeight at the @onCreate() callback by setting the ViewTreeObserver callback.It will only be executed once (when the layout is final, so all views are created), so it does not load the device heavily at all. I think it is a good solution and will give you pixel width and height every time. Please if it helped I welcome rate/ correct answer. – SuppressWarnings Dec 02 '13 at 11:19
  • If you have any more questions i'll be checking back, good luck! – SuppressWarnings Dec 02 '13 at 11:22
0

The width and height are not defined until the view is actually rendered to the screen. Collected from getWidth and getHeight are returning a zero. Also you check this post How do you to retrieve dimensions of a view? Getheight() and Getwidth() always return zero

Community
  • 1
  • 1
androidcodehunter
  • 21,567
  • 19
  • 47
  • 70