2012-05-15 5 views
11

По этой ссылке: ListFragment android developersListFragment не принимает мой макет

Я хочу, чтобы установить свой собственный макет для списка, но это делает исключение.

Вот код:

public class ListFragmentActivity extends FragmentActivity { 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    // TODO Auto-generated method stub 
    super.onCreate(savedInstanceState); 
    FragmentManager fm = getSupportFragmentManager(); 
    if(fm.findFragmentById(android.R.id.content) == null) 
    { 
     myListFragments list = new myListFragments(); 
     fm.beginTransaction().add(android.R.id.content, list).commit(); 
    } 
} 

public static class myListFragments extends ListFragment 
{ 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 
     return inflater.inflate(R.layout.topoffers, container, false); 
    } 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 
     // TODO Auto-generated method stub 
     super.onActivityCreated(savedInstanceState); 
     List<OfferModel> offers = Global.getInstance().getOffers(); 
     List<OfferModel> topOffers = new ArrayList<OfferModel>(4); 
     for (int i = 0; i < 4; i++) { 
      if (offers.get(i).getOfferImage() == null) 
       offers.get(i).setOfferImage(
         downloadFile(offers.get(i).getOfferImageUrl())); 
      topOffers.add(offers.get(i)); 
     } 
     LazyAdapter adapter = new LazyAdapter(getActivity()); 
     adapter.setData(topOffers); 
     setListAdapter(adapter); 
     setListShown(true); 
    } 

    public Bitmap downloadFile(String fileUrl) { 
     URL myFileUrl = null; 
     try { 
      myFileUrl = new URL(fileUrl); 
     } catch (MalformedURLException e) { 
      e.printStackTrace(); 
      return null; 
     } 
     try { 
      HttpURLConnection conn = (HttpURLConnection) myFileUrl 
        .openConnection(); 
      conn.setDoInput(true); 
      conn.connect(); 
      InputStream is = conn.getInputStream(); 
      return BitmapFactory.decodeStream(is); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      return null; 
     } 
    } 
}} 

и мой пользовательский макет R.layout.topoffers

Logcat:

05-15 21:43:56.975: W/dalvikvm(218): threadid=3: thread exiting with uncaught exception (group=0x4001b188) 
05-15 21:43:56.975: E/AndroidRuntime(218): Uncaught handler: thread main exiting due to uncaught exception 
05-15 21:43:56.995: E/AndroidRuntime(218): java.lang.RuntimeException: Unable to start activity ComponentInfo{org.anddev.android.ikiwi/org.anddev.android.ikiwi.ListFragmentActivity}: 
    java.lang.IllegalStateException: Can't be used with a custom content view 
05-15 21:43:56.995: E/AndroidRuntime(218):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2496) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at android.app.ActivityThread.access$2200(ActivityThread.java:119) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at android.os.Handler.dispatchMessage(Handler.java:99) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at android.os.Looper.loop(Looper.java:123) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at android.app.ActivityThread.main(ActivityThread.java:4363) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at java.lang.reflect.Method.invokeNative(Native Method) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at java.lang.reflect.Method.invoke(Method.java:521) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at dalvik.system.NativeStart.main(Native Method) 
05-15 21:43:56.995: E/AndroidRuntime(218): Caused by: java.lang.IllegalStateException: 
    Can't be used with a custom content view 
05-15 21:43:56.995: E/AndroidRuntime(218):  at android.support.v4.app.ListFragment.setListShown(ListFragment.java:282) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at android.support.v4.app.ListFragment.setListShown(ListFragment.java:258) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at org.anddev.android.ikiwi.ListFragmentActivity$myListFragments.onActivityCreated(ListFragmentActivity.java:57) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:891) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1080) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:622) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1416) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:505) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1129) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at android.app.Activity.performStart(Activity.java:3723) 
05-15 21:43:56.995: E/AndroidRuntime(218):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2468) 
05-15 21:43:56.995: E/AndroidRuntime(218):  ... 11 more 
05-15 21:43:57.025: I/dalvikvm(218): threadid=7: reacting to signal 3 
05-15 21:43:57.025: E/dalvikvm(218): Unable to open stack trace file '/data/anr/traces.txt': Permission denied 
+0

Это должно быть более конкретным, чем «оно делает исключения» – Thomas

+0

право, но я не могу определить, что делает исключение –

+0

Сообщите своим регистрационным номерам, где отображаются ошибки – Barak

ответ

5

Это звучит как вопрос, который был сообщен в Google уже.

Google Issue

Если это действительно ваш вопрос, есть несколько предложений в нижней части этой страницы для ее фиксации (ну, более заставить его работать, чем ее исправление).

+0

Благодарю вас, господин Барак, но в этом предположении он написал в краткосрочной перспективе я могу видеть только переопределение setEmptyText (String) :: void и ручную обработку пустого представления .. ..... как я могу переопределить функцию setEmptyText? –

+0

Я считаю, что вы просто удалите текстовое изображение из своего макета и в свой onActivityCreated поместите 'setEmptyText (« Ваше сообщение с пустым текстом »)'. Все примеры, которые я нашел, показывают, что они используются до создания/установки адаптера. – Barak

