【问题标题】:Fragment disappears after setAdapter on ListViewListView 上的 setAdapter 后片段消失
【发布时间】:2014-09-30 08:20:09
【问题描述】:

我在一个包含其他 UI 元素的片段中有一个 ListView。一切正常,直到我在 ListView 上调用 setAdapter。在那一刻,我可以调试 ListView 填充了元素,但在整个片段消失后立即(包括其他 UI 元素)。如果我在 0.1 秒后设置适配器,一切正常。

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    mView = inflater.inflate(R.layout.fragment_listview, null);
    mListView = (ListView)mView.findViewById(R.id.list_items);

    TextView emptyView = (TextView)mView.findViewById(R.id.text_empty);
    mListView.setEmptyView(emptyView);

    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            // this is the only work around to not make the list view disappear
            loadContacts();
        }
    }, 100);
    // if I call loadContacts() here, the Fragment disappears

    mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Person p = mContacts.get(position);
            if (pickerInterface != null) {
                pickerInterface.pickedContact(p);
            }
        }
    });
    return mView;
}


public void loadContacts() {
    mContacts = ContactsDataSource.getAllPhoneContacts(getActivity(), true);
    mAdapter = new ContactsAdapter(getActivity());
    mAdapter.mContacts = mContacts;
    mAdapter.isPlainList = true;
    // after the following line the Fragment is filled and then immediately disappears
    mListView.setAdapter(mAdapter);
}

ContactsAdapter 非常简单:

public class ContactsAdapter extends BaseAdapter {
    public List<Person> mContacts = new ArrayList<Person>();
    public Activity context;

    // Constructor
    public ContactsAdapter(Activity c){
        context = c;
    }

    @Override
    public int getCount() {
        return mContacts.size();
    }

    public Person getItem(int position){
        return mContacts.get(position);
    }

    @Override
    public boolean isEmpty()
    {
        return mContacts.size() == 0;
    }

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

    @SuppressLint("InflateParams")
    public View getView(int position, View convertView, ViewGroup viewGroup) {
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.list_item_contact, null);
        }
        Person person = mContacts.get(position);

        TextView tvName = (TextView) convertView.findViewById(R.id.text_name);
        tvName.setText(person.getDisplayName());
        return convertView;
    }
}

我花了好几个小时调试和寻找原因,却一无所知。感谢您的任何想法。

编辑: XML 如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white" >

    <ListView
        android:id="@+id/list_items"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/line_horizontal"
        android:layout_alignParentTop="true" />

    <TextView
        android:id="@+id/text_empty"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:padding="15dp"
        android:layout_alignParentTop="true"
        android:text="@string/label_no_entries"
        android:textColor="@color/grey"
        android:textSize="21sp" />

    <View
        android:id="@+id/line_horizontal"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_above="@+id/layout_navigation"
        android:background="@color/black" />

    <RelativeLayout
        android:id="@+id/layout_navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true" >

        <TextView
            android:id="@+id/text_scrollback"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:drawablePadding="10dp"
            android:drawableRight="@drawable/backward"
            android:gravity="center_vertical"
            android:paddingBottom="15dp"
            android:paddingLeft="10dp"
            android:paddingTop="15dp"
            android:text="@string/activity_contacts_backward_label"
            android:textColor="@color/mediumgrey" />

        <View
            android:id="@+id/view_coverback"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/text_scrollback"
            android:layout_alignParentLeft="true"
            android:layout_alignRight="@+id/text_scrollback"
            android:layout_alignTop="@+id/text_scrollback"
            android:background="#c0ffffff" />

        <TextView
            android:id="@+id/text_scrollforward"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:drawableLeft="@drawable/forward"
            android:drawablePadding="10dp"
            android:gravity="center_vertical"
            android:paddingBottom="15dp"
            android:paddingRight="10dp"
            android:paddingTop="15dp"
            android:text="@string/activity_contacts_forward_label"
            android:textColor="@color/mediumgrey" />

        <View
            android:id="@+id/view_coverforward"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/text_scrollforward"
            android:layout_alignParentRight="true"
            android:layout_alignLeft="@+id/text_scrollforward"
            android:layout_alignTop="@+id/text_scrollforward"
            android:background="#c0ffffff" />

        <TextView
            android:id="@+id/text_pages"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/text_scrollforward"
            android:layout_toLeftOf="@+id/text_scrollforward"
            android:layout_toRightOf="@+id/text_scrollback"
            android:gravity="center"
            android:textColor="@color/mediumgrey"
            android:textSize="17sp" />
    </RelativeLayout>

