Подтвердить что ты не робот

Может ли ListView содержать фрагменты

Как и в случае, могут ли ЭЛЕМЕНТЫ ListView быть фрагментами. Я знаю, что вы можете назначить TextView XML ListView для изменения способа его просмотра, но можете ли вы добавить фрагменты в ListView.

Например: у меня есть фрагмент. XML для упомянутого фрагмента содержит ImageView, пару текстовых файлов большого формата и текстовый TextView небольшого размера. Код класса Fragment получает Bundle, а затем на основе содержимого соответственно заполняется TextViews и ImageView. И фрагмент XML, и код фрагмента работают без проблем (Я могу показать отдельный фрагмент просто отлично). У меня есть FragmentActivity, в котором я хочу отобразить вышеупомянутый список фрагментов. Вот код, который я использую, чтобы попытаться заполнить ListView внутри представления FragmentActivity:

    ArrayList<Fragment> fragList = new ArrayList<Fragment>();
    Fragment fragment = Fragment.instantiate(this, TileItem.class.getName());
    Bundle bundle = new Bundle();
    bundle.putInt("key", 0);
    fragment.setArguments(bundle);
    fragList.add(fragment);

    ArrayAdapter<Fragment> adapter = new ArrayAdapter<Fragment>(this, R.layout.tile_item, fragList);
    listItems.setAdapter(adapter);

Вот мой способ мышления об этом. Я делаю ArrayList of Fragments для хранения всех моих экземпляров. Затем я создаю фрагмент, создаю Bundle, добавляю данные в Bundle (чтобы Фрагмент мог маршалировать данные в него.), Добавьте Bundle в Fragment, а затем, наконец, добавьте фрагмент в ArrayList. После этого я создаю ArrayAdapter, добавляю макет элемента, который я хочу использовать, и список Фрагментов, которые я сделал; затем установите ListView для чтения из моего адаптера.

Любой, кто запускает этот код, скорее всего, получит NPE @, создающий экземпляр ArrayAdapter. Что дает? Возможно ли это? Прежде чем я продолжаю ломать голову над этим, может кто-то сказать мне, если я просто трачу свое время? Есть ли способ лучше? Я думал об использовании ScrollView, но так много функциональности ListView нужно было бы повторно внедрить, и я ненавижу ненависть-ненависть, изобретая колесо, когда это не нужно.

Спасибо всем, кто читает, и особенно благодарю вас за ваши мысли, если вы решите оставить их. Я попытался найти подходящий ответ на этот вопрос, но все, что мне кажется, это вопросы/веб-страницы, касающиеся использования ListView INSIDE фрагмента; не используя фрагменты КАК ЭЛЕМЕНТЫ ListView

Изменить: я принял предложения ниже и начал расследовать больше. Из того, как выглядят вещи, я должен использовать пользовательский адаптер, который раздувает фрагменты, а не просто строить из XML (из-за отсутствия лучшего способа описать процесс). Однако моя текущая реализация бросает NPE при попытке установить адаптер.

Вот мой код адаптера (сокращенный для краткости):

public class AdapterItem extends ArrayAdapter<Fragment> {

Context c;
List<Fragment> f;

public AdapterItem(Context c, List<Fragment> f) {
    super(c, R.layout.tile_item, f);
    this.c = c;
    this.f = f;
}

@Override
public View getView(int pos, View v, ViewGroup vg) {
    LayoutInflater i = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    return i.inflate(R.layout.tile_item, vg, false);
}

}

и вот как я его реализую:

ArrayList<Fragment> fragList = new ArrayList<Fragment>();
    Fragment fragment = Fragment.instantiate(this, TileItem.class.getName());
    Bundle bundle = new Bundle();
    bundle.putInt("key", 0);
    fragment.setArguments(bundle);
    fragList.add(fragment);

    AdapterItem adapter = new AdapterItem(this, fragList);
    adapter.add(fragment);
    listItems.setAdapter(adapter);

Итак, прошло несколько дней, и я уверен, что эта нить была похоронена. Тем не менее, я думал, что добавлю одно последнее обновление на случай, если кто-то захочет попробовать это, и поиск в Google приведет их сюда. Поэтому в моей реализации я получаю NPE, когда ListView получает адаптер. Хируру ракетоприемника не требуется, чтобы он понял, что адаптер, а не ListView, бросает ошибку. Для жизни меня я не могу понять, почему, хотя...

