0

Я пытаюсь сделать список LoaderManager обратно совместимым с Android 2.1. Список загружается отлично, но сообщение @ id/android: empty показывает, даже если в списке есть заметки.ListFragment показывает пустой текст, когда список не пуст

Я рассмотрел ряд решений на StackOverflow, которые используют setEmptyView() и setEmptyText(), но не смогли заставить их работать.

Это код для ListRragment. Я комбинировал код из различных 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> 

EDIT: Решение было объединить 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, который управляется автоматически для вас. Итак, что вы делаете, отображается отдельный ListView с вашего макета todo_list, а затем изменяется ListView, содержащийся в вашем ListFragment (вот почему кажется, что ничего не загружается в ваш ListView). Если вы просто удалите вызов до getActivity().setContentView(R.layout.todo_list);, он должен работать до тех пор, пока вы правильно добавляете ListFragment.

+0

Удаление getActivity(). SetContentView (R.layout.todo_list); пустое сообщение исчезает как при наличии элементов в списке, так и без элементов. В противном случае приложение по-прежнему работает так, как ожидалось. Я попробую снова использовать setEmptyView. – TTransmit

+0

Объединив это с ответом Элуватара, он работал. Мне нужно было установить макетный инфлятор для использования в 'onCreateView'. – TTransmit

Смежные вопросы