如何根据父视图的尺寸调整 Android 视图的大小
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2159320/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to size an Android view based on its parent's dimensions
提问by Mitch
How can I size a view based on the size of its parent layout. For example I have a RelativeLayout
that fills the full screen, and I want a child view, say an ImageView
, to take up the whole height, and 1/2 the width?
如何根据父布局的大小调整视图的大小。例如,我有一个RelativeLayout
填满全屏的,我想要一个子视图,比如一个ImageView
,占据整个高度,宽度的 1/2?
I've tried overriding all on onMeasure
, onLayout
, onSizeChanged
, etc and I couldn't get it to work....
我试过覆盖, , 等上的所有内容onMeasure
,但我无法让它工作....onLayout
onSizeChanged
回答by Vic
I don't know if anyone is still reading this thread or not, but Jeff's solution will only get you halfway there (kinda literally). What his onMeasure will do is display half the image in half the parent. The problem is that calling super.onMeasure prior to the setMeasuredDimension
will measure all the children in the view based on the original size, then just cut the view in half when the setMeasuredDimension
resizes it.
我不知道是否有人还在阅读这个帖子,但杰夫的解决方案只会让你走到一半(有点字面意思)。他的 onMeasure 将做的是在父级的一半中显示一半的图像。问题是在之前调用 super.onMeasuresetMeasuredDimension
将根据原始大小测量视图中的所有子项,然后在setMeasuredDimension
调整视图大小时将视图切成两半。
Instead, you need to call setMeasuredDimension
(as required for an onMeasure override) andprovide a new LayoutParams
for your view, thencall super.onMeasure
. Remember, your LayoutParams
are derived from your view's parent type, not your view's type.
相反,您需要调用setMeasuredDimension
(根据 onMeasure 覆盖的要求)并LayoutParams
为您的视图提供一个新的,然后调用super.onMeasure
. 请记住,您LayoutParams
的派生自视图的父类型,而不是视图的类型。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth/2, parentHeight);
this.setLayoutParams(new *ParentLayoutType*.LayoutParams(parentWidth/2,parentHeight));
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
I believe the only time you'll have problems with the parent LayoutParams
is if the parent is an AbsoluteLayout
(which is deprecated but still sometimes useful).
我相信唯一一次你会遇到父母问题的时候LayoutParams
是父母是一个AbsoluteLayout
(这已被弃用,但有时仍然有用)。
回答by Jeff
You could solve this by creating a custom View and override the onMeasure() method. If you always use "fill_parent" for the layout_width in your xml then the widthMeasureSpec parameter that is passed into the onMeasusre() method should contain the width of the parent.
您可以通过创建自定义视图并覆盖 onMeasure() 方法来解决此问题。如果您始终在 xml 中为 layout_width 使用“fill_parent”,则传递给 onMeasusre() 方法的 widthMeasureSpec 参数应包含父级的宽度。
public class MyCustomView extends TextView {
public MyCustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(parentWidth / 2, parentHeight);
}
}
Your XML would look something like this:
您的 XML 将如下所示:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<view
class="com.company.MyCustomView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
回答by Phil Kulak
I've found that it's best not to mess around with setting the measured dimensions yourself. There's actually a bit of negotiation that goes on between the parent and child views and you don't want to re-write all that code.
我发现最好不要自己设置测量尺寸。实际上在父视图和子视图之间进行了一些协商,您不想重新编写所有代码。
What you can do, though, is modify the measureSpecs, then call super with them. Your view will never know that it's getting a modified message from its parent and will take care of everything for you:
但是,您可以做的是修改 measureSpecs,然后用它们调用 super。您的视图永远不会知道它正在从其父级收到修改后的消息,并且会为您处理所有事情:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
int myWidth = (int) (parentHeight * 0.5);
super.onMeasure(MeasureSpec.makeMeasureSpec(myWidth, MeasureSpec.EXACTLY), heightMeasureSpec);
}
回答by Cheryl Simon
When you define a layout and view on XML, you can specify the layout width and height of a view to either be wrap content, or fill parent. Taking up half of the area is a bit harder, but if you had something you wanted on the other half you could do something like the following.
当您在 XML 上定义布局和视图时,您可以指定视图的布局宽度和高度以包装内容或填充父级。占据一半的区域有点困难,但如果你在另一半有你想要的东西,你可以做如下的事情。
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView android:layout_height="fill_parent"
android:layout_width="0dp"
android:layout_weight="1"/>
<ImageView android:layout_height="fill_parent"
android:layout_width="0dp"
android:layout_weight="1"/>
</LinearLayout>
Giving two things the same weight means that they will stretch to take up the same proportion of the screen. For more info on layouts, see the dev docs.
给两个东西相同的重量意味着它们会拉伸以占据屏幕的相同比例。有关布局的更多信息,请参阅开发文档。
回答by pinkwerther
I believe that Mayras XML-approachcan come in neat. However it is possible to make it more accurate, with one view only by setting the weightSum. I would not call this a hack anymore but in my opinion the most straightforward approach:
我相信Mayras XML 方法可以很简洁。但是,仅通过设置 weightSum 就可以使其更准确,只有一种视图。我不会再将其称为 hack,但在我看来,这是最直接的方法:
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:weightSum="1">
<ImageView android:layout_height="fill_parent"
android:layout_width="0dp"
android:layout_weight="0.5"/>
</LinearLayout>
Like this you can use any weight, 0.6 for instance (and centering) is the weight I like to use for buttons.
像这样,您可以使用任何权重,例如 0.6(和居中)是我喜欢用于按钮的权重。
回答by Abhishek Gupta
Try this
尝试这个
int parentWidth = ((parentViewType)childView.getParent()).getWidth();
int parentHeight = ((parentViewType)childView.getParent()).getHeight();
then you can use LinearLayout.LayoutParams for setting the chileView's parameters
那么你可以使用 LinearLayout.LayoutParams 来设置 chileView 的参数
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(childWidth,childLength);
childView.setLayoutParams(params);
回答by androidguy
You can now use PercentRelativeLayout. Boom! Problem solved.
您现在可以使用 PercentRelativeLayout。繁荣!问题解决了。
回答by Pavel Lahoda
Roman, if you want to do your layout in Java code (ViewGroup descendant), it is possible. The trick is that you have to implement both onMeasure and onLayout methods. The onMeasure gets called first and you need to "measure" the subview (effectively sizing it to the desired value) there. You need to size it again in the onLayout call. If you fail to do this sequence or fail to call setMeasuredDimension() at the end of your onMeasure code, you won't get results. Why is this designed in such complicated and fragile way is beyond me.
Roman,如果你想在 Java 代码(ViewGroup 后代)中做你的布局,这是可能的。诀窍是您必须同时实现 onMeasure 和 onLayout 方法。onMeasure 首先被调用,您需要在那里“测量”子视图(有效地将其调整为所需的值)。您需要在 onLayout 调用中再次调整大小。如果您未能执行此序列或未能在您的 onMeasure 代码末尾调用 setMeasuredDimension(),您将不会得到结果。为什么要以如此复杂和脆弱的方式设计,我无法理解。
回答by jpm
If the other side is empty. I guess the simplest way would be to add an empty view (e.g. a linear layout) then set both views' widths to fill_parent and both their weights to 1.
如果另一边是空的。我想最简单的方法是添加一个空视图(例如线性布局),然后将两个视图的宽度设置为 fill_parent 并将它们的权重设置为 1。
This works in a LinearLayout...
这适用于 LinearLayout ...
回答by Mario
It's something like this:
它是这样的:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.company.myapp.ActivityOrFragment"
android:id="@+id/activity_or_fragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/linearLayoutFirst"
android:weightSum="100"> <!-- Overall weights sum of children elements -->
<Spinner
android:layout_width="0dp" <!-- It's 0dp because is determined by android:layout_weight -->
android:layout_weight="50"
android:layout_height="wrap_content"
android:id="@+id/spinner" />
</LinearLayout>
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_below="@+id/linearLayoutFirst"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:id="@+id/linearLayoutSecond">
<EditText
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="75"
android:inputType="numberDecimal"
android:id="@+id/input" />
<TextView
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="25"
android:id="@+id/result"/>
</LinearLayout>
</RelativeLayout>