fragment嵌套时遇到的两大坑

来源:互联网 发布:linux fdisk分区教程 编辑:程序博客网 时间:2024/06/05 08:12

虽然这两个坑都是我在完成上一篇博客内容时遇到的问题,不过并不是fragment特有的坑,可能在很多别的情况下同样会遇到的坑。所以我把把这一部分单独写成一个博客。

错误一:

Your content must have a ListView whose id attribute is ‘android.R.id.list’

这句话很显然,你应该把你的ListView的id设置为’android.R.id.list’。
下面我们来分析分析代码这是ListFragment的里面重写的onCreate()方法,获取一个View,然后再从View获取一个ListView。返回当前的View。这样整个ListFragment就获取了一个包含ListView的view。
下面的布局文件中 android:id=”@+id/list” 这样定义的ListView的id。

@Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        View view = inflater.inflate(R.layout.task_list,container);        listView = (ListView)view.findViewById(R.id.list);        return view;    }
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent">    <TextView        android:text="@string/hello_world"        android:textSize="@dimen/text_size_24"        android:layout_width="fill_parent"        android:layout_height="wrap_content" />    <!--android:id="@id/android:list"-->    <ListView        android:id="@+id/list"        android:layout_width="fill_parent"        android:layout_height="wrap_content"/></LinearLayout>

通过错误表达的意思,显然问题出在这里,我们应当用:android:id=”@id/android:list” 来定义ListView的id。
那么,我们就照这样改。改完之后,发现
listView = (ListView)view.findViewById(R.id.list);
这里也在报错,并且怎么改后面的id,都获取不到。
后来才知道:ListView的Id为固定不变的,为"@id/android:list“,ListActivity会根据id自动查找ListView引用;在 Activity 中使用 setListAdapter(adapter); 时就默认设置到了这个list上。如果按一般控件的写法
<ListView android:id="@+id/myListView" …… />
则需要 findViewById 先得到控件对像,再调用对像的 setListAdapter(adapter);
这里第一个问题就解决了。

错误二:

The specified child already has a parent. You must call removeView() on the child’s parent first.

指定的子类已经有父节点,需要先在父节点上remove掉。
我这里出现问题的代码如下:

@Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        View view = inflater.inflate(R.layout.task_list,container);        return view;    }

这里主要是因为
inflater.inflate(R.layout.task_list,container);
我们查看LayoutInflater这个对象的API文档:API(需翻墙)。通过文档我们只看到该对象有三种不同参数的inflate方法:
这里写图片描述
四种方法都返回一个View对象。
我们首先注意第一个参数,如果一int型传递xml文件信息的有两个,另外两个通过XmlPullParser对象传递xml文件信息。
我们一般采用的是int的方式,接下来我们观察后面的参数描述,
这里写图片描述
这里写图片描述
通过参数描述不难看出,第二个参数表示的是返回view的root。很接近我们的解决方案了,我们只需要把第二个参数设定为null,就可以解决我们遇到的问题啦。这样返回的view就不会有root节点啦,也就不会报错了。

到这里我们的问题已经解决了,但是我们再看看最后一个从参数的描述,
Whether the inflated hierarchy should be attached to the root parameter? If false, root is only used to create the correct subclass of LayoutParams for the root view in the XML.
显然,我们在第二个参数不为null时,同样可以解决这个问题,这要我们调用后一个方法,并且将参数设为false即可。通过实践,两种方式都是可以解决这个问题的。

总结

通过第二个问题的分析,我们了解一些使用Android API的方法。这也说明,写程序是完全确定的过程,是讲究逻辑的。我们应当有刨根问底的精神,总是能找到出现问题的原因,并且想出解决的办法的。

0 0
原创粉丝点击