12

I have a logo view, which is a full screen fragment containing single ImageView. I have to perform some operations after the logo image is completely visible.

Following code is used to invoke the special task

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        ImageView logoImageMaster = new ImageView(getContext());
        //logoImageMaster.setImageResource(resID); //even after removing this, i am getting the callback twice
        try {
            // get input stream
            InputStream ims = getActivity().getAssets().open("product_logo.png");
            // load image as Drawable
            Drawable d = Drawable.createFromStream(ims, null);
            // set image to ImageView
            logoImageMaster.setImageDrawable(d);
        }
        catch(IOException ex) {

        }
        logoImageMaster.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {  //FIXME get called twice. Check this out, no info to distinguish first from second
//                Log.e("PANEL", "onGlobalLayout of Logo IV ---------------------------------");
                    activityInterface.doSpecialLogic();
            }
        });
        return logoImageMaster;
    }

My exact problem is, onGlobalLayout is called twice for this view hierarchy.

I know that onGlobalLayout is invoked in performTraversal of View.java hence this is expected.

For my use case of Single parent with Single child view, I want to distinguish the view attributes such that doSpecialLogic is called once[onGlobalLayout is called twice] , after the logo image is completely made visible. Please suggest some ideas.

nmxprime
  • 1,506
  • 3
  • 25
  • 52

3 Answers3

5

OnGlobalLayoutListener gets called every time the view layout or visibility changes. Maybe you reset the views in your doSpecialLogic call??
edit as @Guille89 pointed out, the two set calls cause onGlobalLayout to be called two times

Anyhow, if you want to call OnGlobalLayoutListener just once and don't need it for anything else, how about removing it after doSpecialLogic() call??

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
             //noinspection deprecation
              logoImageMaster.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    } else {
             logoImageMaster.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    }
activityInterface.doSpecialLogic();
Sarosh Khatana
  • 501
  • 6
  • 16
  • Hi, I still get twice, now i set only one time, pls see the updates to the question – nmxprime Sep 10 '16 at 13:36
  • No, I am not reseting the view in `doSpecialLogic` – nmxprime Sep 10 '16 at 13:37
  • well as per the docs onGlobalLayout = "Callback method to be invoked when the global layout state or the visibility of views within the view tree changes" so the views must be reloading again which calls the onGlobalLayout twice. – Sarosh Khatana Sep 10 '16 at 16:00
  • 1
    Just realised, you don't want to stop two calls to the onGlobalLayout but rather to have doSpecialLoagic() called once. How about setting a boolean flag before doSpecialLogic?? i.e. something like if(!flag) {doSpecialLogic; flag=true;} – Sarosh Khatana Sep 10 '16 at 16:11
  • I understand, my setting up a flag, then i need to book keep on that . – nmxprime Sep 12 '16 at 07:43
  • I know that would be simpler, but if i can still differentiate various `onGlobalLayout` calls based on any view state, it would be most useful then i dont need the book-keeping of the flag – nmxprime Sep 12 '16 at 07:45
1

It seems to be called one time for each set done over the imageView

logoImageMaster.setImageResource(resID);

logoImageMaster.setImageDrawable(d);
Guille89
  • 81
  • 8
1

You should Try using kotlin plugin in android

This layout listener is usually used to do something after a view is measured, so you typically would need to wait until width and height are greater than 0. And we probably want to do something with the view that called it,in your case Imageview

So generified the function so that it can be used by any object that extends View and also be able to access to all its specific functions and properties from the function

[kotlin]
    inline fun <T: View> T.afterMeasured(crossinline f: T.() -> Unit) {
    viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
    override fun onGlobalLayout() {
    if (measuredWidth > 0 && measuredHeight > 0) {
    viewTreeObserver.removeOnGlobalLayoutListener(this)
    f()
    }
    }
    })
    }
[/kotlin]

Note: make sure that ImageView is described properly in the layout. That is its layout_width and layout_height must not be wrap_content. Moreover, other views must not result in this ImageView has 0 size.

PN10
  • 1,888
  • 3
  • 23
  • 34