尝试以编程方式添加 RelativeLayout,但似乎不在屏幕上或太大

Trying to add a RelativeLayout programmatically but seems like it's off screen or too big

我有一个 xml 用于屏幕,我在顶部有一个带有搜索条件列表的微调器,旁边有一个按钮(这就是我所说的控制区域),每次按下时,将添加一组视图以进行额外搜索。该组包含另一个微调器,用户将在其中指定运算符(AND、OR)、一个带有搜索条件标题的文本框和一个用户将在其中放置输入的编辑文本(这就是我所说的过滤区域)。这将用于稍后为数据库搜索构建搜索查询。

下面的 xml 是我目前为止对一个组进行硬编码的内容,因此我可以显示我以编程方式添加的内容。

<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:fillViewport="true"> <!--IMPORTANT otherwise backgrnd img. will not fill the whole screen -->

    <RelativeLayout
        android:id="@+id/searchLayout"
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:context="com.kadis.materialref.Search">

        <Spinner
            android:id="@+id/attributeSelector"
            android:layout_width="wrap_content"
            android:layout_height="@dimen/controlElementHeight"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"/>

        <Button
            android:id="@+id/addAttributeButton"
            android:layout_width="@dimen/controlElementHeight"
            android:layout_height="@dimen/controlElementHeight"
            android:layout_alignParentEnd="true"
            android:layout_alignParentRight="true"
            android:layout_toRightOf="@+id/attributeSelector"
            android:layout_toEndOf="@+id/attributeSelector"
            android:onClick="addSearchCondition"
            android:text="@string/addSearchAttributeString"/>

        <View
            android:id="@+id/dividerControl1"
            style="@style/Divider"
            android:layout_below="@+id/attributeSelector"/>

        <View
            android:id="@+id/dividerControl2"
            style="@style/Divider"
            android:layout_below="@+id/dividerControl1"/>

        <RelativeLayout
            android:layout_width="match_parent"
            android:id="@+id/FilterArea0"
            android:layout_height="@dimen/controlElementHeight"
            android:layout_below="@+id/dividerControl2"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true">

                <Spinner
                    android:id="@+id/filterOperator0"
                    android:layout_width="@dimen/controlElementHeight"
                    android:layout_height="match_parent"
                    android:layout_alignParentLeft="true"
                    android:layout_alignParentStart="true"/>

                <TextView
                    style="@style/SearchFormTitle"
                    android:id="@+id/filterTitle0"
                    android:text="@string/column1"
                    android:layout_toRightOf="@id/filterOperator0"
                    android:layout_toEndOf="@id/filterOperator0"
                    android:layout_alignParentEnd="true"
                    android:layout_alignParentRight="true"/>

                <EditText
                    style="@style/SearchFormFieldText"
                    android:layout_below="@+id/filterTitle0"
                    android:layout_toRightOf="@id/filterOperator0"
                    android:layout_toEndOf="@id/filterOperator0"
                    android:layout_alignParentEnd="true"
                    android:layout_alignParentRight="true"/>

        </RelativeLayout>
    </RelativeLayout>
</ScrollView>

画面是这样的

按下按钮添加另一个过滤区域时调用的函数如下。函数 generateViewId 与 API 17 后相同,我只是将它添加到 class 中 for API < 17.

