相对布局中宽度的百分比

我正在为我的Android应用程序中的Login Activity做一个表单布局。下图是我想让它看起来的样子:

enter image description here

我可以通过下面的XML实现这个布局。问题是,这有点粗俗。我必须为主机EditText硬编码一个宽度。具体来说,我必须说明:

android:layout_width="172dp"

我真的想给主机和端口EditText的一个百分比宽度。(主机占用80%,端口占用20%。)这可能吗?下面的XML可以在我的Droid上运行,但似乎并不适用于所有屏幕。我真的想要一个更健壮的解决方案。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >


<TextView
android:id="@+id/host_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/home"
android:paddingLeft="15dp"
android:paddingTop="0dp"
android:text="host"
android:textColor="#a5d4e2"
android:textSize="25sp"
android:textStyle="normal" />


<TextView
android:id="@+id/port_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/home"
android:layout_toRightOf="@+id/host_input"
android:paddingTop="0dp"
android:text="port"
android:textColor="#a5d4e2"
android:textSize="25sp"
android:textStyle="normal" />


<EditText
android:id="@+id/host_input"
android:layout_width="172dp"
android:layout_height="wrap_content"
android:layout_below="@id/host_label"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="4dp"
android:background="@android:drawable/editbox_background"
android:inputType="textEmailAddress" />


<EditText
android:id="@+id/port_input"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_below="@id/host_label"
android:layout_marginTop="4dp"
android:layout_toRightOf="@id/host_input"
android:background="@android:drawable/editbox_background"
android:inputType="number" />


<TextView
android:id="@+id/username_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/host_input"
android:paddingLeft="15dp"
android:paddingTop="15dp"
android:text="username"
android:textColor="#a5d4e2"
android:textSize="25sp"
android:textStyle="normal" />


<EditText
android:id="@+id/username_input"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/username_label"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="4dp"
android:background="@android:drawable/editbox_background"
android:inputType="textEmailAddress" />


<TextView
android:id="@+id/password_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/username_input"
android:paddingLeft="15dp"
android:paddingTop="15dp"
android:text="password"
android:textColor="#a5d4e2"
android:textSize="25sp"
android:textStyle="normal" />


<EditText
android:id="@+id/password_input"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/password_label"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="4dp"
android:background="@android:drawable/editbox_background"
android:inputType="textPassword" />


<ImageView
android:id="@+id/home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_centerVertical="false"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingTop="15dp"
android:scaleType="fitStart"
android:src="@drawable/home" />


<Button
android:id="@+id/login_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/password_input"
android:layout_marginLeft="15dp"
android:layout_marginTop="15dp"
android:text="   login   "
android:textSize="18sp" >
</Button>


</RelativeLayout>
583947 次浏览

不能在RelativeLayout中使用百分比来定义视图的维度。最好的方法是使用线性布局和权重,或自定义布局。

你可以通过布局权重来实现。权重决定了屏幕上无人认领的部分如何划分。给每个EditText一个0的layout_width和一些成比例的权重。也就是说,如果你想让第一个占用两倍的空间,给一个权重为2,给另一个权重为1。

你正在寻找android:layout_weight属性。它将允许你使用百分比来定义你的布局。

在下面的例子中,左键占用70%的空间,右键占用30%的空间。

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">


<Button
android:text="left"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".70" />


<Button
android:text="right"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".30" />


</LinearLayout>

它的工作原理与任何类型的视图相同,你可以用一些EditText替换按钮来满足你的需要。

请确保将layout_width设置为0dp,否则您的视图可能无法正确缩放。

注意,权重和不一定等于1,我只是觉得这样读起来更容易。你可以将第一个权重设置为7,第二个权重设置为3,结果是一样的。

这并没有完全回答最初的问题,即70/30分割,但在组件之间50/50分割的特殊情况下,有一种方法:在中心放置一个无形的支柱,并用它来定位感兴趣的两个组件。

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View android:id="@+id/strut"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_centerHorizontal="true"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignRight="@id/strut"
android:layout_alignParentLeft="true"
android:text="Left"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/strut"
android:layout_alignParentRight="true"
android:text="Right"/>
</RelativeLayout>

由于这是一个非常常见的情况,这个解决方案不仅仅是一个好奇。这有点笨拙,但很有效,因为空的、零大小的支柱应该花费很少。

但总的来说,最好不要对现有的Android布局抱有太多期望……

有趣的是,基于@olefevre的回答,人们不仅可以使用“隐形struts”进行50/50的布局,而且还可以使用涉及2的幂的各种布局。

