So I was doing an implementation in an app, and I wanted to show in the PlateScanner, the plates that the user has scanned.
Now it works, but the design is a bit, "off" hahaha I´m not a very good designer so I was asking if i can in this platform, for some recomendations, not only here, but in general about the apps, and how you would do it!
Right now is a table inside a scrollview inside a AlertDialog
private fun showFleetInfoPopup() {
val builder = AlertDialog.Builder(requireContext())
builder.setTitle("Matriculas leídas")
viewLifecycleOwner.lifecycleScope.launch(dispatcherIO) {
val matriculasList = db.MatriculaDao().getAllDistinct()
withContext(dispatcherMain) {
val scrollView = ScrollView(requireContext()).apply {
val padding = resources.getDimensionPixelSize(R.dimen.common_margin_min)
setPadding(padding, padding, padding, padding)
}
val tableLayout = TableLayout(requireContext()).apply {
val padding = resources.getDimensionPixelSize(R.dimen.common_margin_min)
setPadding(padding, padding, padding, padding)
}
matriculasList.forEach { matriculaEntity ->
val tableRow = TableRow(requireContext()).apply {
val margin = 8
layoutParams = TableLayout.LayoutParams(
TableLayout.LayoutParams.WRAP_CONTENT,
TableLayout.LayoutParams.WRAP_CONTENT
).apply {
setMargins(margin, margin, margin, margin)
}
}
val textView = TextView(requireContext()).apply {
text = matriculaEntity.matricula
textSize = resources.getDimension(R.dimen.text_tiny_body)
}
tableRow.addView(textView)
tableLayout.addView(tableRow)
}
scrollView.addView(tableLayout)
builder.setView(scrollView)
builder.setPositiveButton("OK") { dialog, _ -> dialog.dismiss() }
builder.show()
}
}
}
Thanks in advance for any help!
I think you're making things too complex by creating a dynamic table. The AlertDialog
supports adding a list, which can simplify your implementation significantly. You can provide the list of matricula as a parameter to the showFleetInfoPopup
function and handle the complexity outside the function, even in onCreate
. Here's a simplified version of your code:
private fun showFleetInfoPopup(matriculasList: Array<String>, context: Context) {
val builder: AlertDialog.Builder = AlertDialog.Builder(context)
builder
.setTitle("Matriculas leídas")
.setPositiveButton("OK") { dialog, _ -> dialog.dismiss() }
.setItems(matriculasList) { _, _ -> }
val dialog: AlertDialog = builder.create()
dialog.show()
}
In the example below, I will display the dialog when the user clicks on the "show" button:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button = findViewById<Button>(R.id.button)
button.setOnClickListener {
val data = queryDb()
showFleetInfoPopup(data, this)
}
}
private fun queryDb(): Array<String> {
// Query the database here
// For this example, I will just hard-code the list
return arrayOf("1234 ABCD", "5678 EFGH", "9101 IJKL")
}
To improve this solution further, consider using a ViewModel
to handle the database query. This separates the data handling from the UI logic, making your code more modular and easier to maintain. Here's how you can do it:
class MatriculaViewModel : ViewModel() {
//...
private val matriculaDao = db.MatriculaDao()
fun fetchMatriculas() : List<String> {
return matriculaDao.getAllDistinct()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button = findViewById<Button>(R.id.button)
button.setOnClickListener {
// use this dependency to be able to do that
// implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.8.4"
val matriculaViewModel by viewModels<MatriculaViewModel>()
val data = matriculaViewModel.fetchMatriculas()
showFleetInfoPopup(data.toTypedArray(), this)
}
}
If you want to do thing asynchronously, you can do something like this:
class MatriculaViewModel : ViewModel() {
private val matriculaDao = db.MatriculaDao()
private val _matriculasList = MutableLiveData<List<String>>()
val matriculasList: LiveData<List<String>> get() = _matriculasList
fun fetchMatriculas() {
viewModelScope.launch {
_matriculasList.postValue(matriculaDao.getAllDistinct())
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val button = findViewById<Button>(R.id.button)
button.setOnClickListener {
val matriculaViewModel by viewModels<MatriculaViewModel>()
matriculaViewModel.matriculasList.observe(this) { data ->
showFleetInfoPopup(data.toTypedArray(), this)
}
}
}
Demo: