简体   繁体   English

Android App setContentView(R.layout.activity_main) vs View binding - layout_gravity not respected

[英]Android App setContentView(R.layout.activity_main) vs View binding - layout_gravity not respected

I decided to finally jump into Kotlin this month as a hobby project.我决定本月作为一个爱好项目加入 Kotlin。 I'm working through a Udacity course (Android app dev with Kotlin).我正在学习 Udacity 课程(使用 Kotlin 开发 Android 应用程序)。

I was just trying to replace the viewById with View binding (as a test for me).我只是想用 View 绑定替换 viewById(作为对我的测试)。 Which works fine.哪个工作正常。

But why if I use setContentView(view) from the binding does my layout no longer respect the gravity?但是,如果我从绑定中使用 setContentView(view),为什么我的布局不再尊重重力?

My layout file for my main activity is linear, with center-vertical layout_gravity我的主要活动的布局文件是线性的,中心垂直 layout_gravity

<<?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:orientation="vertical"
    android:layout_gravity="center_vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="1"
        android:textSize="30sp"
        android:layout_gravity="center_horizontal"/>

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

</LinearLayout>


When I use the old setContentView(R.layout.main_activity) in my activity, this displays as expected in the center of the screen当我在我的活动中使用旧的 setContentView(R.layout.main_activity) 时,它会按预期显示在屏幕中央

class MainActivity : AppCompatActivity() {
    @RequiresApi(Build.VERSION_CODES.P)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Let's do it the trad way without binding
        setContentView(R.layout.activity_main)
        val rollButton: Button = findViewById(R.id.roll_button)

Image with central gravity重心图像

If I swap this out for view binding instead and replace the setContentView as shown below如果我将其换成视图绑定并替换 setContentView,如下所示

var binding = ActivityMainBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)

The app still runs, but now the text and button are at the top of the screen.该应用程序仍在运行,但现在文本和按钮位于屏幕顶部。

image top aligned图像顶部对齐

I was just testing that I could make this work in general, as I'd prefer to use in real life (anything to reduce nullPointer exceptions).我只是在测试我是否可以在一般情况下完成这项工作,因为我更喜欢在现实生活中使用(任何减少 nullPointer 异常的方法)。 But if I can't even get a simple example to work properly I'm stuffed.但是,如果我什至不能得到一个简单的例子来正常工作,我就被填满了。

Does anyone know what I am doing wrong?有谁知道我做错了什么? Or what concept I'm missing?或者我缺少什么概念?

Try to change android:layout_gravity="center_horizontal" to android:layout_gravity="center" or maybe try to use RelativeLayout I heard that it's one of the best layouts.尝试将android:layout_gravity="center_horizontal"更改为android:layout_gravity="center"或者尝试使用RelativeLayout我听说它是最好的布局之一。

I'm having trouble with this same problem.我遇到了同样的问题。 I was looking at the documentation for View Binding and it states:我正在查看 View Binding 的文档,它指出:

"View binding doesn't support layout variables or layout expressions, so it can't be used to declare dynamic UI content straight from XML layout files." “视图绑定不支持布局变量或布局表达式,因此它不能用于直接从 XML 布局文件中声明动态 UI 内容。”

I'm wondering if it's related to that?我想知道这是否与此有关? I'm still very new to this, but it's the only thing I can find so far that makes some sense to me.我对此仍然很陌生,但这是迄今为止我能找到的唯一对我有意义的东西。

UPDATE: Found another question asking the same thing ( How to use View Binding with Linear Layout? )更新:发现另一个问题问同样的事情( 如何使用带有线性布局的视图绑定?

Changed android:layout_gravity="center_vertical" to android:gravity="center" , but then had an issue with the preview in Layout Editor not showing it centered;android:layout_gravity="center_vertical"更改为android:gravity="center" ,但随后在布局编辑器中的预览出现问题,未显示居中; to remedy that I added tools:layout_gravity="center_vertical" so the activity_main.xml shows this now at the top:为了解决这个问题,我添加了tools:layout_gravity="center_vertical"所以 activity_main.xml 现在在顶部显示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    tools:layout_gravity="center_vertical"
    android:orientation="vertical"
    tools:context=".MainActivity">

Might not be the best solution, but works to show you the preview and then when you actually run it!可能不是最好的解决方案,但可以向您展示预览,然后在您实际运行它时!

XML layout_ -prefixed attributes work with the parent view. XML layout_前缀属性与父视图一起使用。 When you inflate a view without a parent, the layout_* attributes have no effect.当你对没有父视图的视图进行膨胀时, layout_*属性不起作用。

An activity's setContentView(int) normally delegates to PhoneWindow#setContentView(int) that implicitly uses a parent container layout when inflating the XML layout.活动的setContentView(int)通常委托给PhoneWindow#setContentView(int) ,它在扩展 XML 布局时隐式使用父容器布局。 That's why the 1-arg inflation works in an activity.这就是为什么 1-arg 膨胀在活动中起作用的原因。

View binding does not implicitly supply any parent layouts.视图绑定不隐式提供任何父布局。 You need to explicitly supply it with the three-arg inflate(int, View, boolean) method call where the first arg is the layout id, second one is the parent and the third controls whether the inflated layout should be added to the parent when inflating.您需要使用三参数inflate(int, View, boolean)方法调用显式提供它,其中第一个参数是布局 id,第二个是父级,第三个控制是否应将膨胀布局添加到父级膨胀。

The usual an easy use case is to use fragments where the onCreateView() callback supplies you with a parent container layout and you can just return inflate(id, container, false) .通常一个简单的用例是使用片段,其中onCreateView()回调为您提供父容器布局,您只需返回inflate(id, container, false)

The PhoneWindow content layout is lazily generated, so you kinda have a chicken-and-egg problem. PhoneWindow 内容布局是延迟生成的,所以你有点鸡和蛋的问题。 Calling setContentView() generates the content layout but when calling it you kinda want to already have inflated the view binding with a parent content layout.调用setContentView()会生成内容布局,但是在调用它时,您有点希望已经使用父内容布局扩展了视图绑定。

My suggestion is to move the layout code away from your activity and instead use a fragment for it.我的建议是将布局代码从您的活动中移开,而是使用片段。 Then you can use view binding in your fragment.然后你可以在你的片段中使用视图绑定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 错误 setContentView(R.layout.activity_main) - error setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)导致应用崩溃 - setContentView(R.layout.activity_main) causes app to crash setContentView(R.layout.activity_main) 上的异常; - Exception on setContentView(R.layout.activity_main); setContentView(R.layout.activity_main); 不管用 - The setContentView(R.layout.activity_main); is not working 在setContentView(R.layout.activity_main)中创建的第一个应用程序上的Eclipse和Android ADT错误 - Eclipse and Android ADT error on the first app created in setContentView(R.layout.activity_main) 为什么要使用setContentView(R.layout.activity_main); 布局错误 - Why setContentView(R.layout.activity_main); giving error in layout setContentView(R.layout.activity_main)vs getMenuInflater()。inflate(R.menu.activity_main,menu) - setContentView(R.layout.activity_main) vs getMenuInflater().inflate(R.menu.activity_main, menu) setContentView(R.layout.activity_main)出现运行时错误 - RunTime Error at setContentView(R.layout.activity_main) 在某些设备上调用 setContentView(R.layout.activity_main) 的问题 - Issue with calling setContentView(R.layout.activity_main) on some devices 将 setContentView(R.layout.activity_main) 与 ViewBinding 合并 - Consolidating setContentView(R.layout.activity_main) with ViewBinding
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM