使用merge和include标签动态更改UI,具体取决于点击

时间:2011-01-18 15:45:51

标签: android android-layout

我是Android和编程的新手,所以很容易!

我创建了一个 - 可能过于复杂,但它可以实现我想要的 - main.xml与我的布局是这样的:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main_scrollview"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    >
<LinearLayout
    ...
    >
    <TextView  
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:text="@string/title"
        android:gravity="center"
    />
    <TableLayout
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:stretchColumns="0"
        >
        <TableRow>
            <TextView/>
            <Spinner/>
        </TableRow>
        <TableRow>
            <TextView/>
            <Spinner/>
        </TableRow>
    </TableLayout>
    <TableLayout
        android:id="@+id/main_tablelayout2"
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:stretchColumns="*"
        >
        <include
            android:id="@+id/include"
            layout="@layout/price0"
        />
        <TableRow>
            <TextView/>
            <EditText/>
        </TableRow>
    </TableLayout>
</LinearLayout>
</ScrollView>

这是我试图包含的选项之一(price1.xml):

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TableRow>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:text="@string/price1"
        android:gravity="center_vertical"
    />
    <EditText
        android:id="@+id/price1"
    />
</TableRow> 
</merge>

我正在尝试动态更改包含,具体取决于其中一个微调器具有的值,但是我在启动应用时会收到一个强制关闭。

logcat错误是:

01-18 15:31:42.826: ERROR/AndroidRuntime(719): FATAL EXCEPTION: main
01-18 15:31:42.826: ERROR/AndroidRuntime(719): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at android.view.ViewGroup.addViewInner(ViewGroup.java:1976)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at android.view.ViewGroup.addView(ViewGroup.java:1871)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at android.widget.TableLayout.addView(TableLayout.java:421)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at android.view.ViewGroup.addView(ViewGroup.java:1828)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at android.widget.TableLayout.addView(TableLayout.java:403)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at android.view.ViewGroup.addView(ViewGroup.java:1808)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at android.widget.TableLayout.addView(TableLayout.java:394)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at com.kavi.eta.Calculate$1.onItemSelected(Calculate.java:36)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at android.widget.AdapterView.fireOnSelected(AdapterView.java:871)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at android.widget.AdapterView.access$200(AdapterView.java:42)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at android.widget.AdapterView$SelectionNotifier.run(AdapterView.java:837)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at android.os.Handler.handleCallback(Handler.java:587)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at android.os.Handler.dispatchMessage(Handler.java:92)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at android.os.Looper.loop(Looper.java:123)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at android.app.ActivityThread.main(ActivityThread.java:3647)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at java.lang.reflect.Method.invokeNative(Native Method)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at java.lang.reflect.Method.invoke(Method.java:507)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
01-18 15:31:42.826: ERROR/AndroidRuntime(719):     at dalvik.system.NativeStart.main(Native Method)

看起来我正在编写java代码错误,但我无法弄清楚如何正确删除默认包含并将其替换为另一种布局:

public void onItemSelected(AdapterView<?> arg0, View arg1, int position, long id) { 
            int index = formatSpinner.getSelectedItemPosition();
            if (index == 0) {

                TableLayout tl = (TableLayout)findViewById(R.id.main_tablelayout2);
                tl.removeView(findViewById(R.id.include));

                LayoutInflater inflater = getLayoutInflater();
                tl.addView(inflater.inflate(R.layout.price1, tl, true));
            }

对于长篇文章感到抱歉,但我到处搜索,找不到明确的答案。希望这至少能提供一个体面的例子......

3 个答案:

答案 0 :(得分:0)

我也很新,但也许有帮助:

您可以尝试删除尝试。在这种情况下,我不认为这个标签是合适的,因为你不会有两种直接嵌套的同一种布局。 虽然在这种情况下我不希望出现IllegalStateException。

您是否在onCreate()中添加了视图?

答案 1 :(得分:0)

没有真正找到适当的解决方案,但为了完整性,这就是我最终做的事情: 当findViewById用于price1.xml中的任何视图时(即包含xml),我一直得到NullPointerException。这是设计的吗? 这是一个问题,因为我必须根据用户输入动态添加/删除某些视图。

我的main.xml中仍然有一个include标记,我通过查找相对于它的父级的位置来删除(再次,我无法使findViewById工作,但这同样有效)。然后我根据用户输入在其位置充气另一个xml文件。

if (position == 0) {
                    LinearLayout ll = (LinearLayout)findViewById(R.id.main_linearlayout);
                    ll.removeViewAt(3);
                    LayoutInflater inflater = getLayoutInflater();
                    ll.addView(inflater.inflate(R.layout.replacement1, null), 3);

                } else if (position == 1) {
                    LinearLayout ll = (LinearLayout)findViewById(R.id.main_linearlayout);
                    ll.removeViewAt(3);
                    LayoutInflater inflater = getLayoutInflater();
                    ll.addView(inflater.inflate(R.layout.replacement2, null), 3);

我还清理了我的main.xml以删除不必要的布局嵌套并抛弃了合并标记,并使用TableLayout作为我所包含的xml的根标记。 这似乎是我的UI问题排序(现在!)......

答案 2 :(得分:0)

如果您尝试对所包含布局中的元素使用NullPointerException,您将获得findViewById()。它们不在setContentView(View)中添加的布局中,因此您必须在以下代码段中提供include标记和ID,例如includedLayout -

<include android:id="@+id/includedLayout" layout="@layout/yourLayout"/>

使用正常的findViewById()调用

找到它
ViewGroup includedLayout = (ViewGroup)findViewById(R.id.includedLayout);

然后使用此对象查找包含的布局中的视图。

View myVIew = includedLayout.findViewById(R.id.myViewId);

虽然线程已经老了,但我想这个答案会帮助未来的读者准确找到他们布局中发生的事情。