Во всяком случае, я думаю, что у меня есть идея. Во-первых, небольшая история: некоторое время назад я пытался сделать FragmentTransactions внутри FragmentDialog. Каждый раз, когда я пытался это сделать, я получал NPE. В конце концов, благодаря большим исследованиям, я обнаружил, что причина связана с тем, как создаются Фрагменты. Когда вызывается фрагмент, ему нужен контекст из него родительский. Поскольку родительский диалог - это начальная операция, сам диалог не соответствовал требуемым критериям. Я считаю, что при попытке добавить фрагменты в ListView это тоже так. Поскольку ListView не соответствует соглашению с созданием фрагмента, он бросает NPE и, таким образом, оставляет меня зависанием и возвращается к соглашениям. D @mn... Я действительно надеялся, что смогу это сделать. Использование фрагментов вместо простого XML упростило бы организацию/поиск по списку. О, ну... думаю, это невозможно сделать, если кто-то задается вопросом.

4b9b3361

Ответ 1

Я бы сказал, что это невозможно сделать, поскольку размещение фрагмента в ListView означает, что фрагмент можно умножить на несколько контейнеров. Когда вы используете FragmentManager для создания фрагмента, он помечен идентификатором, что упрощает его перезагрузку и переупорядочивание по ориентации и другим изменениям конфигурации. Он также поощряет использование нескольких конфигураций устройств.

Фрагмент - это действительно подмножество Activity. У вас когда-нибудь будет активность как часть списка? Определенно нет (должен быть ответ!)!!!

Кроме того, не очень полезно прикрепить() и отделить() фрагмент непрерывно по мере их перемещения и выхода из вида (ячейки возвращаются). Это все дорогостоящие операции, с которыми ListView не должен справляться. Списки должны быстро прокручиваться.

Из разговора по комментариям я вижу, что вы хотите добиться хорошего кода с хорошим разделением кода установки и адаптера представления в Activity. Сделайте это с помощью:

  • Переопределите класс View и сделайте свой собственный рисунок и настройте там.
  • Создайте новый класс, в котором вы предоставили необходимый для этого контекст и набор данных, чтобы вернуть вам представление, которое должен показать список - это то, что я обычно делаю.
  • У вас есть класс Utils для создания вашего видео в другом месте (глупо).

Просто не используйте фрагменты в списках. Не тот прецедент, к которому они стремятся. НТН.

Ответ 2

Оказывается, вы можете создать ListView, где каждый элемент в listView является Fragment. Трюк обертывает фрагмент в FrameLayout.

ОБНОВЛЕНИЕ 9/16/2014

Даже если можно создать ListView, которые содержат Fragments, это не похоже на то, что это хорошая идея. Кажется, это определенно является краеугольным камнем в мире Android, и там есть драконы. Для простого фрагмента, такого как пример в приведенном ниже примере, все работает красиво, но если у вас сложный проект, в котором много чего происходит, то это, вероятно, не путь. Мой новый подход состоит в том, чтобы потянуть весь код, связанный с графическим интерфейсом, в View, который расширяет FrameLayout, и вставляет его в ListView - это работает MUTCH BETTER и больше соответствует тому, как Android ожидает использования, Если вам нужна функциональность Fragment в других частях вашего кода, вы можете просто использовать этот новый View там тоже.

Вернуться к исходному ответу...

Я добавил новый пример ManyFragments в мое приложение AnDevCon 14 Fragments example, если вы хотите попробовать его. По сути, это происходит с BaseAdapter, который в моем примере выглядит следующим образом:

    BaseAdapter adapter = new BaseAdapter() {
        @Override public int getCount() { return 10000; }
        @Override public Object getItem(int i) { return new Integer(i); }
        @Override public long getItemId(int i) { return i; }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {

            if (view!=null){
                ManyListItemFragment fragment = (ManyListItemFragment) view.getTag();
                fragment.setCount(i);
            } else {
                FrameLayout layout = new FrameLayout(getActivity());
                layout.setLayoutParams(frameLayoutParams);
                int id = generateViewId();
                layout.setId(id);
                ManyListItemFragment fragment = new ManyListItemFragment();
                fragment.setCount(i);
                getChildFragmentManager()
                        .beginTransaction()
                        .replace(id,fragment)
                        .commit();
                view = layout;
                view.setTag(fragment);
            }

            return view;
        }
    };

Если вам интересно здесь generateViewId():

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public static int generateViewId() {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
        for (;;) {
            final int result = sNextGeneratedId.get();
            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
            int newValue = result + 1;
            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
            if (sNextGeneratedId.compareAndSet(result, newValue)) {
                return result;
            }
        }
    } else {
        return View.generateViewId();
    }
}
private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);

Ответ 3

Вам не нужно использовать фрагменты.

Напишите пользовательский ViewAdapter и раздуйте более сложный макет (или, возможно, несколько более сложных макетов, если вам нужно по-настоящему фантазировать), затем заполните поля макета по мере необходимости.

[Помимо людей, которые ответили в комментариях, используйте ответы, а не комментарии, если вы действительно отвечаете на вопрос! Если только потому, что вы получаете больше очков репутации таким образом!]