Я могу использовать только ViewPager для просмотра страниц назад и не могу переходить вперед
Я могу использовать только ViewPager для просмотра страниц назад и не могу переходить вперед.
Я пишу баннер, но я могу использовать ViewPager только для перехода назад и не могу переходить вперед.
Это адаптер, который я написал.
class MyPagerAdapter extends PagerAdapter {
@Override
public Object instantiateItem(ViewGroup container, int position) {
int p = position % mImgRes.length;
container.addView(mListView.get(p));
return mListView.get(p);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public int getCount() {
return 100;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return (view == object);
}
}
Это сообщение об ошибке.
07-29 20: 45: 02.098 20791-20791 / com.example.myfirstpro E / AndroidRuntime: ФАТАЛЬНОЕ ИСКЛЮЧЕНИЕ: главная Процесс: com.example.myfirstpro, PID: 20791 java.lang.IllegalStateException: указанный дочерний элемент уже имеет родителя. Сначала вы должны вызвать removeView () у родителя ребенка. на android.view.ViewGroup.addViewInner(ViewGroup.java:4465) на android.view.ViewGroup.addView(ViewGroup.java:4301) на android.support.v4.view.ViewPager.addView(ViewPager.java:1505) на android.view.ViewGroup.addView(ViewGroup.java:4242) на android.view.ViewGroup.addView(ViewGroup.java:4215) в com.example.myfirstpro.MainFragment$MyPagerAdapter.instantiateItem(MainFragment.java:62) на android.support.v4.view.ViewPager.addNewItem(ViewPager.java:1034) на android.support.v4.view.ViewPager.populate(ViewPager.java:1216) на android.support.v4.view.ViewPager.populate(ViewPager.java:1116) на android.support.v4.view.ViewPager$3.run(ViewPager.java:273) на android.view.Choreographer$CallbackRecord.run(Хореограф.java:892) на android.view.Choreographer.doCallbacks(Хореограф.java:704) на android.view.Choreographer.doFrame(Хореограф.java:637) на android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:878) на android.os.Handler.handleCallback(Handler.java:739) на android.os.Handler.dispatchMessage(Handler.java:95) на android.os.Looper.loop(Looper.java:148) на android.app.ActivityThread.main(ActivityThread.java:5628) в java.lang.reflect.Method.invoke(родной метод) на com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:853) на com.android.internal.os.ZygoteInit.main(ZygoteInit.java:737)
Программа вылетит, когда я перейду вперед.
Это в дополнение к коду, отличному от адаптера.@Hong Duan
private ViewPager mVpScroll;
private int mImgRes[] = new int[] {
R.drawable.banner01,
R.drawable.banner02,
R.drawable.banner03
};
private List<View> mListView = new ArrayList<>();
private LayoutInflater mInfalte;
public MainFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
for (int i = 0; i < mImgRes.length; i++) {
View inflate = inflater.inflate(R.layout.fragment_main_scroll_item, null);
ImageView ivBanner = (ImageView) inflate.findViewById(R.id.iv_scroll);
ivBanner.setImageResource(mImgRes[i]);
mListView.add(inflate);
}
mInfalte = inflater;
return inflater.inflate(R.layout.fragment_main, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
mVpScroll = (ViewPager) view.findViewById(R.id.vp_scroll);
mVpScroll.setAdapter(new MyPagerAdapter());
}
1 ответ
Как показывает сообщение об ошибке, основной причиной является дочерний View
добавляется дважды. Но почему это происходит только тогда, когда вы проводите назад? Я сделал тестовый проект, и я думаю, что я нашел причину:)
когда ViewPager
свитки, он будет перерабатывать предметы, используя его PagerAdapter
методы: instantiateItem
а также destroyItem
, когда ViewPager
хочет показать новый предмет, instantiateItem
называется, когда ViewPager
прокручивает, вид, который с экрана будет уничтожен методом destroyItem
,
По умолчанию ViewPager
будет держать 1
больше элементов на каждой стороне для плавной прокрутки, а это означает, что есть не более 3
предметы хранятся у ViewPager
,
Проблема в том, что вы используете:
int p = position % mImgRes.length;
реализовать "петлю" ViewPager
, это означает, что если mImgRes.length == 3
, позиция 3 покажет то же самое View
в положении 0.
Теперь подумайте о вашем случае:
когда
ViewPager
начатый, предмет0
а также1
(справа) добавленыinstantiateItem
;затем прокрутите страницу вправо, элемент
1
показано, и элемент2
добавлен, теперь элемент0
(левый боковой элемент),1
,2
(справа) сохраняются;прокрутите страницу вправо еще раз, элемент
2
показано, пункт3
добавлено, пункт0
уничтожен методомdestroyItem
Теперь предмет1
(левый боковой элемент),2
,3
(правый элемент, тот же элемент для0
) хранятся;
Все работает нормально если instantiateItem
а также destroyItem
работает, как ожидалось, и работает, когда вы прокручиваете вправо ("вперед"), но не работает, когда вы прокручиваете влево ("назад"), потому что порядок instantiateItem
а также destroyItem
выполнены разные! Смотрите журнал:
07-30 22:00:04.385 26064-26064/com.example.test D/xxxxx: instantiateItem: 0
07-30 22:00:04.388 26064-26064/com.example.test D/xxxxx: instantiateItem: 1
07-30 22:00:17.693 26064-26064/com.example.test D/xxxxx: instantiateItem: 2
07-30 22:00:18.743 26064-26064/com.example.test D/xxxxx: destroyItem: 0
07-30 22:00:18.744 26064-26064/com.example.test D/xxxxx: instantiateItem: 3
07-30 22:00:26.477 26064-26064/com.example.test D/xxxxx: instantiateItem: 0 < -- crash!!!
07-30 22:00:18.743 26064-26064/com.example.test D/xxxxx: destroyItem: 3
когда вы прокрутите вправо, destroyItem
выполняется сначала, затем instantiateItem
, так что работает нормально, но когда вы прокручиваете влево, instantiateItem
выполняется первым, поэтому, когда печатается последняя строка журнала, элемент 0
добавляется второй раз, потому что элемент 3
(которые разделяют одно и то же View
с предметом 0
) еще не был уничтожен, то вылетает:)
Интересно то, что если mImgRes.length > 3
, он будет работать нормально, потому что когда есть 4 пункта, это не слишком поздно, когда destroyItem
выполнить.
Итак, если вы хотите реализовать ViewPager
с функцией "петли", вы должны думать о том, как обойти эту проблему.