</RelativeLayout>

【问题讨论】:

  • 你可以放你的xml代码...
  • 我已经在上面添加了
  • 很难猜,你需要发布完整的代码。例如。我没有看到你从哪里得到 mListView?如果您直接扩展 Fragment 超级调用什么都不做等等......没有重现上述行为的代码,这只是疯狂的猜测。
  • 对不起,这部分我也应该贴的。 SuperClass 也是一个自定义类,它只是初始化了我在其他片段中使用的标准布局。一切都在 onCreateView 中完成。我已经相应地更改了上面的代码。
  • @Christian,您已将 match_parent 设置为宽度和高度。当列表为空时,您可以看到其他内容,但是当您的列表更新时,它占据了您的完整视图。只是为了检查在 listview 中添加 layout_below="@+id/layout_navigation" 。

标签: android listview android-fragments android-listview baseadapter


【解决方案1】:

你在哪里初始化你的“mListView”? 片段膨胀的时间是“onCreateView()”,从布局中获取视图实例的一般方法是在这个方法上完成的。如下所示

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  View v = inflater.inflate(R.layout.fragment_one, null);
  mListView = (ListView)v.findViewById(R.id.list_items);
  ...
  return v;
}

尝试在“onCreateView”中初始化您的视图(ListViews 和其他)怎么样? 我认为问题是在片段膨胀之前获取视图实例引起的。

【讨论】:

  • 是的,我在自定义超类中做到了。很抱歉没有包含这部分代码。我已经更改了上面的代码。
  • 值得一提,但不是原因,请参阅我的回答,但至少是我的支持
【解决方案2】:

不确定您的问题是什么。可能与自定义超类一起使用。否则,在这里疯狂猜测,但尝试像这样夸大你的视图。

mView = inflater.inflate(R.layout.fragment_listview, container, false);

【讨论】:

  • 这不是原因(请参阅下面我的回答),但感谢您的帮助,至少感谢您对有效操作的支持
【解决方案3】:

首先,存储上下文对象可能很危险,因此应尽可能避免...您可以通过以下步骤在适配器中轻松摆脱它(希望也能解决您的问题):

--> 为您的适配器尝试以下构造函数:

public ContactsAdapter(Context c){
    super(c, R.layout.yourlayout_listitem_name;
}

--> 并调整 getView 方法以使用类似:

final View rowView = View.inflate(viewGroup.getContext(), R.layout.yourlayout_listitem_name, null);

而不是inflater-if-block。然后总是在最后return rowView

只是为了确保我会删除覆盖方法:

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

因为它没有做任何有用的事情;-)

【讨论】:

  • 谢谢你,我试过你提到的,但结果一样。我将BaseAdapter 更改为ArrayAdapter(因为BaseAdapter 没有super(Context, int)。使用您的getView-方法,我每次都会在getView? 被调用时膨胀一个视图?无论如何,在再次更改后片段消失了完全在setAdapter()之后
  • 如果您在 Fragment 中工作,您是否尝试过另一个钩子?像 onViewCreated
  • 是的,我试过onResume和onStart,onViewCreated是不可能的,我必须支持API-Level 9
  • 不要切换到ArrayAdapter,您与BaseAdapter保持一致是正确的。将Context 存储在适配器中是非常好的,因为适配器的生命周期将随着活动而终止。保留 if 块。您不想在每次 getView 调用时重新膨胀视图
【解决方案4】:

感谢大家的支持。通过删除所有代码并逐步重新组装,我找到了原因。以防万一有一天有人遇到同样的问题。

我在超类中声明的ListView 上有一个OnScrollListener。在 OnScrollListener 中,我使用 Visibility.GONE 按需隐藏导航箭头。即使 NavigationArrows 不影响 ListView 的布局,这也是问题所在。通过设置 Visibility.INVISIBLE 一切正常。我想这与整个布局的一些重新绘制问题有关,这些问题不起作用。

【讨论】:

    猜你喜欢
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-29
    • 1970-01-01
    相关资源
    最近更新 更多