Страницы

Поиск по вопросам

вторник, 27 ноября 2018 г.

Создать идентичные 9х9 элементов TextView в виде таблички - с равными размерами

У меня есть компоновка LinearLayout вертикальной ориентации, в которой находятся 9 компоновок LinearLayout горизонтальной ориентации, в каждой из которых по 9 TextView (итого 9 * 9 = 81 элемент TextView). Для грамотной реализации этого творчества я создаю по 9 горизонтальных компоновок LinearLayout и по 9 TextView в каждой из них в Java-коде, а затем, соответственно, добавляю их в основную компоновку компонента Activity примерно так:
for (int y = 8; y >= 0; y--) { LinearLayout mLinearLayout_row = ...//компоновка горизонтальной ориентации for (x = 0; x < 9; x++) { TextView mTextView = layoutInflater.inflate(R.layout.mtextview, ... mLinearLayout_row.addView(mMTextView); } myMainActivityLayout.addView(mLinearLayout_row, 0); }
Все компоновки имеют длину MATCH_PARENT, а высоту WRAP_CONTENT. Вот код mtextview.xml

На экране ширИны всех элементов TextView выглядят равными (если не вглядываться). Но на самом деле система Android задаёт ширину нескольким последним элементам с правой стороны во всех рядах чуть меньшую ширину - это система вычисляет алгоритмом за счёт известного значения атрибута layout_weight у всех TextView
Теперь перейду к проблеме. У меня не получается сделать элементы TextView квадратными, таблица выглядит приплюснутой.

Я пробовал следующие способы:
Использовать кастомный TextView, в классе которого переопределив метод onMeasure
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, widthMeasureSpec); }
Метод очень плох, так как элементы то делаются квадратными, но слева они большие, а справа маленькие - это очень некрасиво выглядит.
Использовать кастомную основную компоновку LinearLayout, в классе которой переопределив метод onMeasure (так же, как в п.1) и установив значение атрибута layout_height у TextView на match_parent - вообще никаких изменений. В коде компонента Activity, в которой всё это происходит, переопределить метод onResume, в котором пытаться получить ширину всех TextView и задать им высоту, равную известной ширине... в общем-то способ не профессиональный и не оптимальный, по моему мнению, но, несмотря на это, я попробовал использовать этот способ, а оказалось, что, когда вызывается метод onResume система ещё не знает ширину элементов!!! (значение функции mTextView.getWidth(), полученное в этом методе равно 0).

Сожалею, что нереально тяжело въехать, в чём же у меня заключается проблема, но я постарался максимально подробно и корректно описать её :).


Ответ

Для того, чтобы сделать ячейки масшатбируемыми и квадратными, можно использовать свойство соотношения сторон app:layout_constraintDimensionRatio в ConstraintLayout


Это позволит вам сделать ячейки квадратными, вне зависимости от расширения экрана, т.к. они просто ужмутся по высоте и ширине
Но я предлагаю пойти вам дальше и переверстать экран с помощью recyclerView (как предложил Виталий в комментариях). Во-первых, это избавит вас от проблемы адресации к этим ячейкам, ведь их нужно будет заполнять и считывать. А во-вторых, реализация с RecycelerView будет эстетичнее (в разметке RecyclerView + адаптер + ViewHolder - вы сами убедитесь в простоте такой реализации). Установив размер 1 в item RecyclerView, вы автоматически его установите всем ячейкам.
Адаптер для RecyclerView стандартный, но нужно переопределить LayouManager. Создаете LayoutManager, наследуете его от GridLayoutManager (можно внутри адаптера):
private static class NonScrollableGridLayoutManager extends GridLayoutManager {
NonScrollableGridLayoutManager(Context context, int span) { super(context, span); }
@Override public boolean canScrollVertically() { return false; }
@Override public boolean canScrollHorizontally() { return false; } }
В адаптере создаете метод, возвращающий объект LayoutManager
public static RecyclerView.LayoutManager getLayoutManager(Context context) { return new NonScrollableGridLayoutManager(context, COUNT_OF_ITEM_IN_LINE); }
Затем устанавливаете для RecyclerView ваш LayoutManager
binding.monthContent.setLayoutManager(CalendarAdapter.getLayoutManager( binding.getRoot().getContext())); binding.monthContent.setAdapter(daysAdapter); binding.monthContent.setItemAnimator(null);
Не правда ли удобно?

Комментариев нет:

Отправить комментарий