7

我创建了一个简单的应用程序来说明在 SDK 17 和 SDK 18 之间包装在 RelativeLayout 中时 LinearLayout 的行为方式的变化。首先,屏幕截图:

当 targetSdkVersion 为“17”时:

在此处输入图像描述

当 targetSdkVersion 为“18”时:

在此处输入图像描述

此活动的布局是:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00ffff"
    android:orientation="vertical" >

    <include layout="@layout/test_list_item"/>

    <ListView
        android:id="@+id/listview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:overScrollMode="never"
        android:scrollingCache="false" >
    </ListView>

</LinearLayout>

text_list_item.xml 是:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#ff0000" >

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:background="#ffff00"
        android:padding="10dp"
        android:text="foobar"
        android:textColor="#000000" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignBottom="@id/text"
        android:layout_alignTop="@id/text"
        android:background="#00ff00"
        android:orientation="horizontal"
        android:weightSum="1.0" >

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.5"
            android:background="#0000ff" />
    </LinearLayout>

</RelativeLayout>

活动的 onCreate() 如下所示:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test);
    findViewById(R.id.text).bringToFront();
    final ListView mListView = (ListView) findViewById(R.id.listview);
    mListView.setAdapter(new TestAdapter());
}

TestAdapter 看起来像这样:

public class TestAdapter extends BaseAdapter {

    private static final int COUNT = 3;

    @Override
    public int getCount() {
        return COUNT;
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public boolean areAllItemsEnabled() {
        return true;
    }

    @Override
    public boolean isEnabled(int position) {
        return false;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.test_list_item, null);
        view.findViewById(R.id.text).bringToFront();
        return view;
    }

当 target = 17 时,LinearLayout 的子视图在位于 ListView 内部和在 ListView 外部时都被正确调整为可用宽度的 50%。当 target = 18 用作列表项的布局时,它不会调整大小。在这种情况下,它的宽度保持在“0dp”并且永远不会调整大小。

理想情况下,我希望以 SDK 19 为目标。不过,为了做到这一点,我以某种方式适应这种行为变化。关于如何实现的任何想法?

顺便说一句,布局如此复杂和“怪异”是有原因的;我意识到有更直接的方法可以实现这种特殊的视觉效果。

编辑

提供更多关于我为什么使用这种病态布局的信息:它用于“仪表”。LinearLayout 中的 View 使用 ScaleAnimation 进行拉伸或收缩,使其占据总可用宽度的所需百分比。棘手的是我需要在仪表顶部覆盖文本,并且我希望仪表的高度由文本确定。

因此,外部的 RelativeLayout 应该“与其父级一样宽”,但只能“与其包含的 TextView 一样高”。该 RelativeLayout 内部的 LinearLayout 应该与其父级一样宽和高。LinearLayout 中的 View 应该和包含它的 LinearLayout 一样高,但只有一半宽。

这正是我在针对 SDK 17和/或在 SDK 18+ 中当布局不用作 ListView item 的内容时得到的行为。

编辑

发布到开发者群:

https://groups.google.com/forum/#!msg/android-developers/KuoY5Tklyms/TbNq6ndD_PwJ

4

3 回答 3

4

改变

final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.test_list_item, null);

至:

final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.test_list_item, parent, false);

我想你会有更好的运气。


更新

好吧,这就是我可以告诉你的。

如果您启动 Hierarchy View,您将看到您View提供的蓝色背景在“内部 ListView”场景中的高度为 0。根据您问题的其他答案,宽度是正确的,这表明问题与重量无关。

如果您查看的源代码RelativeLayoutandroid:targetSdkVersion,他们确实在17 与 18+之间的分界线上添加了一些改变行为的智能。我的猜测是你绊倒了mAllowBrokenMeasureSpecs,在某些与ListView容器相关的情况下,但这只是一个猜测。当它是一个简单的容器时,我有足够的时间去摸索容器的所有布局/测量东西,我写的,当我睡了一整夜时——理解RelativeLayout有限的睡眠超出了我的能力。我已经戳了戳你的样本,尝试了各种方法,看看它们是否能解决问题,但没有结果。

关于你在我戳这个时发布的编辑:

  • 原则上,您不需要基本布局是RelativeLayout. AFrameLayout应该也可以,因为您需要做的就是能够在 Z 轴上堆叠东西并能够使您的标签居中。话虽如此,当我沿着这条路走下去时,我得到了更奇怪的结果,尽管这些结果似乎与 无关targetSdkVersion,所以我可能只是在某个地方搞砸了

  • 即使你坚持使用RelativeLayout,你也不应该需要LinearLayout。在运行时,你知道你的宽度,所以你应该动画仪表的宽度,而不是它的重量。因此,只需ViewRelativeLayout(or FrameLayout) 中加上 be 就足够了。

但我会欣然同意这是一种奇怪的行为。

于 2014-01-29T21:58:43.093 回答
1

看起来因为它只是一个视图并且不需要渲染任何东西,所以为了优化,一些测量方法被跳过了。将 View 更改为 TextView 并设置一些文本,您会看到它确实按预期显示。我确实了解 LinearLayout 以不同方式呈现视图(不确定那是正确的还是 ListView 是正确的)

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ff0000" >

<TextView
    android:id="@+id/text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:background="#ffff00"
    android:padding="10dp"
    android:text="foobar"
    android:textColor="#000000" />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_alignBottom="@id/text"
    android:layout_alignTop="@id/text"
    android:background="#00ff00"
    android:orientation="horizontal"
    android:weightSum="1.0" >

    <TextView
        android:id="@+id/testView"
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:layout_weight="0.5"
        android:background="#0000ff"
        android:singleLine="false" />
</LinearLayout>

 @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.text_list_item, null);

        view.findViewById(R.id.text).bringToFront();
        TextView testView = (TextView)view.findViewById(R.id.testView);
        testView.setText("some test text for viewNo:"+String.valueOf(position));

        return view;
    }

在此处输入图像描述

于 2014-02-07T21:05:10.390 回答
0

我认为使用方式layout_weight(尝试int numbers> = 0)改变了。与android:layout_width="0dp"(try match_parent) 结合使用会更加不稳定。

该参数的另一个问题weight是,某些设备处理它的方式与其他设备不同。

一般来说,我建议只使用 LinearLayouts,如果可能的话不要使用权重。你可以用gravity(例如gravity="center"),做同样的事情layout_gravity,但它可以节省工作。paddingmargin

编辑 - 示例1:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#ff0000" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#00ff00"
        android:orientation="horizontal">

        <View
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="#0000ff" />

        <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:background="#ffff00"
            android:padding="10dp"
            android:text="foobar"
            android:textColor="#000000" />

        <View
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="#00ff00" />
    </LinearLayout>

</LinearLayout>

示例2:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#ff0000" >

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:background="#ffff00"
        android:padding="10dp"
        android:text="foobar"
        android:textColor="#000000" />

</LinearLayout>
于 2014-01-30T01:20:37.873 回答