how can I change the text from several TextViews dynamically? [duplicate] - android

This question already has answers here:
TextViews text change in a for loop
(4 answers)
Closed 4 years ago.
I need to set the text of some textViews already existing in a layout with a for loop. Eg. TextView_01, TextView_02, etc. IS there a way to do something like the following speculative code:
for(1 in 0..6){
TextView_0(change value with i).text = something
}

This isn't the best way to do things, but it's probably the most universal, while avoiding creating a pre-defined array of TextViews:
val base = "TextView_0"
for (i in 1 until 6) {
val textView = findViewById(resources.getIdentifier("${base}i", "id", packageName)
textView.text = something
}
I changed your for loop a little bit, since you had the wrong syntax. I also replaced .. with until, since .. means through the right bound, which probably isn't what you want. If you do need 6 to be a value of i, then change it back to ...
If all the TextViews are under a single parent in XML, give that parent an ID, then loop through its children:
val parent = findViewById(R.id.tvParent)
for (i in 0 until parent.getChildCount()) {
(container.getChildAt(i) as TextView).text = something
}

You can use parent container
for (i in 0 until container.childCount) {
(container.getChildAt(i) as TextView).text = something
}

A better way is to make use of DataBinding and LiveData APIs, you can assign different variables or the same variable to your TextViews' text attributes.

Related

Kotlin : How to insert a value of a variable in a name of another variable

Sadly, I failed to find any answer to this question on SO or elsewhere.
I am studying Kotlin and Android development and I wonder how I can insert a value of a variable in a name of another variable. Or if there is another, better solution to this problem I have.
Suppose, my code looks like this:
...
private fun rollDice() {
// Create new Dice object with 6 sides and roll the dice
val dice = Dice(6)
val diceRoll = dice.roll()
// Find the ImageView in the layout
val diceImage: ImageView = findViewById(R.id.imageView)
// Determine which drawable resource ID to use based on the dice roll
val drawableResource = when (diceRoll) {
1 -> R.drawable.dice_1
2 -> R.drawable.dice_2
3 -> R.drawable.dice_3
4 -> R.drawable.dice_4
5 -> R.drawable.dice_5
else -> R.drawable.dice_6
}
// Update the ImageView with the correct drawable resource ID
diceImage.setImageResource(drawableResource)
// Update the content description
diceImage.contentDescription = diceRoll.toString()
}
...
I wonder if in the
"Determine which drawable resource ID to use based on the dice roll"
block I could actually use something like this (also, sorry, I don't know the correct syntax yet):
val drawableResource = R.drawable.{"dice_"+ diceRoll.toString()}
This way I could have saved much space and make the code easily extensible, if, for example, I had a 20-sided dice, I still would have needed this single line of code.
Or else I would have needed to add
when(diceRoll){
...
20 lines of code here
...
}
How can I solve this problem?
Thank you.
Thanks to Shlomi Katriel for linking the correct solution to this in comment on the original post.
A way to formulate my question in this context would be exactly as in linked post — "How to get a resource id with a known resource name?"
My solution code for this exact case (changed 2 blocks):
// Determine which drawable resource ID to use based on the dice roll
val drawableResourceId : Int = this.resources.getIdentifier("dice_$diceRoll", "drawable",this.packageName)
// Update the ImageView with the correct drawable resource ID
diceImage.setImageResource(drawableResourceId)

Cant check if my textview that inside of an array is visible or not in Kotlin

I have a 2D array (matrix) of Textviews called Board. Board has 16 Textviews in it, only one of them is invisible. In this given lines of code, I tried to find the invisible one between all the rest. For some reason, the line with the If condition collapses my app every time. I don't understand what my problem is, can someone help me?
P.S. Sorry for my English, it's not my native language.
Here is my code:
var i = 0
for (i in 0..4) {
var j = 0
for (j in 0..4) {
var tvtemp = board[i][j]
if (tvtemp.visibility == View.INVISIBLE) {
Toast.makeText(applicationContext,board[i][j].text, Toast.LENGTH_SHORT).show()
}
}
}
== operator is used to compare the data of two variables.
Please don’t misunderstand this equality operator with the Java == operator as both are different. == operator in Kotlin only compares the data or variables, whereas in Java or other languages == is generally used to compare the references.
Solution:
if(!tvtemp.isVisible){
....
}
You could try using the isShown method. It determines if the view is visible to the user. If a view's visibility is set to be visible, but it it crossed off the screen then isShown will equal false. If you have no scrollview and all views are fitted in the activity then this could work for you
if (!tvtemp.isShown) {
Toast.makeText(applicationContext,board[i][j].text, Toast.LENGTH_SHORT).show()
}

Android LayoutPosition is -1 causing OutOfBoundsException

I've created an app that has a list of cards within a RecyclerView that each have functionality of their own. I wanted to have each card choose the next color from an array defined in my colors.xml. In order to accomplish this, within my ViewHolder initialization, I set the background color of the card using cardContainer.setBackgroundColor(colors[this.layoutPosition % colors.size]. This would make it so that the colors would be cycled when more cards are created. However, I seem to be encountering the issue where my layout position is negative despite there being a set number of cards (25) created at the beginning.
While trying to search around and find the cause, I read here that if you call notifyDataSetChanged() the adapterPosition will become -1. While I am not using adapterPosition here, I thought that maybe it would be a similar issue, however, I am not adding any additional data at the time of the creation of the list items.
My ViewHolder code can be seen below. This is where the issue arises, but if any additional code is necessary feel free to ask.
class ViewHolder(itemView : View, private val listener: HabitClickListener) : RecyclerView.ViewHolder(itemView) {
val habitTitle: TextView = itemView.habitTitle
val streak: TextView = itemView.dayCounter
val cardContainer: LinearLayout = itemView.cardContainer
private val decreaseCounterButton : Button = itemView.decreaseCounterButton
private val increaseCounterButton : Button = itemView.increaseCounterButton
init {
chooseCardColor() // Choose the color for each card from the available colors
itemView.setOnClickListener {
listener.onCardClick(this.layoutPosition)
}
decreaseCounterButton.setOnClickListener {
listener.onDecrease(this.layoutPosition)
}
increaseCounterButton.setOnClickListener {
listener.onIncrease(this.layoutPosition)
}
}
private fun chooseCardColor() {
val colors = itemView.resources.getIntArray(R.array.cardColors)
cardContainer.setBackgroundColor(colors[this.layoutPosition % colors.size])
}
}
I will try to simplify this further, you should use the getAdapterPosition of ViewHolder
In recyclerview, storing the data and displaying the data are two separate things(Notice how you can use different managers(LinearLayoutManager, GridLayoutManager) to present the data in a different way.When some data changes in recyclerview, it notifies the ui to change what is shown in the screen. Even though it is really small, there is a delay between the change in the content of recyclerview and change in layout, that's why these two behave differently.
My information in this may be outdated but also don't just use the position variable as it can be inconsistent when another element is added/deleted to recyclerview due to how onBindViewHolder()(existing variables position wasn't updated when a new element is added/deleted) behaves. Instead use getAdapterPosition().
Edit: Quick fix if you don't want to deal with viewHolder gimmicks.
Add a new field to your custom object which decides what color it should be. Then make this calculation in your fragment/activity by looking at the index of your object in the list instead of doing the calculation in the viewHolder. Now you can set the color you want inside the viewHolderby looking at your object's new field. Of course you should be careful when adding/deleting a new object when you do this, but same holds true when you do it via viewHolder

Creating large amount of Views in Code

I'm trying to create a custom View that contains a list of CheckBoxes based on my database. This means I have to create the Views at run-time, and can't do it in XML. However, the method I'm using for this is very slow. Is there a faster method to create large amount of Views in code?
For example, with the 18 types in my database, it can take over 1 second to create all the CheckBoxes.
class FilterView : LinearLayout {
private fun init(types : List<Type>){
... setup
// Creating the CheckBoxes, this takes all the time.
checkboxes = Array(types.size, {
AppCompatCheckBox(context).apply {
text = types[it].type
CompoundButtonCompat.setButtonTintList(this, ColorStateList(states, intArrayOf(colours[it], colours[it])))
}
})
... add to view
}
What your looking for is a Recyclerview. It can all be explained here. The downvote was likely because this is assumed to be common knowledge or easily googled on your own. I was new once too. Here you go.

Android Exception: UnknownFormatConversionException

Hi I am setting some text inside a RobotoText that is positioned inside of a ViewHolder I am calling it like this:
viewHolder.txtSimilarAds.setText((((Property) ads.get(position)).getSimilar_items_count() == 1 ? context.getString(R.string.ad_data_similar) : context.getString(R.string.ad_data_similar_plural, ads.get(position).getImagesCount())));
However (sometimes NOT always)for some reason I keep getting this error exception UnknownFormatConversionException and it points to this line inside of the class. What could be the problem? Am I doing anything wrong?
Check that the string in R.string.ad_data_similar_plural contains a valid placeholder for an integer. It should be something like "Here is my number: %d".
String format specification
As an aside, one-liner like these are harder to understand, and make debugging more difficult. A more readable approach would have given the erroneous line more easily:
String similarAdsText;
Property adsProperty = ads.get(position);
if (adsProperty.getSimilar_items_count() == 1) {
similarAdsText = context.getString(R.string.ad_data_similar);
}
else {
similarAdsText = context.getString(R.string.ad_data_similar_plural, adsProperty.getImagesCount());
}
viewHolder.txtSimilarAds.setText(similarAdsText);
You are trying too many methods in single line try splitting it. The problem looks like you are comparing Property object with 1 which is wrong.
(Property)ads.get(position)).getSimilar_items_count() == 1
change this to
Property property = (Property) ads.get(position));
property.getSimilar_items_count() == 1

Categories

Resources