例如,这里有一个布局,将宽度切割成四个相等的部分(实际上是三个,权重为1,1,2):

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


<View
android:id="@+id/strut"
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:background="#000000" />


<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/strut" >


<View
android:id="@+id/left_strut"
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_toLeftOf="@+id/strut"
android:layout_centerHorizontal="true"
android:background="#000000" />


<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignRight="@+id/left_strut"
android:text="Far Left" />


<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_toRightOf="@+id/left_strut"
android:text="Near Left" />
</RelativeLayout>


<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/strut"
android:layout_alignParentRight="true"
android:text="Right" />


</RelativeLayout>

我已经解决了这个问题,创建一个自定义视图:

public class FractionalSizeView extends View {
public FractionalSizeView(Context context, AttributeSet attrs) {
super(context, attrs);
}


public FractionalSizeView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
setMeasuredDimension(width * 70 / 100, 0);
}
}

这是不可见的支柱,我可以用它来对齐RelativeLayout中的其他视图。

您可以查看新的百分比支持库。

compile 'com.android.support:percent:22.2.0'

docs

sample

更新1

正如@EmJiHash所指出的,PercentRelativeLayoutAPI等级26.0.0中已弃用

以下引用谷歌的评论:

这个类在API级别26.0.0中已弃用。 可以考虑使用ConstraintLayout和相关的布局。下面展示了如何使用ConstraintLayout

复制百分比布局的功能

谷歌引入了新的API叫做 android.support.percent . %

然后,您可以指定百分比,以采取的视图

添加编译依赖项,如

implementation 'com.android.support:percent:22.2.0

其中,PercentRelativeLayout是我们可以做的百分比布局

 <android.support.percent.PercentRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
app:layout_widthPercent="50%"
app:layout_heightPercent="50%"
app:layout_marginTopPercent="25%"
app:layout_marginLeftPercent="25%"/>
</android.support.percent.PercentRelativeLayout>

你可以使用PercentRelativeLayout,它是最近添加到设计支援图书馆中,没有文档记录,不仅可以指定相对于彼此的元素,还可以指定可用空间的总百分比

RelativeLayout的子类,支持基于百分比的维度 和利润率。可以使用来指定子元素的尺寸或边距

<android.support.percent.PercentRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_widthPercent="50%"
app:layout_heightPercent="50%"
app:layout_marginTopPercent="25%"
app:layout_marginLeftPercent="25%"/>
</android.support.percent.PercentFrameLayout>

Percent包在你的应用程序中提供了基于支持添加和管理百分比的api的尺寸。

要使用,你需要添加这个到你的Gradle依赖项列表:

dependencies {
compile 'com.android.support:percent:22.2.0'//23.1.1
}

只是把你的两个textviews主机和端口在一个独立的线性布局水平和使用android:layout_weight使百分比

更新

由@EmJiHash PercentRelativeLayout和PercentFrameLayout指出 在API级别26.0.0

考虑使用ConstraintLayout

谷歌引入了名为android.support.percent的新API

1) PercentRelativeLayout

2) PercentFrameLayout

添加编译依赖项,如

compile 'com.android.support:percent:23.1.1'

你可以用百分比来指定维度,这样就可以同时获得RelativeLayout和percentage的好处

 <android.support.percent.PercentRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
app:layout_widthPercent="40%"
app:layout_heightPercent="40%"
app:layout_marginTopPercent="15%"
app:layout_marginLeftPercent="15%"/>
</android.support.percent.PercentRelativeLayout/>

检查https://github.com/mmin18/FlexLayout,你可以直接在布局xml中使用百分比或java表达式。

<EditText
app:layout_left="0%"
app:layout_right="60%"
app:layout_height="wrap_content"/>
<EditText
app:layout_left="prev.right+10dp"
app:layout_right="100%"
app:layout_height="wrap_content"/>

PercentRelativeLayout在支持库的26.0.0版本中已弃用。

谷歌引入了新的布局,名为ConstraintLayout

将库作为依赖项添加到模块级构建中。gradle文件:

     dependencies {
compile 'com.android.support.constraint:constraint-layout:1.0.1'
}

只需添加一个布局文件:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.constraint.ConstraintLayout>

约束

约束帮助您保持小部件的一致性。您可以使用锚(例如下面所示的约束句柄)来确定不同小部件之间的对齐规则。

 ></a></p>


