Issue
I want to set the UI elements from the code for an English learning App. There are more than 100 topics for each section of the app so I just created three pages of fragment changing UI elements according to the string I receive from getStringExtra. as follows:
when (activity?.intent?.getStringExtra("clickedGrammarTopic")) {
"To Be - am/is/are" -> {
binding.firstPageToolbarText.text = getText(R.string.tobe_amisare_fp_toolbar_text)
binding.firstPageTextOne.text = getText(R.string.tobe_amisare_fp_1)
binding.firstPageTablePronoun.text = getText(R.string.tobe_amisare_table_pronoun)
binding.firstPageTableAuxillaryVerb.text = getText(R.string.tobe_amisare_table_auxillary_verb)
binding.firstPageTableVerb.text = getText(R.string.tobe_amisare_table_pronoun)
binding.firstPageTablePronounI.text = getText(R.string.tobe_amisare_table_pronoun_I)
binding.firstPageTableAuxAm.text = getText(R.string.tobe_amisare_table_aux_am)
binding.firstPageTableVerbOne.text = getText(R.string.tobe_amisare_table_verb_one)
binding.firstPageTableTranslation.text = getText(R.string.tobe_amisare_table_translation)
binding.firstPageTablePronounYou.text = getText(R.string.tobe_amisare_table_pronoun_you)
binding.firstPageTableAuxAre.text = getText(R.string.tobe_amisare_table_aux_are)
binding.firstPageTableVerbTwo.text = getText(R.string.tobe_amisare_table_verb_two)
binding.firstPageTableTranslationTwo.text = getText(R.string.tobe_amisare_table_translation)
binding.firstPageTablePronounHe.text = getText(R.string.tobe_amisare_table_pronoun_he)
binding.firstPageTableAuxIs.text = getText(R.string.tobe_amisare_table_aux_is)
....
}
The problem here is whenever I try to add a new topic, I need to write over 50 lines of code. Is there an easier way to deal with this? If not, would this method have any negative effect on the overall performance of the app? (tried designing each page on .xml files ended up in a mess)
Solution
You can create a helper function that does the original getText
calls, but with resource name as a parameter, instead of the resource id.
fun Context.text(name: String): CharSequence {
val resId = resources.getIdentifier(name, "string", this.packageName)
return resources.getText(resId)
}
EDIT: Since this means that we are accessing resources without using ids, you might have to turn off resource shrinking (shrinkResources false
), so they are not removed from release builds or use this trick instead https://stackoverflow.com/a/44129736
android {
...
buildTypes {
release {
minifyEnabled true
shrinkResources false // <--
// ...
}
}
}
Then the main function is the one that has the mapping. But now you only need to have this once. It can use a resourcePrefix
parameter that will be used to discriminate resource strings for each topic.
fun setTextsForTopic(resourcePrefix: String) {
requireContext().run {
binding.firstPageToolbarText.text = text("${resourcePrefix}_fp_toolbar_text")
binding.firstPageTextOne.text = text("${resourcePrefix}_fp_1")
binding.firstPageTablePronoun.text = text("${resourcePrefix}_table_pronoun")
binding.firstPageTableAuxillaryVerb.text = text("${resourcePrefix}_table_auxillary_verb")
binding.firstPageTableVerb.text = text("${resourcePrefix}_table_pronoun")
binding.firstPageTablePronounI.text = text("${resourcePrefix}_table_pronoun_I")
binding.firstPageTableAuxAm.text = text("${resourcePrefix}_table_aux_am")
binding.firstPageTableVerbOne.text = text("${resourcePrefix}_table_verb_one")
binding.firstPageTableTranslation.text = text("${resourcePrefix}_table_translation")
binding.firstPageTablePronounYou.text = text("${resourcePrefix}_table_pronoun_you")
binding.firstPageTableAuxAre.text = text("${resourcePrefix}_table_aux_are")
binding.firstPageTableVerbTwo.text = text("${resourcePrefix}_table_verb_two")
binding.firstPageTableTranslationTwo.text = text("${resourcePrefix}_table_translation")
binding.firstPageTablePronounHe.text = text("${resourcePrefix}_table_pronoun_he")
binding.firstPageTableAuxIs.text = text("${resourcePrefix}_table_aux_is")
// ...
// fill these in for the second page
binding.secondPageToolbarText.text = text("${resourcePrefix}_???")
binding.secondPageTextOne.text = text("${resourcePrefix}_???")
// ...
// fill these in for the third page
binding.thirdPageToolbarText.text = text("${resourcePrefix}_???")
binding.thirdPageTextOne.text = text("${resourcePrefix}_???")
// ...
}
}
Then the usage becomes just a single line for every topic. So adding a new topic is now a single line of code (after updating your strings.xml
file).
when (activity?.intent?.getStringExtra("clickedGrammarTopic")) {
"To Be - am/is/are" -> setTextsForTopic("tobe_amisare")
// adding a new topic is now a single line (after updating your strings.xml file)
"Past tense" -> setTextsForTopic("past_tense")
}
You have to be consistent with the naming of string ids, of course. But even if that is not the case now, you can just do a single refactoring of string ids to get that sorted once and for all.
Answered By - Ma3x
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.