Percentage width in a RelativeLayout
I am working on a form layout for a Login Activity
in my Android App. The image below is how I want it to look like:
I was able to achieve this layout with the following XML. The problem is, it's a bit hackish. I had to hard-code a width for the host EditText. Specifically, I had to specify:
android:layout_width="172dp"
I'd really like to give a percentage width to the host and port EditText's . (Something like 80% for the host, 20% for the port.) Is this possible? The following XML works on my Droid, but it doesn't seem to work for all screens. I would really like a more robust solution.
<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>
Solution 1:
You are looking for the android:layout_weight
attribute. It will allow you to use percentages to define your layout.
In the following example, the left button uses 70% of the space, and the right button 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>
It works the same with any kind of View, you can replace the buttons with some EditText to fit your needs.
Be sure to set the layout_width
to 0dp
or your views may not be scaled properly.
Note that the weight sum doesn't have to equal 1, I just find it easier to read like this. You can set the first weight to 7 and the second to 3 and it will give the same result.
Solution 2:
This does not quite answer the original question, which was for a 70/30 split, but in the special case of a 50/50 split between the components there is a way: place an invisible strut at the center and use it to position the two components of interest.
<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>
As this is a pretty common case, this solution is more than a curiosity. It is a bit of a hack but an efficient one because the empty, zero-sized strut should cost very little.
In general, though, it's best not to expect too much from the stock Android layouts...
Solution 3:
Update 1
As pointed by @EmJiHash PercentRelativeLayout is deprecated in API level 26.0.0
Below quoting google comment:
This class was deprecated in API level 26.0.0. consider using ConstraintLayout and associated layouts instead. The following shows how to replicate the functionality of percentage layouts with a ConstraintLayout
Google introduced new API called android.support.percent
Then you can just specify percentage to take by view
Add compile dependency like
implementation 'com.android.support:percent:22.2.0
in that, PercentRelativeLayout is what we can do a percentage wise layout
<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>
Solution 4:
You cannot use percentages to define the dimensions of a View inside a RelativeLayout. The best ways to do it is to use LinearLayout and weights, or a custom Layout.