+0

Я сделал то, что вы сказали мне, но, к сожалению, он не работает, он по-прежнему вызывает исключение. –

-2

Попробуйте удалить setListShown(true);?

У меня была такая же проблема, некоторое время назад. Это швы, которые вы не можете использовать, если у вас есть пользовательский макет в ListFragment.

+1

Но я хочу использовать setListSHown, чтобы я мог контролировать, отображается ли этот список. Я бы хотел, чтобы он не отображался, ожидая появления в нем исходных данных. В это время вместо этого будет показан индикатор неопределенного прогресса. Индикатор прогресса был бы приятным. – topwik

23

Создание файла макета list_content.xml

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

    <LinearLayout android:id="@+id/progressContainer" 
      android:orientation="vertical" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:visibility="gone" 
      android:gravity="center"> 

     <ProgressBar style="?android:attr/progressBarStyleLarge" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" /> 
     <TextView android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:textAppearance="?android:attr/textAppearanceSmall" 
       android:text="" 
       android:paddingTop="4dip" 
       android:singleLine="true" /> 

    </LinearLayout> 

    <FrameLayout android:id="@+id/listContainer" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent"> 

     <ListView android:id="@android:id/list" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       android:drawSelectorOnTop="false" /> 
     <TextView android:id="@+id/internalEmpty" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       android:gravity="center" 
       android:textAppearance="?android:attr/textAppearanceLarge" /> 
    </FrameLayout> 

</FrameLayout> 

Поместите это внутри ListFragment класс:

public ListView mList; 
boolean mListShown; 
View mProgressContainer; 
View mListContainer; 

public void setListShown(boolean shown, boolean animate){ 
    if (mListShown == shown) { 
     return; 
    } 
    mListShown = shown; 
    if (shown) { 
     if (animate) { 
      mProgressContainer.startAnimation(AnimationUtils.loadAnimation(
        getActivity(), android.R.anim.fade_out)); 
      mListContainer.startAnimation(AnimationUtils.loadAnimation(
        getActivity(), android.R.anim.fade_in)); 
     } 
     mProgressContainer.setVisibility(View.GONE); 
     mListContainer.setVisibility(View.VISIBLE); 
    } else { 
     if (animate) { 
      mProgressContainer.startAnimation(AnimationUtils.loadAnimation(
        getActivity(), android.R.anim.fade_in)); 
      mListContainer.startAnimation(AnimationUtils.loadAnimation(
        getActivity(), android.R.anim.fade_out)); 
     } 
     mProgressContainer.setVisibility(View.VISIBLE); 
     mListContainer.setVisibility(View.INVISIBLE); 
    } 
} 
public void setListShown(boolean shown){ 
    setListShown(shown, true); 
} 
public void setListShownNoAnimation(boolean shown) { 
    setListShown(shown, false); 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 
    int INTERNAL_EMPTY_ID = 0x00ff0001; 
    View root = inflater.inflate(R.layout.list_content, container, false); 
    (root.findViewById(R.id.internalEmpty)).setId(INTERNAL_EMPTY_ID); 
    mList = (ListView) root.findViewById(android.R.id.list); 
    mListContainer = root.findViewById(R.id.listContainer); 
    mProgressContainer = root.findViewById(R.id.progressContainer); 
    mListShown = true; 
    return root; 
} 

Теперь вы можете использовать, как правило:

setListShown(boolean shown); 
setListShown(boolean shown, boolean animate); 
setListShownNoAnimation(boolean shown); 

Источник:

http://source-android.frandroid.com/frameworks/base/core/java/android/app/ListFragment.java

http://source-android.frandroid.com/frameworks/base/core/res/res/layout/list_content.xml

8

Просто замените оригинальный ListView с CustomListView Layout в рамках метода onCreateView. Работал для меня.

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 
    View layout = super.onCreateView(inflater, container, 
      savedInstanceState); 
    ListView lv = (ListView) layout.findViewById(android.R.id.list); 
    ViewGroup parent = (ViewGroup) lv.getParent(); 

    // Remove ListView and add CustomView in its place 
    int lvIndex = parent.indexOfChild(lv); 
    parent.removeViewAt(lvIndex); 
    LinearLayout mLinearLayout = (LinearLayout) inflater.inflate(
      R.layout.custom_list, container, false); 
    parent.addView(mLinearLayout, lvIndex, lv.getLayoutParams()); 
    return layout; 
} 
+0

Престижность удаления ненужного списка из иерархии. –

0

Мне просто нужно, чтобы изменить мой пустой текст TextView свойства и сделал это

@Override 
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { 
    // Swap the new cursor in. (The framework will take care of closing the 
    // old cursor once we return) 
    mAdapter.swapCursor(cursor); 
    if (cursor.getCount() == 0) { 
     setEmptyText(getString(R.string.no_users)); 
     TextView tvEmpty = (TextView) getListView().getEmptyView(); 
     tvEmpty.setTextColor(getResources().getColor(R.color.blue)); 
    } 
    // The list should now be shown. 
    if (isResumed()) { 
     setListShown(true); 
    } else { 
     setListShownNoAnimation(true); 
    } 
} 

