Sir Von Berker
Sir Von Berker

Reputation: 390

TextView text changes but does not update in layout (Kotlin - Android)

TextView text changes but does not update in layout. I tried every method I could find but nothing worked. I have a very basic application with a single activity and 3 layouts*. *This is the first app I make so I tought it would have been simpler this way The main problems I am facing are two: almost all the informations around are old and in java, and my textView text does not change.. The app is a simple Rock-Paper-Scissor game I'm trying to make as an exercise.

The textViews.text values get updated but the layout always shows the same text... I have no idea what could be the problem. I am also struggling to understand exactly how all of this is working exactly...like InflateLayout, Context and Android in general. I do not understand much from android's reference.

THERE IS NO INFLATE(), POSTINFLATE(), FORCELAYOUT(), VISIBILITY TOGGLES BECAUSE NONE OF THEM WORKED :(

Excerpt of the code

class MainActivity : AppCompatActivity() {

lateinit var TITLE:TextView
lateinit var PARAGRAPH:TextView

override fun onCreate(savedInstanceState :Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val InflaterInitializer = LayoutInflater.from(applicationContext) as LayoutInflater
    val inflater = InflaterInitializer.inflate(R.layout.activity_2, null, false)

    TITLE= inflater.findViewById(R.id.title) as TextView
    PARAGRAPH= inflater.findViewById(R.id.paragraph) as TextView

}

There are three functions like this:

fun FUNCTION(v :View) {
    val userChoice = "XXX"
    val computerChoice = getComputerChoice()
    if (userChoice == computerChoice) {
        FUNCTION_2(computerChoice)
    } else {
        runOnUiThread {
            TITLE.text =
                if (computerChoice == "YYY") getString(R.string.YOU_WON) else getString(R.string.YOU_LOSE);
            PARAGRAPH.text = getString(R.string.STRING, computerChoice)
        }
    }; resultScreen()
}

Function_2...

private fun FUNCTION_2(cc :String) {
    runOnUiThread {
        TITLE.text = getString(R.string.STRING)
        PARAGRAPH.text = getString(R.string.STRING, cc)
    }; resultScreen()
}

resultScreen() is just a call to setContentView(LAYOUT)

Here's a video of the app and the update problem: https://i.sstatic.net/zNuTe.jpg

Code complete here: https://github.com/noiwyr/MorraCinese


EDIT Unfortunately none of the answers actually worked as I hoped, however redesigning the app and using multiple activities with some tweaks solved the issue. You may find the new code in the github repo.

However I would be curious to know if there is a working solution for this question :)

Upvotes: 0

Views: 2311

Answers (3)

Rajiv Rajan
Rajiv Rajan

Reputation: 151

There are quite a few errors in your code, so I'm going to break down the answer with your code. Do find the Comments inline

class MainActivity : AppCompatActivity() {

    /**
    * First, Follow conventions for naming variables, they are usually in camelcase for variables and functions, Capitalized for Constants.
    * Second, lateinit is used to defer the initialization of a variable, for views, such as 
    * TextView's, you could use the Kotlin Synthentic library which automatically references the Views of your layout. 
    */
    lateinit var TITLE:TextView
    lateinit var PARAGRAPH:TextView

    override fun onCreate(savedInstanceState :Bundle?) {
        super.onCreate(savedInstanceState)
        /** 
        * Set content view, internally set's the layout file after inflation using the Activity context. Which means, that you do not 
        * need to specifically inflate the view. 
        */
        setContentView(R.layout.activity_main)

        /**
        * This is the reason why your layout doesn't know refresh, what you're doing here is inflating another layout, but not setting it to your activity. 
        * This is not required as explained above
        */
        val InflaterInitializer = LayoutInflater.from(applicationContext) as LayoutInflater
        /**
        * Inflater inflates a View Object. one would use this approach if they were programatically adding Views 
        */
        val inflater = InflaterInitializer.inflate(R.layout.activity_2, null, false)

        /**
        * the below views are pointing to a reference of TextView for the non visible inflated view. Which is the reason why the text is not updated. 
        */
        TITLE= inflater.findViewById(R.id.title) as TextView
        PARAGRAPH= inflater.findViewById(R.id.paragraph) as TextView

    }
}

Here's the code to make things work

class MainActivity : AppCompatActivity() {

    private var title:TextView? = null
    private var paragraph:TextView? = null

    override fun onCreate(savedInstanceState :Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        title= inflater.findViewById(R.id.title) as TextView
        paragraph= inflater.findViewById(R.id.paragraph) as TextView

    }

    fun function(v :View) {
        val userChoice = "XXX"
        val computerChoice = getComputerChoice()
        if (userChoice == computerChoice) {
            function2(computerChoice)
        } else {
            title.text = if (computerChoice == "YYY") getString(R.string.YOU_WON) else getString(R.string.YOU_LOSE);
            paragraph.text = getString(R.string.STRING, computerChoice)

        } 
        resultScreen()
    }

    private fun function2(cc :String) { 
       title.text = getString(R.string.STRING)
       paragraph.text = getString(R.string.STRING, cc)
       resultScreen()
    }
}

If your use case is to show different screens, look at starting more than one Activity and transitioning between them using Intents

Upvotes: 0

Garnik
Garnik

Reputation: 145

By calling InflaterInitializer.inflate(R.layout.activity_2, null, false) you inflate a new view hierarchy from the specified xml resource, which is not attached to any of your views (these new views are not shown on your screen). Then you found text views from that new view hierarchy and changed their titles.

So, your onCreate method have to look like this:

override fun onCreate(savedInstanceState :Bundle?) {
   super.onCreate(savedInstanceState)
   setContentView(R.layout.activity_2)

   TITLE = findViewById(R.id.title)
   PARAGRAPH = findViewById(R.id.paragraph)
}

Also, it's redundant to use methods runOnUiThread() (your code already runs on Ui thread) and resultScreen().

Upvotes: 1

Ishika Vaghasiya
Ishika Vaghasiya

Reputation: 38

You no need anything , you creat over code no problem I suggest you

val InflaterInitializer = LayoutInflater.from(applicationContext) as LayoutInflater val inflater = InflaterInitializer.inflate(R.layout.activity_outcome, null, false)

Comment this above code no need in kotlin

motivoRisultato.text = getString(R.string.scelta_pc, computerChoice)

Simpaly make this type of code

Upvotes: 0

Related Questions