public void addSearchCondition(View view)
{
    // Get selection from spinner in control area; the attribute to add in the search conditions.
    Spinner attributeSelector = (Spinner) findViewById(R.id.attributeSelector);
    String attributeSelected = attributeSelector.getSelectedItem().toString();

    // Get layout where I will add stuff.
    RelativeLayout searchLayout = (RelativeLayout) findViewById(R.id.searchLayout);

    // Get last id of the last child so we know under which to add the new layout
    int bottomChildId = searchLayout.getChildAt(searchLayout.getChildCount()-1).getId();

    //
    // New Relative Layout to be added.
    //
    RelativeLayout filterLayout = new RelativeLayout(this);
    filterLayout.setId(generateViewId());
    // Define width and height parameters.
    RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(
            RelativeLayout.LayoutParams.MATCH_PARENT,
            R.dimen.controlElementHeight);
    // Define position
    rlp.addRule(RelativeLayout.BELOW, bottomChildId);
    rlp.addRule(RelativeLayout.ALIGN_PARENT_START);
    rlp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
    filterLayout.setLayoutParams(rlp);

    //
    // Add the operator spinner.
    //
    Spinner operatorSpinner = new Spinner(this);
    operatorSpinner.setId(Search.generateViewId());
    // Get the options for the spinner.
    String[] operators = getResources().getStringArray(R.array.operators);
    // Add items on the spinner.
    ArrayAdapter<String> spinnerArrayAdapter =
            new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, operators);
    spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    operatorSpinner.setAdapter(spinnerArrayAdapter);
    // Define width and height parameters.
    RelativeLayout.LayoutParams rlpSp = new RelativeLayout.LayoutParams(
            R.dimen.controlElementHeight,
            R.dimen.controlElementHeight);
    // Define position
    rlpSp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
    rlpSp.addRule(RelativeLayout.ALIGN_PARENT_START);
    // Set layout parameters
    operatorSpinner.setLayoutParams(rlpSp);
    // Add spinner on the layout
    filterLayout.addView(operatorSpinner);

    //
    // Add a text view as the title
    //
    final TextView tv = (TextView)getLayoutInflater().inflate(R.layout.search_attribute_title, null);
    tv.setId(Search.generateViewId());
    // Set text to display
    tv.setText(attributeSelected);
    // Define width and height parameters.
    RelativeLayout.LayoutParams rlpTV = new RelativeLayout.LayoutParams(
            RelativeLayout.LayoutParams.WRAP_CONTENT,
            RelativeLayout.LayoutParams.WRAP_CONTENT);
    // Define position
    rlpTV.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
    rlpTV.addRule(RelativeLayout.ALIGN_PARENT_END);
    rlpTV.addRule(RelativeLayout.RIGHT_OF, operatorSpinner.getId());
    rlpTV.addRule(RelativeLayout.END_OF, operatorSpinner.getId());
    // Set layout parameters
    tv.setLayoutParams(rlpTV);
    // Add spinner on the layout
    filterLayout.addView(tv);

    // Add an Edit Text as the placeholder for the user input
    final EditText et = (EditText)getLayoutInflater().inflate(R.layout.search_attribute_input, null);
    et.setId(Search.generateViewId());
    // Set text to display
    et.setText(attributeSelected);
    // Define width and height parameters.
    RelativeLayout.LayoutParams rlpET = new RelativeLayout.LayoutParams(
            RelativeLayout.LayoutParams.WRAP_CONTENT,
            RelativeLayout.LayoutParams.WRAP_CONTENT);
    // Define position
    rlpET.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
    rlpET.addRule(RelativeLayout.ALIGN_PARENT_END);
    rlpET.addRule(RelativeLayout.RIGHT_OF, operatorSpinner.getId());
    rlpET.addRule(RelativeLayout.END_OF, operatorSpinner.getId());
    rlpET.addRule(RelativeLayout.BELOW, tv.getId());
    // Set layout parameters
    et.setLayoutParams(rlpET);
    // Add spinner on the layout
    filterLayout.addView(et);

    // Adding the whole filter layout to the search layout (whole screen)
    searchLayout.addView(filterLayout);
}

我不确定问题是否出在 textView 和 editText 的 LayoutParameters 但要添加规则我必须有 LayoutParameters 并且我必须传递一些参数。也许我应该通过 wrap_content 因为在 xml 硬编码中我没有通过它们?

我已调试并创建并添加了布局。 id 已生成,当我在屏幕上按下时,硬编码 xml 下方的白色 space 反应就像是带有操作员选择的微调器。所以我猜尺寸可能出了问题? 按下按钮后,过滤区域为 "added" 如果我按下应该是微调器的白色区域(带有运算符),则会触发

为了以防万一

,我目前的尺寸定义如下
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>

    <!-- Fonts sizes -->
    <dimen name="titleBig">48sp</dimen>
    <dimen name="titleMed">36sp</dimen>
    <dimen name="titleSmall">24sp</dimen>
    <dimen name="searchTitle">10sp</dimen>
    <dimen name="searchField">15sp</dimen>

    <!-- Padding -->
    <dimen name="titlePadding">20dp</dimen>

    <!-- Element heights -->
    <dimen name="controlElementHeight">40dp</dimen>

此外,当我在具有属性(搜索过滤器)的微调器中选择另一个选项时,按钮消失了,我认为它被推到了屏幕右侧?我该如何解决?

所以在为 RelativeLayout 创建 LayoutParams 的代码中:

RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(
        RelativeLayout.LayoutParams.MATCH_PARENT,
        R.dimen.controlElementHeight);

您实际上并没有将维度作为高度传递,而是传递了该维度资源的唯一标识符。如果您为您的项目打开 R.java 并搜索 controlElementHeight,您实际上可以看到该值。所以你可能传递了一个巨大的整数值作为高度,因为 ID 是像 0x7f0a0047.

这样的值

你真正想要的是这样的:

RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(
                RelativeLayout.LayoutParams.MATCH_PARENT,
                getResources().getDimensionPixelSize( R.dimen.controlElementHeight) );

这将请求已定义维度资源的实际值,按设备的屏幕密度缩放。