Не забывайте, что если вы пытаетесь инициализировать tvEmpty перед вызовом setEmptyText("Empty"), вы будете работать в NullPointerException

2

Сегодня у меня была такая же проблема. Глядя на решение в Google, я нашел сообщение в японском блоге. (http://blog.nkzn.net/entry/2012/06/14/160706).

Для использования setListShown(boolean) вы должны сделать первый в макете:

<?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" > 

    <FrameLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 

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

    <LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_centerInParent="true" 
    android:gravity="center" 
    android:visibility="gone" > 

    <ProgressBar 
     android:id="@android:id/progress" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" /> 
    </LinearLayout> 
</RelativeLayout> 

Теперь в вашем ListFragment:

public class SampleListFragment extends ListFragment { 

    /** ID for progressbar parent */ 
    private static final int INTERNAL_PROGRESS_CONTAINER_ID = 0x00ff0002; 
    /** ID for listview parent */ 
    private static final int INTERNAL_LIST_CONTAINER_ID = 0x00ff0003; 

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

    // get you progressBar and his parent 
    ProgressBar pBar = (ProgressBar) view.findViewById(android.R.id.progress); 
    LinearLayout pframe = (LinearLayout) pBar.getParent(); 
    pframe.setId(INTERNAL_PROGRESS_CONTAINER_ID); 

    ListView listView = (ListView) view.findViewById(android.R.id.list); 
    listView.setItemsCanFocus(false); 
    FrameLayout lFrame = (FrameLayout) listView.getParent(); 
    lFrame.setId(INTERNAL_LIST_CONTAINER_ID);  

    return view; 
    } 
} 

с этим 2 IdS номерами seted в своих родителей setListShown (булево) будет работать без проблемы.

+0

Я прочитал ListFragment, и это единственный способ. Спасибо =) –

13

Это может быть проще: Создайте свой макет, как обычно, но не добавляйте список/пустое/загрузочное содержимое. Тогда в вашей listfragment в onCreateView:

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    View v = super.onCreateView(inflater, container, savedInstanceState); 
    ViewGroup parent = (ViewGroup) inflater.inflate(R.layout.mylayout, container, false); 
    parent.addView(v, 0); 
    return parent; 
} 

Теперь вы можете использовать setListShown ...

+0

Просто попробовал, он работает. Лучшее решение здесь! Гораздо проще, чем другой, поскольку вы храните все методы из SDK. – pommedeterresautee

+1

Вы можете не только использовать setListShow(), но и получить все поведение на складе и посмотреть в пределах вашего собственного большего макета. Вы можете поместить контейнер в родительский элемент и добавить к нему супер-представление вместо самого родителя. – lilbyrdie

+0

Это работает, но, как вы видите [здесь] (http://imgur.com/CCfqgmE), это заставляет вашу иерархию иметь два андроида: id/list. –

0

Этот код работает для меня:

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    View root = super.onCreateView(inflater, container, savedInstanceState); 

    ((TextView)root.findViewById(0x00ff0001)).setText("some text"); 

    ListView list = (ListView) root.findViewById(android.R.id.list); 
    list.setEmptyView(root.findViewById(0x00ff0001)); 

    return root; 
} 
1

Другим решением, которое работало для меня, а просто поставить эта линия

<include layout="@android:layout/list_content" /> 

вместо вашего списка.

Вы можете создать собственный контент поверх него или окружить его некоторыми другими видами. Например, вот как мой макет выглядит следующим образом:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:orientation="vertical" 
android:layout_width="match_parent" 
android:layout_height="match_parent" > 

<RelativeLayout 
     xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:padding="@dimen/default_view_padding" 
     android:gravity="center" 
     android:weightSum="4"> 

    <ImageButton 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:id="@+id/btnCounterBack" 
      android:src="?attr/ic_previous" 
      android:background="?android:attr/selectableItemBackground" 
      android:contentDescription="@null"/> 

    <TextView 
      android:id="@+id/tvCounterLevel" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:textAppearance="?android:attr/textAppearanceMedium" 
      android:text="@string/counter_categories" 
      android:layout_gravity="center" 
      android:paddingTop="@dimen/default_view_padding" 
      android:paddingBottom="@dimen/default_view_padding" 
      android:layout_alignParentTop="true" 
      android:layout_alignParentLeft="true" 
      android:layout_alignParentStart="true" 
      android:gravity="center"/> 

</RelativeLayout> 

<LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="0dp" 
     android:layout_weight="1" 
     android:gravity="center_vertical" 
     android:background="?attr/dropShadowBackground" 
     android:orientation="vertical" > 

    <include layout="@android:layout/list_content" /> 

</LinearLayout> 

0

Немного поздно, но не видел этот ответ.

Внутри Fragment:

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

     ListFragmentHelper.adaptView(view); 

     return view; 
    } 

но иметь в виду, что вfragment_list_activity.xml вам необходимо установить идентификаторы android:id="@id/loading", android:id="@id/content" и android:id="@id/empty" ваших мнений!

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