Получить целенаправленный вид из ViewPager
Я использую ViewPager для переключения видов с помощью прокрутки влево/вправо.
ViewPager нуждается в адаптере, поэтому я создал его:
public class ListViewPagerAdapter extends PagerAdapter {
protected static final String TAG = "ListViewPagerAdapter";
protected static final int NUM_VIEWS = 3;
protected final Activity mActivity;
public ListViewPagerAdapter(Activity activity) {
mActivity = activity;
}
@Override
public int getCount() {
return NUM_VIEWS;
}
@Override
public void startUpdate(View container) {}
@Override
public Object instantiateItem(View container, int position) {
// ViewPager
ViewPager viewPager = (ViewPager) container;
// Wird verwendet, um die Views aufzurufen
LayoutInflater layoutInflater = mActivity.getLayoutInflater();
// Standardmäßig ist news eingeblendet
View view = layoutInflater.inflate(R.layout.news_fragment, null);
// Falls sich die Position verändert, so verändert sich auch die View
if (position == 0) {
view = layoutInflater.inflate(R.layout.favorite_fragment, null);
} else if (position == 2) {
view = layoutInflater.inflate(R.layout.videos_fragment, null);
}
// View einblenden
viewPager.addView(view, 0);
return view;
}
@Override
public void destroyItem(View container, int position, Object object) {
// ViewPager
ViewPager viewPager = (ViewPager) container;
// View
View view = (View) object;
// View löschen
viewPager.removeView(view);
}
@Override
public void finishUpdate(View container) {}
@Override
public boolean isViewFromObject(View view, Object object) {
View _view = (View) object;
return view == _view;
}
@Override
public Parcelable saveState() {
return null;
}
@Override
public void restoreState(Parcelable state, ClassLoader loader) {}
}
Теперь, я хочу получить текущий сфокусированный просмотр с помощью viewpager.
Я пробовал getChildAt (x), но он не работает.
Есть ли какой-то пример, или вы знаете, как получить текущий вид?
Спасибо
Ответы
Ответ 1
Можно сохранить текущий активный объект (View, Fragment,...), переопределив метод PagerAdapter.setPrimaryItem. Например:
private View mCurrentView;
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
mCurrentView = (View)object;
}
Ответ 2
Вам нужно зарегистрировать слушателя на ViewPager
:
pager.setOnPageChangeListener(new MyPageChangeListener());
Вы должны настроить слушателя, расширив прослушиватель заглушек:
private int focusedPage = 0;
private class MyPageChangeListener extends ViewPager.SimpleOnPageChangeListener {
@Override
public void onPageSelected(int position) {
focusedPage = position;
}
}
Я нашел это, посмотрев исходный код ViewPager.java в библиотеке совместимости . Я читал, что мы можем сделать больше, например catch onPageScrollStateChanged
.
Чтобы построить адаптер, я использовал код в этом сообщении в блоге. Возможно, вы захотите посмотреть.
Ответ 3
Вы можете добавить тег к созданному представлению в методе instantiateItem:
view.setTag(position);
Позже вы можете получить доступ к текущему выбранному виду:
mPager.findViewWithTag(mPager.getCurrentItem());
Ответ 4
Мне недавно понадобилось реализовать это точное решение. Вот как я это сделал:
Map<Integer, Object> views = Maps.newHashMap();
@Override
public Object instantiateItem(View container, int position) {
/* Create and add your View here */
Object result = ???
views.put(position, result);
return result;
}
@Override
public void destroyItem(View container, int position, Object object) {
/** Remove your View here */
views.remove(position);
}
protected View findViewForPosition(int position) {
Object object = views.get(position);
if (object != null) {
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
if (isViewFromObject(view, object)) {
return view;
}
}
}
return null;
}
Ответ 5
Попробуйте следующее:
public View getCurrentView(ViewPager pager) {
for (int i = 0; i < pager.getChildCount(); i++) {
View child = pager.getChildAt(i);
if (child.getX() <= pager.getScrollX() + pager.getWidth() &&
child.getX() + child.getWidth() >= pager.getScrollX() + pager.getWidth()) {
return child;
}
}
return getChildAt(0);
}
Ответ 6
Чтобы получить целенаправленное представление, я использую этот способ:
Когда я раздуваю свое представление, прежде чем добавлять его в ViewPager, я устанавливаю для него тег. Затем я проверяю этот тег.
private View getCurrentView()
{
for (int i = 0; i < pager.getChildCount(); i++)
{
View v = pager.getChildAt(i);
if (v != null)
{
if (v.getTag().equals(pageList.get(pager.getCurrentItem()).getTag())) return v;
// pageList is a list of pages that I pass to page adapter
}
}
return null;
}
Ответ 7
данные ответы мне не подходят, все они имеют нежелательные побочные эффекты. Либо мне нужно добавить ненужные переменные (мне нравится чистый код), либо я должен сам работать с каркасом Android.
Мое решение основано на отражении, которое обращается к списку массивов всех объектов в ViewPager и возвращает текущий выбранный объект в ViewPager. Он почти не имеет побочных эффектов (отражение медленное, подклассификация существующего класса), и он сохраняет код в чистоте.
public class ViewPagerEx extends ViewPager {
private static final String TAG = ViewPagerEx.class.getSimpleName();
public ViewPagerEx(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ViewPagerEx(Context context) {
super(context);
}
public Object getCurrentObject() {
try {
final Field itemsField = ViewPager.class.getDeclaredField("mItems");
itemsField.setAccessible(true);
final ArrayList<Object> items = (ArrayList<Object>) itemsField.get(this);
final int currentItemIndex = getCurrentItem();
if (currentItemIndex < 0 || currentItemIndex >= items.size()) {
return null;
}
final Object infoItem = items.get(getCurrentItem());
final Class<?> itemInfoClass = findItemInfoClass(ViewPager.class.getDeclaredClasses());
final Field objectField = itemInfoClass.getDeclaredField("object");
objectField.setAccessible(true);
return objectField.get(infoItem);
} 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;
}
private Class<?> findItemInfoClass(final Class<?>[] classes) throws IllegalArgumentException {
for (int i = 0; i < classes.length; i++) {
if (classes[i].getSimpleName().equals("ItemInfo")) {
return classes[i];
}
}
throw new IllegalArgumentException("cannot find class ItemInfo");
}
}
Ответ 8
Внутри FragmentStatePagerAdapter
:
private View mCurrentView;
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
Fragment f = (Fragment) object;
mCurrentView = f.getView();
}
Ответ 9
Если вы внимательно изучите, на ViewPager будет сохранено не более 3 просмотров.
Вы можете легко получить текущий вид
view = MyActivity.mViewPager.getChildAt(1);
Ответ 10
Я что-то упустил? Там только 3 ребенка внутри ViewGroup, поэтому он сводится к:
int current = viewPager.getCurrentItem();
int childCount = viewPager.getChildCount();
// If there a single page or we're at the beginning, return the first view
if (childCount == 1 || current == 0) {
return viewPager.getChildAt(0);
} else { //For any other case, we want the second child. This is either the last page or the page in the middle for any other case.
return viewPager.getChildAt(1);
}