我正在为我的Android应用程序中的登录活动做一个表单布局。下图是我想让它看起来的样子:
我能够使用以下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>
由于PercentRelativeLayout在26.0.0中已弃用,并且嵌套的布局,如RelativeLayout内部的LinearLayout对性能有负面影响(了解ConstraintLayout的性能优势),为您实现百分比宽度的最佳选择是用ConstraintLayout替换您的RelativeLayout。
这个问题可以通过两种方式解决。
解决方案#1使用百分比偏移的指导方针
<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
<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>
在这两种情况下,你会得到这样的结果
更新1
正如@EmJiHash指出的那样,PercentRelativeLayout在API级别26.0.0中已弃用
以下引用谷歌的评论:
这个类在API级别26.0.0中已弃用。
可以考虑使用ConstraintLayout和相关的布局。下面展示了如何使用ConstraintLayout复制百分比布局的功能
谷歌引入了名为android.support.percent的新API
然后,您可以指定百分比,以采取的视图
添加编译依赖项,如
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>
有趣的是,基于@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>
由于PercentRelativeLayout在26.0.0中已弃用,并且嵌套的布局,如RelativeLayout内部的LinearLayout对性能有负面影响(了解ConstraintLayout的性能优势),为您实现百分比宽度的最佳选择是用ConstraintLayout替换您的RelativeLayout。
这个问题可以通过两种方式解决。
解决方案#1使用百分比偏移的指导方针
<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
<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>
在这两种情况下,你会得到这样的结果
我已经解决了这个问题,创建一个自定义视图:
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中的其他视图。