可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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>
回答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.
回答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...
回答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
compile \'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>
回答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.
回答5:
You can have a look at the new percent support library.
compile \'com.android.support:percent:22.2.0\'
docs
sample
回答6:
You can use PercentRelativeLayout, It is a recent undocumented addition to the Design Support Library, enables the ability to specify not only elements relative to each other but also the total percentage of available space.
Subclass of RelativeLayout that supports percentage based dimensions
and margins. You can specify dimension or a margin of child by using
attributes with \"Percent\" suffix.
<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>
The Percent package provides APIs to support adding and managing percentage based dimensions in your app.
To use, you need to add this library to your Gradle dependency list:
dependencies {
compile \'com.android.support:percent:22.2.0\'//23.1.1
}
回答7:
I have solved this creating a custom View:
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);
}
}
This is invisible strut I can use to align other views within RelativeLayout.
回答8:
Update
As pointed by @EmJiHash PercentRelativeLayout and PercentFrameLayout
is deprecated in API level 26.0.0
Consider Using ConstraintLayout
Google introduced new API called android.support.percent
1)PercentRelativeLayout
2)PercentFrameLayout
Add compile dependency like
compile \'com.android.support:percent:23.1.1\'
You can specify dimension in percentage so get both benefit of RelativeLayout
and 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/>
回答9:
PercentRelativeLayout is deprecated from Revision 26.0.0 of support Library.
Google introduced new Layout called ConstraintLayout.
Add the library as a dependency in your module-level build.gradle file:
dependencies {
compile \'com.android.support.constraint:constraint-layout:1.0.1\'
}
just add in a layout file:
<?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
Constraints help you keep widgets aligned. You can use anchors, such as the constraint handles shown below, to determine alignment rules between various widgets.
Wrap Content
: The view expands as needed to fit its contents.
Match Constraints
: The view expands as needed to meet the definition of its constraints after accounting for margins. However, if the given dimension has only one constraint, then the view expands to fit its contents. Using this mode on either the height or width also allows you to set a size ratio.
Fixed
: You specify a specific dimension in the text box below or by resizing the view in the editor.
Spread
: The views are evenly distributed (after margins are accounted for). This is the default.
Spread inside
: The first and last view are affixed to the constraints on each end of the chain and the rest are evenly distributed.
Weighted
: When the chain is set to either spread or spread inside, you can fill the remaining space by setting one or more views to \"match constraints\" (0dp). By default, the space is evenly distributed between each view that\'s set to \"match constraints,\" but you can assign a weight of importance to each view using the layout_constraintHorizontal_weight and layout_constraintVertical_weight attributes. If you\'re familiar with layout_weight in a linear layout, this works the same way. So the view with the highest weight value gets the most amount of space; views that have the same weight get the same amount of space.
Packed
: The views are packed together (after margins are accounted for). You can then adjust the whole chain\'s bias (left/right or up/down) by changing the chain\'s head view bias.
Center Horizontally or Center Vertically
: To create a chain of views quickly, select them all, right-click one of the views, and then select either Center Horizontally or Center Vertically, to create either a horizontal or vertical chain
Baseline alignment
: Align the text baseline of a view to the text baseline of another view.
Constrain to a guideline
: You can add a vertical or horizontal guideline to which you can constrain views, and the guideline will be invisible to app users. You can position the guideline within the layout based on either dp units or percent, relative to the layout\'s edge.
Adjust the constraint bias
: When you add a constraint to both sides of a view (and the view size for the same dimension is either \"fixed\" or \"wrap content\"), the view becomes centered between the two constraints with a bias of 50% by default. You can adjust the bias by dragging the bias slider in the Properties window
Set size as a ratio
: You can set the view size to a ratio such as 16:9 if at least one of the view dimensions is set to \"match constraints\" (0dp).
You can learn more from the official doc.
回答10:
Since PercentRelativeLayout was deprecated in 26.0.0 and nested layouts like LinearLayout inside RelativeLayout have a negative impact on performance (Understanding the performance benefits of ConstraintLayout) the best option for you to achieve percentage width is to replace your RelativeLayout with ConstraintLayout.
This can be solved in two ways.
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>
In both cases, you get something like this
回答11:
You can accomplish this via layout weights. A weight dictates how the unclaimed portions of the screen are divided up. Give each EditText a layout_width of 0, and some proportional weight. I.e., give one a weight of 2, and the other a weight of 1 if you want the first to take up twice as much space.
回答12:
Interestingly enough, building on the answer from @olefevre, one can not only do 50/50 layouts with \"invisible struts\", but all sorts of layouts involving powers of two.
For example, here is a layout that cuts the width into four equal parts (actually three, with weights of 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>
回答13:
Just put your two textviews host and port in an independant linearlayout horizontal and use android:layout_weight to make the percentage
回答14:
Check https://github.com/mmin18/FlexLayout which you can use percent or java expression directly in layout xml.
<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\"/>