如何根据父视图调整Android视图的大小';s尺寸
如何根据视图父布局的大小调整视图的大小。例如,我有一个填满整个屏幕的如何根据父视图调整Android视图的大小';s尺寸,android,layout,Android,Layout,如何根据视图父布局的大小调整视图的大小。例如,我有一个填满整个屏幕的相对视图,我想要一个子视图,比如说图像视图,占据整个高度,1/2宽度 我尝试过覆盖所有的onMeasure,onLayout,onSizeChanged,等等,但我无法让它工作….当您在XML上定义布局和视图时,您可以将视图的布局宽度和高度指定为wrap\u content或fill\u parent。占据一半的面积有点困难,但是如果你在另一半上有你想要的东西,你可以做如下的事情 赋予两件东西相同的重量意味着它们将拉伸以占据
相对视图
,我想要一个子视图,比如说图像视图
,占据整个高度,1/2宽度
我尝试过覆盖所有的
onMeasure
,onLayout
,onSizeChanged
,等等,但我无法让它工作….当您在XML上定义布局和视图时,您可以将视图的布局宽度和高度指定为wrap\u content
或fill\u parent
。占据一半的面积有点困难,但是如果你在另一半上有你想要的东西,你可以做如下的事情
赋予两件东西相同的重量意味着它们将拉伸以占据屏幕的相同比例。有关布局的详细信息,请参见Roman,如果您想使用Java代码(ViewGroup子代)进行布局,则可以。诀窍是您必须同时实现onMeasure和onLayout方法。
首先调用onMeasure,您需要在那里“测量”子视图(有效地将其调整为所需的值)。您需要在onLayout call中重新调整大小。如果您未能执行此序列,或者在onMeasure代码的末尾未能调用setMeasuredDimension(),您将无法获得结果。我无法理解为什么这个设计如此复杂和脆弱。您可以通过创建自定义视图并重写onMeasure()方法来解决这个问题。如果总是对xml中的布局宽度使用“fill\u parent”,那么传递到onmeasure()方法的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);
}
}
您的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>
<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>
我不知道是否有人还在读这篇文章,但杰夫的解决方案只能让你走到一半(有点像字面意思)。他的onMeasure将在父对象的一半中显示一半的图像。问题是在
setMeasuredDimension
之前调用super.onMeasure将根据原始大小测量视图中的所有子视图,然后在setMeasuredDimension
调整视图大小时将其切成两半
相反,您需要调用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);
}
我相信,只有当父级
LayoutParams
为AbsoluteLayout
(不推荐使用,但有时仍然有用)时,才会出现问题。如果另一侧为空。我想最简单的方法是添加一个空视图(例如线性布局),然后将两个视图的宽度设置为“填充父视图”,并将其权重设置为1
这在线性布局中有效…我发现最好不要自己设置测量尺寸。实际上,在父视图和子视图之间存在一些协商,您不想重新编写所有这些 但是,您可以做的是修改measurespec,然后使用它们调用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);
}
我相信这是可以做到的。但是,可以通过设置权重和使其更精确,只使用一个视图。我不再称之为黑客,但我认为这是最直接的方法:
<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>
这样,您可以使用任何重量,例如,0.6(和居中)是我喜欢用于按钮的重量。它是这样的:
<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>
<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>
试试这个
int parentWidth = ((parentViewType)childView.getParent()).getWidth();
int parentHeight = ((parentViewType)childView.getParent()).getHeight();
然后可以使用LinearLayout.LayoutParams设置chileView的参数
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(childWidth,childLength);
childView.setLayoutParams(params);
现在可以使用PercentRelativeLayout。繁荣问题已解决。我一直在努力解决这个问题,我想更改抽屉布局的抽屉宽度,它是其父项的第二个子项。
最近我想出来了,但不知道有没有更好的主意
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
super.onLayout(changed, l, t, r, b)
(getChildAt(1).layoutParams as LayoutParams).width = measuredWidth/2
}
我不推荐这样做,但是……作为黑客,如果你使用上述方法,你可以将其中一个视图设置为“虚拟”,并将android:visibility=“invisible”设置为填充一半区域,那么只使用一半区域的目的是什么?你打算在另一半展示什么吗?您对剩余区域所做的工作将告诉您最佳的方法这肯定应该是#1-如果您可以在xml中执行,为什么要在java中执行?根据我的经验,这很少起作用,尤其是在调用填充/匹配父项或权重时。最好在设置MeasuredDimension后调用measureChildren(例如,使用MeasureSpec.MakeMasureSpec(newWidth,MeasureSpec.AT_))。MeasureSpec.getSize(widthMeasureSpec)
真的给出了正确的父级宽度吗?对我来说,它只是返回非常接近实际宽度的随机宽度,但不精确。@M.Schenk有它。我有一个加权布局内的视频视图。我需要的宽度是屏幕大小的一个百分比,我需要保持纵横比。这会拉伸视频,因此包装内容
不起作用。维克的回答不适用于这种情况,但@M.Schenk的评论适用。它还保存了一个额外的布局过程。您还应该将其作为可见性的答案发布。对super.onMeasure()
的调用不会简单地覆盖并消除先前对this.setMeasuredDimension()的调用的影响吗?正如@Spinner所提到的,我也很好奇,为什么要调用super.onMeasure()
没有覆盖前面的计算。@jeff=>为什么parentWidth/2???@Leon_SFS:问题是:“整个高度,1/2宽度”PercentRelativeLayout在API级别26.0-beta1中被弃用。你说的“在API级别”是什么意思?你是说图书馆版本号吗?