Вызовите getMeasuredWidth() или getWidth() для RecyclerView, возвращающего 0 при привязке данных

Я использую привязку данных для настройки RecyclerView, Вот адаптер привязки:

fun setRecyclerDevices(recyclerView: RecyclerView, items: List<Device>, itemBinder: MultipleTypeItemBinder,
                                   listener: BindableListAdapter.OnClickListener<Device>?) {

        var adapter = recyclerView.adapter as? DevicesBindableAdapter
        if (adapter == null) {
            val spannedGridLayoutManager = SpannedGridLayoutManager(orientation = SpannedGridLayoutManager.Orientation.VERTICAL,
                    spans = getSpanSizeFromScreenWidth(recyclerView.context, recyclerView))
            recyclerView.layoutManager = spannedGridLayoutManager
            recyclerView.addItemDecoration(SpaceItemDecorator(left = 15, top = 15, right = 15, bottom = 15))
            adapter = DevicesBindableAdapter(items, itemBinder)
            adapter.setOnClickListener(listener)
            recyclerView.adapter = adapter
        } else {
            adapter.setOnClickListener(listener)
            adapter.setItemBinder(itemBinder)
            adapter.setItems(items)
        }
    }

getSpanSizeFromScreenWidth нужна ширина переработчика, чтобы сделать некоторые вычисления. Но это всегда возвращается 0,

Я пытался применить ViewTreeObserver как это:

recyclerView.viewTreeObserver.addOnGlobalLayoutListener(object: ViewTreeObserver.OnGlobalLayoutListener {

                override fun onGlobalLayout() {
                    recyclerView.viewTreeObserver.removeOnGlobalLayoutListener(this)
                    val spannedGridLayoutManager = SpannedGridLayoutManager(orientation = SpannedGridLayoutManager.Orientation.VERTICAL,
                            spans = getSpanSizeFromScreenWidth(recyclerView.context, recyclerView))
                    recyclerView.layoutManager = spannedGridLayoutManager
                }
            })

Или использовать post как это:

recyclerView.post({
                val spannedGridLayoutManager = SpannedGridLayoutManager(orientation = SpannedGridLayoutManager.Orientation.VERTICAL,
                        spans = getSpanSizeFromScreenWidth(recyclerView.context, recyclerView))
                recyclerView.layoutManager = spannedGridLayoutManager
            })

Код getSpanSizeFormScreenWidth:

private fun getSpanSizeFromScreenWidth(context: Context, recyclerView: RecyclerView): Int {
        val availableWidth = recyclerView.width.toFloat()
        val px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 300f, context.resources.displayMetrics)
        val margin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 15f, context.resources.displayMetrics)
        return Math.max(1, Math.floor((availableWidth / (px + margin)).toDouble()).toInt()) * DevicesBindableAdapter.WIDTH_UNIT_VALUE
    }

Но все равно возвращается 0 несмотря на мой RecyclerView отображается на экране (не 0).

Есть идеи?

1 ответ

При проверке кода выясняется, что ваш RecyclerView может на самом деле все в порядке, но ваша логика в getSpanSizeFromScreenWidth может не быть.

Это выглядит так: Math.floor((availableWidth / (px + margin)).toDouble()).toInt() всегда будет 0, когда availableWidth меньше чем (px + margin), Это приведет к getSpanSizeFromScreenWidth возвращать 0,


Разбивая это:

  • Math.floor - округляет double до целого числа
  • availableWidth / (px + margin) - будет низким числом (доля availableWidth)

Поэтому вы собираетесь получить 0 иногда особенно на экранах меньшего размера и / или экранах меньшей плотности.

Имеет ли это смысл? Может быть, это не проблема, но я бы начал там. Трудно точно сказать вам проблему, не зная всего контекста, но это, вероятно, ваша проблема.


Если это не ваша проблема, не могли бы вы сказать, какова ваша ценность для availableWidth, px, а также margin во время исполнения?

Другие вопросы по тегам