7

Actual Code:

My Main Activity:

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)

        val rollButton = binding.rollButton
        rollButton.setOnClickListener { rollDice() }

        setContentView(binding.root)
    }

    private fun rollDice() {
        val randomDiceRoll = Random.nextInt(6) + 1
        Toast.makeText(this, randomDiceRoll.toString(), Toast.LENGTH_SHORT).show()
        binding.resultText.text = randomDiceRoll.toString()
    }

My XML file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center_vertical"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/result_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="@string/count"
        android:textSize="30sp" />

    <Button
        android:id="@+id/roll_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="@string/roll" />

</LinearLayout>

Preview in android studio:

Preview

Actual layout in device:

actual layout

If I change setContentView(binding.root) to setContentView(R.layout.activity_main), the layout of Android Studio and the device become the same, but of course, the button doesn't work anymore...

Why does this happen? Why is ActivityMainBinding.inflate(layoutInflater) changing the layout? How to fix this?

Thanks

GitHub Repo: https://github.com/Wizard28082006/Dice_Roller

Wizard28
  • 355
  • 1
  • 3
  • 12

5 Answers5

5

If I change setContentView(binding.root) to setContentView(R.layout.activity_main), the layout of Android Studio and the device become the same

Most likely caused by how the container is not passed to the inflater if the view is inflated like this.

You could try the following instead:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root"

And

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        binding = ActivityMainBinding.bind(findViewById(R.id.root))

        val rollButton = binding.rollButton
        rollButton.setOnClickListener { rollDice() }
EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
  • Can you explain why the stems are not passed? – Wizard28 May 10 '20 at 15:25
  • Well, it's never passed, is it? To find it, you'd have to do `findViewById(Window.ID_CONTENT` but nobody really does that. – EpicPandaForce May 10 '20 at 15:27
  • I spent 6 hours trying to figure out `ActivityMainBinding.bind(findViewById(R.id.root))`, I honestly wish I could give you more points on this - thank you! – Nefariis Jul 18 '21 at 00:32
  • @Nefariis in retrospect, using `ActivityMainBinding.bind(findViewById(Window.ID_CONTENT).getChildAt(0)))` is technically more correct, mostly because that way you don't need to give an ID to the root container. I've been calling that `container` instead of `root` to stop having conflicts with `binding.getRoot()`. – EpicPandaForce Jul 19 '21 at 01:55
  • 1
    doesnt this defeat the purpose of using view bindings – Luca Guarro Jan 26 '22 at 05:11
  • @LucaGuarro no? why would it – EpicPandaForce Jan 26 '22 at 05:33
  • See https://developer.android.com/topic/libraries/view-binding "In most cases, view binding replaces findViewById" – Luca Guarro Jan 26 '22 at 05:46
  • 1 findViewById replacing 17+ findViewByIds still sounds like a deal – EpicPandaForce Jan 26 '22 at 09:52
  • @EpicPandaForce Isn't the layout inflated twice if you use the layout resource id instead of the binding object? Also, won't the listeners be installed to the wrong layout object? I'm referencing Sean McQuillan's findViewById vs ViewBinding article: https://medium.com/androiddevelopers/use-view-binding-to-replace-findviewbyid-c83942471fc – Nathan Meade Jan 10 '23 at 16:31
  • @NathanMeade using `_Binding.bind()` will not instantiate the layout again, that's `.inflate()`. – EpicPandaForce Jan 10 '23 at 21:15
  • Ah okay, yes - I was using `.inflate()`. Good to know! Thanks @EpicPandaForce – Nathan Meade Jan 11 '23 at 01:10
3

Maybe you should set android:layout_height as match_parent in your linearlayout and align inner views in it.

  • I got a [working code](https://hasteb.in/dixetazi.xml) from the changes you said me to make, this one looks the same across android studio and my device... But I used `android:gravity="center_vertical"` instead of `android:layout_gravity="center_vertical" to make it work... Can you explain why did this happen? – Wizard28 May 10 '20 at 03:54
  • @Wizard28 I experienced the same result when doing what you did. Sandeep Patil's answer does a good job explaining why this occurs. – Nathan Meade Jan 10 '23 at 16:25
3

Since the screenshots suggest that the question comes from the Udacity course on Andorid, there is a good explanation on the course knowledge hub (link accessible only to the course users). In short, the explanation is the two things mentioned in the setContentView docs and the ViewBinding docs.

First is that when using setContentView the

layout parameters of the specified view are ignored

and the drawback of ViewBinding is

it doesn't support layout variables or layout expressions, so it can't be used to declare dynamic UI content straight from XML layout files

Sandeep Patil
  • 1,272
  • 3
  • 9
  • 12
  • 1
    This should be higher up. This explains what the problem actually is. Simply changing the layout_gravity to gravity doesn't explain what the problem is and why this issue is occurring. Thank you Sandeep. – Nathan Meade Jan 10 '23 at 16:26
3

There is a difference between android:gravity and android:layout_gravity:

  • android:gravity sets the gravity of the View Content (or child in case it was applied on a ViewGroup).
  • meanwhile android:layout_gravity sets the gravity of the View it is applied on, relative to its parent.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:gravity="center_vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="1"
        android:layout_gravity="center_horizontal"
        android:textSize="30sp"/>
</LinearLayout>
kafran
  • 729
  • 7
  • 13
0

Adding android:gravity = "center" to LinearLayout solves the problem.

Luca Guarro
  • 1,085
  • 1
  • 11
  • 25