0

我正在嘗試使LoaderManager列表向後兼容Android 2.1。該列表加載正常,但@ id/android:empty消息顯示即使列表中有清晰可見的項目。ListFragment在列表不爲空時顯示空文本

我已經看過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); 
    } 

} 
+0

呃你是從片段設置活動的內容視圖?!爲什麼? – Eluvatar

+0

它在ListActivity中,但ListActivity與LoaderManager不兼容。 LoaderManager需要使用ListFragment來代替(爲了向後兼容性而使用getSupportLoaderManager時)。我對Android相當陌生。這是否回答你的問題? – TTransmit

+0

是的,你應該看看使用http://developer.android.com/guide/components/fragments.html,我沒有專門使用'ListFragment',但你應該重寫'OnCreateView'並用你的自定義佈局替代因此這就是爲什麼你根本沒有看到你的列表視圖(在頂部添加一個文本視圖,只是試着讓它可見),至於其他的方面呢......我從來沒有使用過LoaderManager,但是如果我看到它需要一個片段。 – Eluvatar

回答

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

+0

刪除getActivity()。setContentView(R.layout.todo_list);當列表中有項目或沒有項目時,空消息都會消失。否則,該應用程序仍然按預期工作。我將再次嘗試使用setEmptyView。 – TTransmit

+0

將此與Eluvatar的答案結合起來。我需要在'onCreateView'中設置佈局充氣器。 – TTransmit

相關問題