ScrollView溢出其FrameLayout父级 [英] ScrollView overflowing its FrameLayout parent
问题描述
我有一个复杂的LinearLayout
(垂直),其中FrameLayout
在其他内容上方(TextView
和EditText
框). FrameLayout
包含两件事:a)地图和b)包含半透明的LinearLayout
的ScrollView
,该半透明的LinearLayout
覆盖"地图. ScrollView最初是GONE
,但我以编程方式使其可见.我还以编程方式将视图添加到嵌入在ScrollView
中的LinearLayout
中.
I have a complicated LinearLayout
(vertical) with a FrameLayout
above some other stuff (a TextView
and an EditText
box). The FrameLayout
contains two things: a) a map and b) a ScrollView
containing a semi-transparent LinearLayout
that 'overlays' the map. The ScrollView is initially GONE
, but I render it visible programmatically. I also programmatically add Views into the LinearLayout
embedded in the ScrollView
.
使用onMeasure()
设置FrameLayout的尺寸,以使高度和宽度相等.这使得FrameLayout
占据了设备屏幕的顶部,而TextView
和EditText
则位于下面.
The FrameLayout dimensions are set using onMeasure()
so that the height and width are equal. This make the FrameLayout
take up the top portion of the device screen while the TextView
and EditText
fit below.
public static class MyFrameLayout extends FrameLayout {
public FrameLayoutWithMap(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onMeasure(int widthSpec, int heightSpec) {
super.onMeasure(widthSpec, heightSpec);
int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
setMeasuredDimension(size, size);
}
}
一切从一开始就很有效.但是,当我向嵌入在ScrollView
中的LinearLayout
中添加足够的视图时,ScrollView最终将在FrameLayout
下面的TextView
中后面处扩展.换句话说,ScrollView溢出其FrameLayout
父级,然后将其底部隐藏.当我继续将视图添加到ScrollView
中嵌入的LinearLayout
中时,ScrollView
最终将开始滚动.一旦ScrollView
是设备屏幕的高度,就好像发生了这种情况.
Everything actually works great in the beginning. However, when I add enough Views to the LinearLayout
embedded in the ScrollView
the ScrollView will eventually extend behind the TextView
below the FrameLayout
. In other words, the ScrollView overflows its FrameLayout
parent, the bottom of which is then hidden. As I continue to add Views to the LinearLayout
embedded in the ScrollView
the ScrollView
will eventually start scrolling. It appears as though this happens once the ScrollView
is the height of the device screen.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activityRoot"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#323232"
tools:context=".MainActivity" >
<FrameLayout
class="com.myapp.main.MyFrameLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#070707" >
<com.myapp.main.MapView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ScrollView
android:id="@+id/overlayScrollView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:layout_gravity="left"
android:scrollbars="vertical"
android:fillViewport="false"
android:visibility="gone" >
<LinearLayout
android:id="@+id/overlayLinearLayout"
android:orientation="vertical"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:padding="1dp"
android:background="#AA000000" >
</LinearLayout>
</ScrollView>
</FrameLayout>
<TextView
android:id="@+id/tvMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="left"
android:textColor="#FFFFFF"
android:textSize="14sp" />
<EditText android:id="@+id/entry"
android:background="@drawable/entry_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lines="1"
android:singleLine="true"
android:textSize="16sp"
android:textColor="#ffffff"
android:hint="@string/entry" />
</LinearLayout>
我想让ScrollView
在其FrameLayout
父级的高度后开始滚动.换句话说,我希望ScrollView
保留在其FrameLayout
父级中包含.
What I would like to happen is for the ScrollView
to start scrolling as soon as it's the height of its FrameLayout
parent. Put another way, I'd like for the ScrollView
to remain contained within its FrameLayout
parent.
你知道我在做什么错吗?
Any idea what I'm doing wrong here?
推荐答案
更新:
新的 ConstraintLayout 库为您提供了细粒度控制您的视图相对于父视图和其他视图的大小.它还支持长宽比,因此您可以(例如)强制视图始终为正方形.
The new ConstraintLayout library gives you fine-grained control of how your views are sized in relation to the parent and to other views. It also supports aspect ratios, so you can (for instance) force a view to always be square.
原始回复:
问题在于您如何测量特殊的FrameLayout.当您调用super.onMeasure()
时,此视图及其所有子视图将根据给定的度量规范对其进行度量.在那之后,您限制了该视图的尺寸,但是它的所有子视图都没有意识到.只有该视图及其 parent 知道这一点.它的孩子已经测量出自己的想法,认为此视图的大小不受您对setMeasuredDimension()
的额外调用所限制.
The problem is how you are measuring your special FrameLayout. When you call super.onMeasure()
, this view and all of its children will measure themselves according to the measure specs given. After that, you constrain the dimensions of this view, but none of its children are aware of this; only this view and its parent are aware of this. Its children have measured themselves thinking the size of this view is not constrained by your extra call to setMeasuredDimension()
.
再次调用super.onMeasure()
将迫使其子级重新测量自己,从而通知他们新的尺寸.
Calling super.onMeasure()
again will force its children to measure themselves again, thereby informing them of the new size.
@Override
public void onMeasure(int widthSpec, int heightSpec) {
super.onMeasure(widthSpec, heightSpec);
int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
int spec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
super.onMeasure(spec, spec);
}
请注意,这将导致此视图及其所有子级在每次测量通过时都进行两倍的测量,因此它可能不是性能最高的方法,但是它将完成您想要的操作.
Note this will cause this view and all its children to measure twice as many times with each measure pass, so it might not be the most performant approach, but it will accomplish what you want.
这篇关于ScrollView溢出其FrameLayout父级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!