Не удалось получить текущий вид в Viewpager
Я использую ViewPager для отображения текста на нескольких страницах. Я пытаюсь получить текущий вид и выбрать новую страницу. Причина, по которой я хочу получить текущее представление, заключается в том, что в зависимости от номера страницы я изменяю некоторые свойства некоторых компонентов представления, таких как textview, image и т. Д. Я использую приведенный ниже код для того же
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 является нулевым. Любые идеи, если я делаю что-то не так здесь. Есть ли другой способ записать текущее представление (страницу) в viewpager, чтобы я мог вносить изменения в представление в зависимости от того, на каком номере страницы я нахожусь?
4 ответа
Вы можете использовать setTag с представлением, которое вы возвращаете, в вашем методе instantiateItem (PagerAdapter).
Таким образом, когда вы создаете свои представления в PagerAdapter, метод также instantiateItem(ViewGroup container, int position))
, вы должны использовать setTag для вашего просмотра.
Как это:
view.setTag("myview" + position);
return view;
когда вам нужен текущий вид:
View view = (View) pager.findViewWithTag("myview" + pager.getCurrentItem());
Вы используете этот подход:
@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;
}
Вы получаете исключение с нулевым указателем, потому что вы установили offscreenPageLimit на 3. Вьюпейджер будет хранить только 3 страницы. MPager.getChildAt(4) получит null. Чтобы установить текстовое представление, вы можете использовать диспетчер фрагментов адаптера, чтобы получить все фрагменты и получить представление фрагмента в позиции.
adapter.fragmentManager.fragments[position1].view
Я добавил 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) {}
})
Причина, по которой ваше текущее представление является нулевым, заключается в том, что адаптер пейджера начинает уничтожать свои элементы в целях повышения эффективности памяти. Один способ, который я нашел, сработал бы - переопределить метод destroyItem() адаптера пейджера и сохранить ваши данные либо через список, либо с помощью анализируемого класса.