首页 文章

RelativeLayout中的百分比宽度

提问于
浏览
412

我正在为我的Android应用程序中的登录 Activity 制作表单布局 . 下面的图片是我希望它看起来像:

enter image description here

我能够使用以下 XML 实现此布局 . 问题是,它有点hackish . 我不得不为主机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>

14 回答

  • 11

    更新1

    由@EmJiHash指出 PercentRelativeLayoutAPI level 26.0.0 中已弃用

    Below quoting google comment:

    此类在API级别26.0.0中已弃用 . 考虑使用ConstraintLayout和相关的布局 . 下面显示如何使用ConstraintLayout复制百分比布局的功能


    Google introduced new API called android.support.percent

    然后,您只需指定要查看的百分比即可

    添加编译依赖性就像

    compile '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>
    
  • 1

    您不能使用百分比来定义RelativeLayout中的视图的尺寸 . 最好的方法是使用LinearLayout和权重,或自定义布局 .

  • 3

    只需将您的两个textviews主机和端口放在一个独立的linearlayout水平,并使用android:layout_weight来制作百分比

  • 279

    PercentRelativeLayout已从支持库的修订版26.0.0中弃用 .

    Google introduced new Layout called ConstraintLayout.

    在库模块级build.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>
    

    Constraints

    约束可以帮助您保持小部件对齐 . 您可以使用锚点(如下面显示的约束句柄)来确定各个窗口小部件之间的对齐规则 .

    • Wrap Content :视图根据需要展开以适合其内容 .

    • Match Constraints :在考虑边距后,视图会根据需要进行扩展,以满足其约束的定义 . 但是,如果给定维度只有一个约束,则视图会展开以适合其内容 . 在高度或宽度上使用此模式还允许您设置尺寸比率 .

    • Fixed :您可以在下面的文本框中指定特定尺寸,也可以在编辑器中调整视图大小 .

    • Spread :视图均匀分布(在考虑边距后) . 这是默认值 .

    • Spread inside :第一个和最后一个视图附加在链的每一端的约束上,其余视图均匀分布 .

    • Weighted :当链被设置为展开或展开时,您可以通过将一个或多个视图设置为"match constraints"(0dp)来填充剩余空间 . 默认情况下,空间均匀分布在每个视图之间's set to 252335 but you can assign a weight of importance to each view using the layout_constraintHorizontal_weight and layout_constraintVertical_weight attributes. If you'在线性布局中熟悉layout_weight,这种方式相同 . 因此,具有最高权重值的视图获得最大的空间;具有相同权重的视图获得相同的空间量 .

    • Packed :视图被打包在一起(在考虑边距之后) . 然后,您可以调整整个链's bias (left/right or up/down) by changing the chain'的头视图偏差 .

    • Center Horizontally or Center Vertically :要快速创建视图链,请选择所有视图,右键单击其中一个视图,然后选择“水平居中”或“垂直居中”,以创建水平或垂直链

    • Baseline alignment :将视图的文本基线与另一个视图的文本基线对齐 .

    • Constrain to a guideline :您可以添加可以约束视图的垂直或水平参考线,并且该参考线将对应用用户不可见 . 您可以根据相对于布局边缘的dp单位或百分比将指南定位在布局中 .

    • Adjust the constraint bias :向视图的两侧添加约束(并且同一维度的视图大小为"fixed"或"wrap content")时,视图将在两个约束之间居中,默认偏差为50% . 您可以通过拖动“属性”窗口中的偏移滑块来调整偏差

    • Set size as a ratio :如果至少有一个视图尺寸设置为"match constraints"(0dp),则可以将视图大小设置为16:9之比 .

    您可以从doc官方了解更多信息 .

  • 78

    Update

    正如@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 和百分比的好处

    <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/>
    
  • 31

    您正在寻找 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>
    

    它适用于任何类型的View,您可以使用一些EditText替换按钮以满足您的需求 .

    务必将 layout_width 设置为 0dp 或者您的观点可能无法正确缩放 .

    请注意,权重总和不必等于1,我发现这样更容易阅读 . 您可以将第一个权重设置为7,将第二个权重设置为3,它将得到相同的结果 .

  • 18

    您可以通过布局权重来完成此操作 . 重量决定了如何分割屏幕的无人认领部分 . 给每个EditText一个layout_width为0,以及一些比例权重 . 即,如果你想让第一个占据两倍的空间,给一个重量为2,另一个重量为1 .

  • 6

    有趣的是,在@olefevre的答案的基础上,人们不仅可以使用“隐形支柱”进行50/50布局,而且还可以使用两种方式进行各种布局 .

    例如,这是一个将宽度切割成四个相等部分的布局(实际上是三个,权重为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>
    
  • 3

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

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

    docs

    sample

  • 128

    检查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"/>
    
  • 11

    由于PercentRelativeLayout在26.0.0中已弃用,而且RelativeLayout内的LinearLayout等嵌套布局对性能有负面影响(Understanding the performance benefits of ConstraintLayout),因此实现百分比宽度的最佳选择是用ConstraintLayout替换RelativeLayout .

    这可以通过两种方式解决 .

    SOLUTION #1 Using guidelines with percentage offset

    <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>
    

    SOLUTION #2 Using chain with weighted width for 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>
    

    在这两种情况下,你都会得到这样的东西

  • 705

    这并没有完全回答原始问题,即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布局中存在太多期待......

  • 3

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

    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中对齐其他视图的隐形支柱 .

  • 4

    您可以使用PercentRelativeLayout,它是 Design Support Library 的最近未记录的添加,使得能够不仅指定彼此相对的元素,还指定可用空间的 total percentage .

    RelativeLayout的子类,支持基于百分比的维度和边距 . 您可以使用带有“Percent”后缀的属性来指定子项的维度或边距 .

    <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包在您的应用中提供基于 APIs to support adding and managing percentage 的维度 .

    要使用,您需要添加此 library to your Gradle dependency 列表:

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

相关问题