layout_margin on按钮未在布局中考虑

时间:2015-03-27 20:43:31

标签: android android-layout

我想我可能在layout_margin处理按钮的方式上发现了一个错误。可以归结为测量时不考虑按钮边距。结果,他们的父母ViewGroup测量自己略微过小。当最终绘制按钮时,没有足够的空间,他们被迫包装或椭圆化他们的文本。即使按钮的祖父母中有足够的空间让按钮的父母变大,也会发生这种情况。无论我在按钮的样式中设置layout_margin还是在按钮本身上设置layout_margin,都存在问题。我不知道这是否会影响其他类型的观点。

这是一个已知问题吗?除了不在按钮上使用边距之外,是否存在任何解决方法?(或者我只是做错了什么?)

我在大约一年前发现unanswered question表示layout_margin在自定义按钮样式中根本不起作用。它实际上对我来说就像问题的提问者所期望的那样,至少在按钮确实具有指定余量的意义上。所以也许谷歌最近“修复”了它并且修复忽略了一些东西。

此片段布局演示了此问题。它在编辑器中看起来很好。指定的按钮样式的3dp<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" > <EditText android:id="@+id/userField" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ems="8" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:hint="@string/hint_user" /> <EditText android:id="@+id/passwordField" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/userField" android:layout_alignLeft="@id/userField" android:layout_alignRight="@id/userField" android:inputType="textPassword" android:fontFamily="sans-serif" android:hint="@string/hint_password" /> <Button android:id="@+id/loginButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@+id/userField" android:layout_centerVertical="true" style="@style/button_blue" android:text="@string/login" /> </RelativeLayout>

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <fragment
        android:id="@+id/fragment"
        android:name="com.example.MyFragment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        tools:layout="@layout/fragment_login" />

</RelativeLayout>

good layout

但是当这个片段放在另一个布局中时,片段的宽度显然是不正确的。

\u00A0

bad layout

文本包含中间词,因为我在按钮文本中使用了不间断的空格(layout_margin)。在正常空间中,它包裹在单词边界。如果我从按钮样式中删除<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.chalcodes.marginbug.MainActivity" > <RelativeLayout android:id="@+id/buttonLayout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" > <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="20dp" android:text="Button" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="20dp" android:layout_toRightOf="@id/button1" android:text="Button" /> </RelativeLayout> </RelativeLayout> ,问题就会消失。

编辑:这是一个展示问题的独立布局。问题始终出现在WYSIWYG编辑器SDK 21中。在实际设备上,错误表现在2.3.6和4.0.4而不是4.4.1或5.0.1。

{{1}}

margin bug

编辑2:跟进corsair992的评论,我将AS更新到最新版本(1.2 beta 3)并粘贴了我上面的独立示例。这个 重现了这个问题。但奇怪的是,当我将预览方向从纵向更改为横向时,问题就消失了。更奇怪的是,当我回到肖像时,问题没有回来!如果我重新启动AS,它会在第一次时错误地渲染我的布局,然后在旋转后正确渲染它。 Eclipse总是错误地渲染布局。

我注意到Android Studio的WYSIWYG编辑器比Eclipse更加积极地缓存事物。在Eclipse中,我可以立即看到对自定义视图的更改,但是在一个干净的&amp; amp;之后,AS固执地依赖于自定义视图的旧渲染。重建,甚至重启后。所以也许AS正在缓存一些关于布局的信息,这有助于它第二次正确渲染。但也许这只是掩盖了这个错误。

2 个答案:

答案 0 :(得分:0)

我实际上创建了自己的解决方法,似乎解决了这个问题。但这只是一个概念证明。这个问题似乎没有影响4.4或5.0,虽然我发誓我已经看到它在我的4.4设备上发生了某些时候。为了使解决方法可以部署,我必须有条件地激活它。

我会将奖金奖励给能够向我展示此问题影响的Android版本(如果是已知问题)或在运行时检测设备是否受到影响的聪明方法的人。

import android.content.Context;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.widget.Button;

public class WorkaroundButton extends Button {

    public WorkaroundButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        final ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) getLayoutParams();       
        final int width = getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
        final int height = getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
        setMeasuredDimension(width, height);
    }

}

答案 1 :(得分:0)

我能够重现这一点的唯一方法就是选择&#34; Wear Square&#34;编辑器中的虚拟设备。

enter image description here

似乎问题不在于保证金。正如您在上图和第一次编辑的图像中看到的那样,边距确实是强制执行的。

问题在于边距大小,android:layout_toRightOf属性和RelativeLayout缺少&#34;权重&#34; LinearLayouts中的概念。

不使用android:layout_toRightOf,而是使用为其子项指定权重值的水平LinearLayout,或使用左侧按钮上的android:layout_alignParentLeft="true"和右侧按钮上的android:layout_alignParentRight="true"