#android #kotlin #button
#Android #kotlin #кнопка
Вопрос:
Я прошу помощи, чтобы понять, каков наилучший способ решить мою проблему: у меня есть динамическая сетка (сеточное описание) интерактивных элементов (созданных программно), скажем, кнопок, где каждый элемент должен хранить дополнительную информацию, предоставляемую сеточным описанием. Пока это просто класс, который расширяет кнопку (или любое другое интерактивное представление). Я хотел бы представить все свойства для каждой отдельной кнопки в отдельном XML-файле, содержащем, например, цвет текста, размер текста, фон и любое другое свойство, связанное с дизайном, которое мне может понадобиться, избегая жесткого кода всего при выделении кнопки, но я не знаю, как «дать»этот макет для только что созданного объекта. Другое требование заключается в том, что каждая кнопка должна быть квадратной, то есть одна из кнопок width или height должна содержать wrap_content , а другая должна иметь тот же размер, что и предыдущая.
Я пробовал несколько способов, создавая новый XML-файл с ConstraintLayout, который содержит кнопку, а затем создавая новый класс, подкласс ConstraintLayout но тогда у меня есть другой (бесполезный) уровень в иерархии представлений.
Каков наилучший способ добиться этого?
Заранее спасибо.
Ответ №1:
Так что, если я правильно понимаю, это будет ответ. Избавьтесь от GridLayout, поскольку он устарел. Вместо этого используйте RecyclerView следующим образом:
<androidx.recyclerview.widget.RecyclerView
android:id="@ id/rvMainMenu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent" />
Для кнопок, как вы их называете, создайте новую модель в папке layout следующим образом (я знаю, что это не совсем кнопка, но вы можете изменить этот код):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:background="#00000000"
android:padding="20dp">
<androidx.cardview.widget.CardView
android:id="@ id/item_cardview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="20dp"
app:cardCornerRadius="20dp"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/main_menu_item_background_color"
android:gravity="center">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@ id/iv_menu_item_image"
android:paddingTop="5dp"
android:layout_width="70dp"
android:layout_height="70dp"
android:src="@drawable/ic_baseline_image_24"/>
<TextView
android:id="@ id/tv_menu_item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAlignment="center"
tools:text="sample api to use"
android:textSize="24dp"
android:textColor="@color/main_menu_text_color"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
И модельный класс:
data class MenuItem (
val id: Int,
val icon: Int,
val title: String,
val tag: String
)
Затем вам нужно будет создать адаптер для обработки данных, вводимых в модель:
откройте класс MenuItemAdapter (private val context: Контекст, private var list: ArrayList): RecyclerView.Адаптер<RecyclerView.ViewHolder>()
{ private var OnClickListener: OnClickListener? = нуль
fun setOnClickListener(onClickListener: OnClickListener)
{
this.onClickListener = onClickListener
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return MyViewHolder(
LayoutInflater.from(context).inflate(R.layout.menu_item, parent, false)
)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val menuItemModel = list[position]
if (holder is MyViewHolder)
{
holder.itemView.iv_menu_item_image.setImageResource(menuItemModel.icon)
holder.itemView.tv_menu_item_title.text = menuItemModel.title
holder.itemView.setOnClickListener {
if (onClickListener != null)
{
onClickListener!!.onClick(position, menuItemModel)
}
}
}
}
override fun getItemCount(): Int {
return list.size
}
interface OnClickListener
{
fun onClick(position: Int, model: MenuItem)
}
private class MyViewHolder(view: View) : RecyclerView.ViewHolder(view)
}
Наконец, сообщите RecyclerView, что отображать. Если вам нужен макет сетки, используйте его следующим образом:
private fun setUpRecyclerView(menuItemsList: ArrayList<MenuItem>) {
rvMainMenu.layoutManager = GridLayoutManager(this, 1) //number represents the number of items in a row
val menuAdapter = MenuItemAdapter(this, menuItemsList)
rvMainMenu.adapter = menuAdapter
menuAdapter.setOnClickListener(object : MenuItemAdapter.OnClickListener
{
override fun onClick(position: Int, model: MenuItem) {
when(model.id)
{
idOfModel -> doSomething()
}
})
}
}
Так вы отображаете динамические данные, собранные из файла, базы данных, api, чего угодно, в адаптивном представлении (бонус — вы также можете использовать RecyclerView как ListView, изменив пару строк кода)