Передать значения ширины и высоты объекта перед показом Activity в переменные

На экране у меня FrameLayout и LinerLayout. Во FrameLayout я хочу разместить в определенном месте какой-либо объект. Например, картинку. Ее расположение зависит от размера контейнера. Для размещения картинки мне необходимо вычислить ширину и высоту FrameLayout. Если я пытаюсь узнать ширину и высоту FrameLayout в методе onCreate(), то получаю значения 0. Ведь у нас экран еще не нарисовался.

Если я пытаюсь узнать ширину и высоту FrameLayout используя метод onResume(), то тоже получаю 0. Здесь я не совсем понял, почему возвращаются 0.

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

Я создал глобальные переменные, и в них передаю значения ширины и высоты, но как только метод заканчивает работу, значения опять обнуляются. Мой код

// Объявил ДО класса MainActivity
    
            var elementHeight = 0
            var elementWidth = 0

// Эти методы уже в классе MainActivity
    
            override fun onResume() {
                super.onResume()
                countWidthHeight()
            }
        
            fun countWidthHeight() {
                val flayerLayout = binding.container
                flayerLayout.getViewTreeObserver()
                    .addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
                        override fun onGlobalLayout() {
                            flayerLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this)
        // Здесь ширина и высота вычисляются правильно
                            elementHeight = flayerLayout.height //height is ready
                            elementWidth = flayerLayout.width
                        }
                    })
            }
        
            fun viewHeightWidth() {
        // а здесь oneHeight и oneWidth уже равны 0 хотя им передаются значения глобальных переменных
                val oneHeight = elementHeight
                val oneWidth = elementWidth
            }

Подскажите, что я делаю неправильно. Kotlin и Android начал изучать не так давно.


Ответы (2 шт):

Автор решения: Danila Kartovitskii

Запустив Вашу программу, убедился в своих мыслях. Как я выяснил в комментариях, viewHeightWidth() запускается из метода onResume().

override fun onResume() {
    super.onResume()
    countWidthHeight()
    viewHeightWidth()
}
  1. Мы вызвали функцию countWidthHeight(), добавили ViewTreeObserver.OnGlobalLayoutListener (Ещё раз повторю, мы ТОЛЬКО добавили его, т.е. в данный момент сам листенер ещё не вызывался)
  2. Дальше по порядку идет вызов функции viewHeightWidth(), которая использует глобальные переменные, которые не успели поменяться, т.е равны 0.

2 Способа решить вашу проблему

Первый способ:

Сделать вызов viewHeightWidth(), внутри ViewTreeObserver.OnGlobalLayoutListener.

 fun countWidthHeight() {
                val flayerLayout = binding.container
                flayerLayout.getViewTreeObserver()
                    .addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
                        override fun onGlobalLayout() {
                            flayerLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this)
                            elementHeight = flayerLayout.height 
                            elementWidth = flayerLayout.width
                            viewHeightWidth()
                        }
                    })
            }

Второй способ: Избавьтесь от OnGlobalLayoutListener и используйте View.post (документация)

override fun onResume() {
    super.onResume()
    binding.container.post {
        viewHeightWidth()
    }
}

fun viewHeightWidth() {
    val oneHeight = binding.container.height
    val oneWidth = binding.container.width
}
→ Ссылка
Автор решения: Style-7

Для подобных задач хорошо подходит слушатель View.OnLayoutChangeListener : просто добавьте его к ViewGroupв методе onCreate активности.

    ViewGroup veiw_group = findViewById( R.id.root );
    veiw_group.addOnLayoutChangeListener( new View.OnLayoutChangeListener(){
        @Override
        public void onLayoutChange( View view, int left, int top, int right, int bottom, int i4, int i5, int i6, int i7 ){
        }
    } );
→ Ссылка