【问题标题】:ListFragment shows empty text when the list is not empty当列表不为空时,ListFragment 显示空文本
【发布时间】:2013-09-30 17:12:21
【问题描述】:

我正在尝试使 LoaderManager 列表向后兼容 Android 2.1。列表加载正常,但即使列表中有项目清晰可见,@id/android:empty 消息也会显示。

我在 StackOverflow 上查看了许多使用 setEmptyView() 和 setEmptyText() 但无法让它们工作的解决方案。

这是 ListFragment 的代码。我一直在组合来自各种http://www.vogella.com/ 教程的代码。

package com.example.contentprov;

import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;

import com.example.contentprov.data.MyTodoContentProvider;
import com.example.contentprov.data.TodoTable;

/*
 * TodosOverviewActivity displays the existing todo items
 * in a list
 * 
 * You can create new ones via the ActionBar entry "Insert"
 * You can delete existing ones via a long press on the item
 */

public class TodoOverviewFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<Cursor>, OnItemClickListener {
    private SimpleCursorAdapter adapter;

    /** Called when the activity is first created. */

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getActivity().setContentView(R.layout.todo_list);
        fillData();
    }

    // Opens the second activity if an entry is clicked
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        Intent i = new Intent(getActivity(), TodoDetailActivity.class);
        Uri todoUri = Uri.parse(MyTodoContentProvider.CONTENT_URI + "/" + id);
        i.putExtra(MyTodoContentProvider.CONTENT_ITEM_TYPE, todoUri);
        startActivity(i);
    }

    private void fillData() {

        // Fields from the database (projection)
        // Must include the _id column for the adapter to work
        String[] from = new String[] { TodoTable.COLUMN_SUMMARY };
        // Fields on the UI to which we map
        int[] to = new int[] { R.id.label };

        getActivity().getSupportLoaderManager().initLoader(0, null, this);
        adapter = new SimpleCursorAdapter(getActivity(), R.layout.todo_row, null, from,
                to, 0);

        setListAdapter(adapter);
    }

    // Creates a new loader after the initLoader () call
    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        String[] projection = { TodoTable.COLUMN_ID, TodoTable.COLUMN_SUMMARY };
        CursorLoader cursorLoader = new CursorLoader(getActivity(),
                MyTodoContentProvider.CONTENT_URI, projection, null, null, null);
        return cursorLoader;
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        adapter.swapCursor(data);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        // data is not available anymore, delete reference
        adapter.swapCursor(null);
    }

    @Override
    public void onItemClick(AdapterView<?> l, View v, int position, long id) {
        Intent i = new Intent(getActivity(), TodoDetailActivity.class);
        Uri todoUri = Uri.parse(MyTodoContentProvider.CONTENT_URI + "/" + id);
        i.putExtra(MyTodoContentProvider.CONTENT_ITEM_TYPE, todoUri);

        startActivity(i);
    }

} 

这是列表的 XML 文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <ListView
        android:id="@id/android:list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

    <TextView
        android:id="@id/android:empty"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/no_todos" />

</LinearLayout> 

编辑:解决方案是结合 Eluvatar 和 dymmeh 的答案。这是 ListFragment 的新版本。

package com.example.contentprov;

import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;

import com.example.contentprov.data.MyTodoContentProvider;
import com.example.contentprov.data.TodoTable;

/*
 * TodosOverviewActivity displays the existing todo items
 * in a list
 * 
 * You can create new ones via the ActionBar entry "Insert"
 * You can delete existing ones via a long press on the item
 */

public class TodoOverviewFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<Cursor>, OnItemClickListener {
    private SimpleCursorAdapter adapter;

    /** Called when the activity is first created. */

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        fillData();
    }

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

    // Opens the second activity if an entry is clicked
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        Intent i = new Intent(getActivity(), TodoDetailActivity.class);
        Uri todoUri = Uri.parse(MyTodoContentProvider.CONTENT_URI + "/" + id);
        i.putExtra(MyTodoContentProvider.CONTENT_ITEM_TYPE, todoUri);
        startActivity(i);
    }

    private void fillData() {

        // Fields from the database (projection)
        // Must include the _id column for the adapter to work
        String[] from = new String[] { TodoTable.COLUMN_SUMMARY };
        // Fields on the UI to which we map
        int[] to = new int[] { R.id.label };

        getActivity().getSupportLoaderManager().initLoader(0, null, this);
        adapter = new SimpleCursorAdapter(getActivity(), R.layout.todo_row, null, from,
                to, 0);

        setListAdapter(adapter);
    }

    // Creates a new loader after the initLoader () call
    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        String[] projection = { TodoTable.COLUMN_ID, TodoTable.COLUMN_SUMMARY };
        CursorLoader cursorLoader = new CursorLoader(getActivity(),
                MyTodoContentProvider.CONTENT_URI, projection, null, null, null);
        return cursorLoader;
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        adapter.swapCursor(data);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        // data is not available anymore, delete reference
        adapter.swapCursor(null);
    }

    @Override
    public void onItemClick(AdapterView<?> l, View v, int position, long id) {
        Intent i = new Intent(getActivity(), TodoDetailActivity.class);
        Uri todoUri = Uri.parse(MyTodoContentProvider.CONTENT_URI + "/" + id);
        i.putExtra(MyTodoContentProvider.CONTENT_ITEM_TYPE, todoUri);

        startActivity(i);
    }

} 

【问题讨论】:

  • 呃,您正在从片段中设置活动的内容视图?!为什么?
  • 它在 ListActivity 中,但 ListActivity 与 LoaderManager 不兼容。 LoaderManager 需要使用 ListFragment 来代替(当使用 getSupportLoaderManager 以实现向后兼容性时)。我对Android相当陌生。这能回答你的问题吗?
  • 是的,你应该看看使用developer.android.com/guide/components/fragments.html,我没有专门使用ListFragment,但你应该覆盖OnCreateView并在那里替换你的自定义布局,因为这就是你不使用的原因完全看到您的列表视图(在顶部添加一个文本视图并尝试使其可见),至于其余部分......我从未使用过 LoaderManager 但如果它需要一个片段,我会感到惊讶。跨度>
  • 我确实看到了列表视图。它只是出现在“TextView”中空消息的顶部。我会看一下片段指南。我在另一个线程中看到了“OnCreateView”,还没有尝试使用它。
  • 使用onCreateView 定义要使用的布局。非常感谢。

标签: java android android-listview android-listfragment android-loadermanager


【解决方案1】:

通过调用getActivity().setContentView(R.layout.todo_list);,您是在告诉您的活动显示ListView 和一个空的TextView。您的 ListFragment 已经包含一个自动为您管理的 ListView 和空的 TextView。因此,您正在做的是从您的todo_list 布局中显示一个单独的ListView,然后修改包含在您的ListFragment 中的ListView(这就是为什么看起来没有任何内容加载到您的ListView 中的原因)。如果您只是删除对getActivity().setContentView(R.layout.todo_list); 的调用,只要您正确添加ListFragment,它就应该可以工作。

【讨论】:

  • 移除 getActivity().setContentView(R.layout.todo_list);当列表中有项目或没有项目时,空消息都会消失。否则,该应用程序仍按预期工作。我会再次尝试使用 setEmptyView。
  • 将此与 Eluvatar 的答案相结合有效。我需要设置要在onCreateView 中使用的布局充气器。
猜你喜欢
  • 1970-01-01
  • 2020-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多