instantiateItem (ViewGroup, int) в PagerAdapter и AddView в путанице ViewPager - PullRequest
22 голосов
/ 02 сентября 2011

До сих пор я собирал примеры, чтобы почувствовать API-интерфейсы Android SDK в целом. Однако я зашел в тупик.

Я пытаюсь накачать LinearLayout двумя TextViews из файла XML. Это будут тогда представления, которые разбиты на страницы. Я просто не могу заставить это работать и понимаю, что совершенно не понимаю, что происходит с кодом.

Глядя на источник, я вижу, что метод ViewPager.addNewItem вызывает InstantiateItem из поставляемого адаптера. И addNewItem называется в populate(). populate () вызывается в ряде других мест.

В любом случае, в этом примере я обнаружил, что когда метод переопределяется для PagerAdapter, необходимо включить вызов addView() в коллекции ViewPager, которая передается из ViewPager в качестве аргумента.

Если я хочу добавить несколько представлений, я подумал, что это будет случай вызова addView () более одного раза, но как instantiateItem () возвращает объект ViewPager (в моем примере он возвращает представление, которое он добавил) не знаю что вернуть. Я пытался вернуть завышенное представление и ряд других вещей.

Пожалуйста, кто-нибудь может объяснить, что здесь происходит?

Очень ценится.

@Override
public Object instantiateItem(View collection, int position) {

    layout = inflater.inflate(R.layout.animallayout, null);
    TextView tv = (TextView) layout.findViewById(R.id.textView1);
    tv.setText("1________________>" + position);

    TextView tv2 = (TextView) layout.findViewById(R.id.textView2);
    tv.setText("2________________>" + position);

    ((ViewPager) collection).addView(layout);
    return layout;
}

Ответы [ 2 ]

57 голосов
/ 02 сентября 2011

Я недавно реализовал это, и это мой метод instantiateItem (сделал его немного минимальным для удобства чтения.

@Override
public Object instantiateItem(View collection, int position) {
    Evaluation evaluation = evaluations.get(position);

    View layout = inflater.inflate(R.layout.layout_evaluation, null);

    TextView evaluationSummary = (TextView) layout.findViewById(R.id.evaluation_summary);
    evaluationSummary.setText(evaluation.getEvaluationSummary());

    ((ViewPager) collection).addView(layout);

    return layout;
}

@Override
public void destroyItem(View collection, int position, Object view) {
     ((ViewPager) collection).removeView((View) view);
}

@Override
public boolean isViewFromObject(View view, Object object) {
    return view == object;
}

Таким образом, для отображаемой страницы я получаю данные из моего списка evaluations, используя позицию в качестве индекса. Затем надуйте Layout, который имеет представления, я тоже добавлю свои данные. Затем я получаю TextView, чтобы установить текст сводной оценки. Затем все Layout добавляется к ViewPager. И, наконец, Layout также возвращается.

Если вы все еще не можете получить его, отправьте свой код.

15 голосов
/ 27 мая 2013

У меня такое же недопонимание, как работает этот адаптер, и я провел некоторое исследование.
Ключевая особенность заключается в том, что ваши представления хранятся в двух местах:
1 в ViewPager вы добавляете их, вызывая ((ViewPager) container).addView(view); (здесь вам нужно хранить только три вида, то, что вы видите, и левую и правую окрестности)
2 в private final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>(); это член ViewPager, есть сохраненные представления с информацией о их возможностях (они добавляются здесь путем вызова метода адаптера mAdapter.instantiateItem(this, position);)

static class ItemInfo {
    Object object;
    int position;
    boolean scrolling;
    float widthFactor;
    float offset;
}

Когда вы скользите, ViewPager получает позицию вида из массива mItems или создает его и сравнивает это представление с потомками ViewPager с помощью метода адаптеров public boolean isViewFromObject(View view, Object object).Вид, равный object, отображается для пользователя на ViewPager.Если вид отсутствует, то отображается пустой экран.
Вот метод ViewPager, в котором вид сравнивается с объектом:

ItemInfo infoForChild(View child) {
    for (int i=0; i<mItems.size(); i++) {
        ItemInfo ii = mItems.get(i);
        if (mAdapter.isViewFromObject(child, ii.object)) {
            return ii;
        }
    }
    return null;
}

Если позиция представлений из mItems не находится в диапазоне {currentposition -1, текущее положение +1}, тогда оно будет уничтожено:

mItems.remove(itemIndex);
mAdapter.destroyItem(this, pos, ii.object);

представление памяти ViewPager 1

Это одна ловушка с destroyItem при перемещении впередЕлка называется destroyItem и затем добавляется новый элемент, но когда вы двигаетесь назад, сначала добавляется новый элемент, а затем старый уничтожается.Если вы попытаетесь использовать только три кэшированных представления, вы можете получить IllegalStateException: The specified child already has a parent., скользя назад.

ViewPager memory

...