<ol>
<li><code>Wrap Content</code>:视图根据需要展开以适应其内容。</li>
<li><code>Match Constraints</code>:在考虑了保证金后,视图根据需要扩展以满足其约束的定义。但是,如果给定的维度只有一个约束,那么视图将展开以适应其内容。在高度或宽度上使用此模式还可以设置大小比例。</li>
<li><code>Fixed</code>:你可以在下面的文本框中指定一个特定的维度,或者在编辑器中调整视图的大小。</li>
<li><code>Spread</code>:视图是均匀分布的(在考虑了边距之后)。这是默认值。</li>
<li><code>Spread inside</code>:第一个和最后一个视图被附加到链的每一端的约束,其余的均匀分布。</li>
<li><code>Weighted</code>:当链被设置为spread或spread inside时,你可以通过将一个或多个视图设置为“匹配约束”(0dp)来填充剩余空间。默认情况下,空间平均分布在每个设置为“匹配约束”的视图之间,但您可以使用layout_constraintHorizontal_weight和layout_constraintVertical_weight属性为每个视图分配重要性权重。如果你熟悉线性布局中的layout_weight,它的工作方式是一样的。因此,具有最高权重值的视图获得最多的空间;具有相同权重的视图获得相同的空间量。</li>
<li><code>Packed</code>:视图被打包在一起(在考虑了边距之后)。然后,您可以通过改变链的头部视图偏差来调整整个链的偏差(左/右或上/下)。</li>
<li><code>Center Horizontally or Center Vertically</code>:要快速创建一个视图链,选中所有视图,右键单击其中一个视图,然后选择水平居中或垂直居中,创建一个水平或垂直的链</li>
<li><code>Baseline alignment</code>:将一个视图的文本基线对齐到另一个视图的文本基线。</li>
<li><code>Constrain to a guideline</code>:你可以添加一个垂直或水平的指导方针,你可以约束视图,指导方针将是不可见的应用程序用户。您可以根据相对于布局边缘的dp单位或百分比在布局中定位指导方针。</li>
<li><code>Adjust the constraint bias</code>:当你在视图的两侧添加约束时(相同维度的视图大小是“固定的”或“包装内容”),默认情况下,视图会在两个约束之间居中,偏差为50%。您可以通过拖动“属性”窗口中的偏置滑块来调整偏置</li>
<li><code>Set size as a ratio</code>:如果至少有一个视图维度被设置为“匹配约束”(0dp),则可以将视图大小设置为16:9这样的比例。</li>
</ol>


<p>你可以从官方的<a href=医生中了解更多。

 ></a></p></div>
                                                                            </div>
                                </div>
                            </div>
                        </div>
                                                <div class=

由于PercentRelativeLayout在26.0.0中已弃用,并且嵌套的布局,如RelativeLayout内部的LinearLayout对性能有负面影响(理解ConstraintLayout的性能优势),为您实现百分比宽度的最佳选择是用ConstraintLayout替换您的RelativeLayout。

这个问题可以通过两种方式解决。

解决方案#1使用百分比偏移的指导方针

Layout Editor

<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">


<TextView
android:id="@+id/host_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Host"
android:layout_marginTop="16dp"
android:layout_marginLeft="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="@+id/host_input" />


<TextView
android:id="@+id/port_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Port"
android:layout_marginTop="16dp"
android:layout_marginLeft="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="@+id/port_input" />


<EditText
android:id="@+id/host_input"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:inputType="textEmailAddress"
app:layout_constraintTop_toBottomOf="@+id/host_label"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/guideline" />


<EditText
android:id="@+id/port_input"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:inputType="number"
app:layout_constraintTop_toBottomOf="@+id/port_label"
app:layout_constraintLeft_toLeftOf="@+id/guideline"
app:layout_constraintRight_toRightOf="parent" />


<android.support.constraint.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.8" />


</android.support.constraint.ConstraintLayout>

解决方案#2使用链与加权宽度的EditText

Layout Editor

<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">


<TextView
android:id="@+id/host_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Host"
android:layout_marginTop="16dp"
android:layout_marginLeft="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="@+id/host_input" />


<TextView
android:id="@+id/port_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Port"
android:layout_marginTop="16dp"
android:layout_marginLeft="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="@+id/port_input" />


<EditText
android:id="@+id/host_input"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:inputType="textEmailAddress"
app:layout_constraintHorizontal_weight="0.8"
app:layout_constraintTop_toBottomOf="@+id/host_label"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/port_input" />


<EditText
android:id="@+id/port_input"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:inputType="number"
app:layout_constraintHorizontal_weight="0.2"
app:layout_constraintTop_toBottomOf="@+id/port_label"
app:layout_constraintLeft_toRightOf="@+id/host_input"
app:layout_constraintRight_toRightOf="parent" />


</android.support.constraint.ConstraintLayout>

在这两种情况下,你会得到这样的结果

Result View .