Не удалось получить текущий просмотр в Viewpager
Я использую viewpager для отображения текста на нескольких страницах. Я пытаюсь получить текущее представление, я выбираю новую страницу. Причина, по которой я хочу получить текущее представление, состоит в том, что, основываясь на номере страницы, я меняю некоторые свойства некоторых компонентов вида, таких как textview, изображение и т.д.
Я использую приведенный ниже код для того же
ViewPager mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
View CurrView;
OnPageChangeListener pageChangelistener = new OnPageChangeListener() {
@Override
public void onPageSelected(int pageSelected) {
currView = mPager.getChildAt(mPager.getCurrentItem());
myTextView = (TextView)currView.findViewById(R.id.myTextView);
loadBookmarkSetting(pageSelected);//do some changes in myTextView properties based on the page number }
mPager.setOnPageChangeListener(pageChangelistener);
Теперь проблема, с которой я сталкиваюсь, после того, как я прокручиваю 3 страницы, и когда я прихожу на 4-ю страницу, я получаю исключение nullpointer в строке "myTextView = (TextView) currView.findViewById(R.id.myTextView);". Это так, потому что currView имеет значение null. Любые идеи, если я делаю что-то неправильно здесь. Есть ли другой способ захвата текущего представления (страницы) в viewpager, так как я могу делать изменения в представлении, основываясь на том, на каком номере страницы я нахожусь?
Ответы
Ответ 1
Вы можете использовать setTag с представлением, которое вы возвращаете в методе instantiateItem (PagerAdapter).
Итак, когда вы создаете свои представления в PagerAdapter, метод также instantiateItem(ViewGroup container, int position))
, вы должны использовать setTag для вашего представления.
Вот так:
view.setTag("myview" + position);
return view;
когда вам нужен текущий вид:
View view = (View) pager.findViewWithTag("myview" + pager.getCurrentItem());
Ответ 2
Вы используете такой подход:
@Nullable
public static View getActiveView(@Nonnull final ViewPager viewPager) {
final PagerAdapter adapter = viewPager.getAdapter();
if (null == adapter || adapter.getCount() == 0 || viewPager.getChildCount() == 0) {
return null;
}
int position;
final int currentPosition = viewPager.getCurrentItem();
for (int i = 0; i < viewPager.getChildCount(); i++) {
final View child = viewPager.getChildAt(i);
final LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
if (layoutParams.isDecor) {
continue;
}
final Field positionField;
try {
positionField = LayoutParams.class.getDeclaredField("position");
positionField.setAccessible(true);
position = positionField.getInt(layoutParams);
} catch (NoSuchFieldException e) {
break;
} catch (IllegalAccessException e) {
break;
}
if (position == currentPosition) {
return child;
}
}
return null;
}
Ответ 3
Я добавил SparseArray в свой адаптер и добавил представление в instantiateItem()
и удалил его в destroyItem()
val views = SparseArray<View>()
...
override fun instantiateItem(container: ViewGroup, position: Int): Any
{
//...
container.addView(view)
views.put(position, view)
return view
}
override fun destroyItem(container: ViewGroup, position: Int, obj: Any)
{
views.remove(position)
container.removeView(obj as View)
}
fun showFooter(currentItem: Int) {
views[currentItem].footer_layout.animate().alpha(1f)
}
fun hideFooter(currentItem: Int) {
views[currentItem].footer_layout.animate().alpha(0f)
}
И тогда я могу вызвать методы на адаптере:
viewPager.addOnPageChangeListener(object: ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {
when (state) {
SCROLL_STATE_IDLE -> adapter.showFooter(viewPager.currentItem)
SCROLL_STATE_DRAGGING -> adapter.hideFooter(viewPager.currentItem)
}
}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
override fun onPageSelected(position: Int) {}
})
Ответ 4
Я использую этот метод с android.support.v4.view.ViewPager
View getCurrentView(ViewPager viewPager) {
try {
final int currentItem = viewPager.getCurrentItem();
for (int i = 0; i < viewPager.getChildCount(); i++) {
final View child = viewPager.getChildAt(i);
final ViewPager.LayoutParams layoutParams = (ViewPager.LayoutParams) child.getLayoutParams();
Field f = layoutParams.getClass().getDeclaredField("position"); //NoSuchFieldException
f.setAccessible(true);
int position = (Integer) f.get(layoutParams); //IllegalAccessException
if (!layoutParams.isDecor && currentItem == position) {
return child;
}
}
} catch (NoSuchFieldException e) {
Log.e(TAG, e.toString());
} catch (IllegalArgumentException e) {
Log.e(TAG, e.toString());
} catch (IllegalAccessException e) {
Log.e(TAG, e.toString());
}
return null;
}
Ответ 5
Вы получаете исключение нулевого указателя, потому что вы установили offscreenPageLimit равным 3. ViewPager будет хранить только 3 pages.mPager.getChildAt(4) получит нулевое значение.
Чтобы установить просмотр текста, вы можете использовать менеджер фрагментов адаптера, чтобы получить все фрагменты и получить вид фрагмента в позиции.
adapter.fragmentManager.fragments[position1].view
Ответ 6
Причина, по которой ваше текущее представление имеет значение null, заключается в том, что адаптер пейджера начинает уничтожать свои элементы для повышения эффективности памяти. Один из способов, который я нашел, будет заключаться в том, чтобы переопределить метод destroyItem() для пейджера-адаптера и сохранить ваши данные либо через список, либо с помощью класса-подпрограммы.