Ostatnie kilka godzin pisania aplikacji poświęciłem na walce z dynamicznym tworzeniem elementów GUI w kodzie. Udało mi się w końcu wstępnie uzyskać efekt, który chciałem, i który jeszcze dopracuję. Problemem okazał się mały szczegół, o którym nie widziałem…
Problem, który chcę opisać, napotkałem przy tworzeniu ekranu wyświetlającego szczegóły dokumentu. Na tym ekranie powinien być widoczny tytuł dokumentu, tagi oraz wszystkie pliki wraz z ich opisami. I przy tym ostatnim elemencie powstały problemy.
Powyżej wstawiłem efekt jaki bym chciał osiągnąć. Chodzi oczywiście o rozmieszczenie elementów – niebieskie linie oraz zielony kolor zostały dodane dla lepszej widoczności co się dzieję. Wracając do układu elementów – pliki chciałbym wyświetlić w formie tabelarycznej, gdzie w lewej kolumnie będzie miniaturka zdjęcia/pliku, a w prawej będzie dodany opis pliku.
Powyższy efekt udało się uzyskać przy pomocy następującego kodu:
<TableRow android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:layout_width="110dp" android:layout_height="110dp"> <ImageView android:layout_width="100dp" android:layout_height="100dp" android:layout_gravity="center_horizontal|center_vertical" android:src="@android:drawable/ic_dialog_map" /> </FrameLayout> <TextView android:layout_width="wrap_content" android:layout_height="110dp" android:scrollHorizontally="false" android:text="Ut ac libero tincidunt, bibendum sem nec, pellentesque sem." /> </TableRow>Czy tworzę TableRow i są w nim dwa elementy:
- FrameLayout, który w sobie zawiera ImageView z obrazem
- TextView, który zawiera opis pliku
Oczywiście kod ten w XMLu stworzyłem tylko po to, żeby zobaczyć, których elementów mam użyć, żeby uzyskać efekt jaki chcę. Sama lista plików z opisami będzie oczywiście tworzona dynamicznie w kodzie.
Jeden wiersz tworzyłem mniej więcej w poniższy sposób:
val filesLayout = findViewById(R.id.show_document_files_table).asInstanceOf[TableLayout] val dim110 = (110 * this.getResources.getDisplayMetrics.density + 0.5f).toInt val tableRow = new TableRow(this) tableRow.setLayoutParams(new TableRow.LayoutParams(MATCH_PARENT, MATCH_PARENT)) val imageFrameLayout = new FrameLayout(this) imageFrameLayout.setLayoutParams(new FrameLayout.LayoutParams(dim110, dim110)) val imageView: ImageView = new ImageView(this) imageView.setImageBitmap(...) val layoutParams = new LinearLayout.LayoutParams(thumbnail.getWidth, thumbnail.getHeight) layoutParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL imageView.setLayoutParams(layoutParams) imageFrameLayout.addView(imageView) tableRow.addView(imageFrameLayout) val fileDescription = new TextView(this) fileDescription.setLayoutParams(new LinearLayout.LayoutParams(WRAP_CONTENT, dim110, 0.1f)) fileDescription.setText(...) tableRow.addView(fileDescription) filesLayout.addView(tableRow)Tworząc elementy tabeli w kodzie starałem się tworzył dokładnie te same elementy z tymi samymi parametrami, które użyłem w XMLu. Niestety tworzenie wiersza tabeli w powyższy sposób powodował, iż na ekranie nic się nie pojawiało – tabela zostawała pusta. Metodą prób i błędów próbowałem dojść do tego co jest nie tak i w końcu mi się udało.
Okazało się, iż przy tworzeniu ustawień layouty, czyli tworząc obiekty LayoutParams musimy użyć LayoutParams z klasy rodzica danego elementu, a nie z samego elementu. Czyli w przypadku gdzie tworzyłem wiersz tabeli w poniższy sposób
val tableRow = new TableRow(this) tableRow.setLayoutParams(new TableRow.LayoutParams(MATCH_PARENT, MATCH_PARENT))wystarczyło zamienić na:
val tableRow = new TableRow(this) tableRow.setLayoutParams(new TableLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT))Czyli użyć TableLayout.LayoutParams zamiast TableRow.LayoutParams, ponieważ TableLayout jest rodzicem naszego wiersza.
Po takich zmianach w kodzie ekran wyświelił elementy w taki sposób w jaki chciałem. Kod po modyfikacjach wyglada następująco:
val filesLayout = findViewById(R.id.show_document_files_table).asInstanceOf[TableLayout] val dim110 = (110 * this.getResources.getDisplayMetrics.density + 0.5f).toInt val tableRow = new TableRow(this) tableRow.setLayoutParams(new TableLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)) val imageFrameLayout = new FrameLayout(this) imageFrameLayout.setLayoutParams(new TableRow.LayoutParams(dim110, dim110)) val imageView: ImageView = new ImageView(this) imageView.setImageBitmap(...) val layoutParams = new FrameLayout.LayoutParams(thumbnail.getWidth, thumbnail.getHeight) layoutParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL imageView.setLayoutParams(layoutParams) imageFrameLayout.addView(imageView) tableRow.addView(imageFrameLayout) val fileDescription = new TextView(this) fileDescription.setLayoutParams(new TableRow.LayoutParams(WRAP_CONTENT, dim110, 0.1f)) fileDescription.setText(...) tableRow.addView(fileDescription) filesLayout.addView(tableRow)