OnGlobalLayout различать различные вызовы

У меня есть вид логотипа, который является полноэкранным фрагментом, содержащим одиночный ImageView. Я должен выполнить некоторые операции после того, как изображение логотипа будет полностью видимым.

Следующий код используется для вызова специальной задачи

@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;
    }

Моя конкретная проблема: onGlobalLayout вызывается дважды для этой иерархии представлений.

Я знаю, что onGlobalLayout вызывается в performTraversal of View.java, поэтому это ожидается.

В случае использования одного родительского элемента с одиночным дочерним представлением я хочу различать атрибуты вида, чтобы doSpecialLogic вызывается один раз [onGlobalLayout вызывается дважды], после того, как изображение логотипа полностью становится видимым. Пожалуйста, предложите несколько идей.

Ответ 1

OnGlobalLayoutListener вызывается каждый раз при изменении макета представления или видимости. Может быть, вы reset мнения в вашем вызове doSpecialLogic?
изменить как указывал @Guille89, два заданных вызова вызывают onGlobalLayout, которые вызывают два раза

Во всяком случае, если вы хотите вызвать OnGlobalLayoutListener только один раз и не нуждаетесь в нем ни для чего другого, как насчет его удаления после вызова doSpecialLogic()

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
             //noinspection deprecation
              logoImageMaster.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    } else {
             logoImageMaster.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    }
activityInterface.doSpecialLogic();

Ответ 2

Кажется, он называется одним раз для каждого набора, выполненного над imageView

logoImageMaster.setImageResource(resID);

logoImageMaster.setImageDrawable(d);

Ответ 3

Вам следует попробовать использовать плагин kotlin в android

Этот приемник макета обычно используется для выполнения чего-то после измерения вида, поэтому вам обычно нужно подождать, пока ширина и высота не превысят 0. И мы, вероятно, хотим что-то сделать с видом, который вызвал его, в вашем дело ImageView

Таким образом, эта функция была сгенерирована таким образом, чтобы ее можно было использовать любым объектом, который расширяет представление, а также может иметь доступ ко всем своим конкретным функциям и свойствам из функции

[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]

Примечание: убедитесь, что ImageView правильно описан в макете. Это его layout_width и layout_height не должны быть wrap_content. Более того, другие представления не должны приводить к тому, что этот ImageView имеет размер 0.