Вызвать 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 ).

Есть идеи?

При проверке кода кажется, что ваш RecyclerView самом деле может быть getSpanSizeFromScreenWidth , но вашей логики в 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 во время выполнения?