Get focused View from ViewPager

后端 未结 11 1213
情深已故
情深已故 2020-11-27 12:50

i use the ViewPager for switching views with left/right swipe.

The ViewPager needs an Adapter, so I\'ve built this one:

public class ListViewPagerAda         


        
相关标签:
11条回答
  • 2020-11-27 13:26

    I recently needed to implement this exact solution. Here's the way I did it:

    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;
    }
    
    0 讨论(0)
  • 2020-11-27 13:28

    To get focused view I use this way:

    When I inflate my view before add it on ViewPager I set tag to it. Then I check this tag.

    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;
    }
    
    0 讨论(0)
  • 2020-11-27 13:32

    the given answers were not really suitable for me, they all have unwanted side effects. Either I have to add unnecessary variables (I like clean code) or I have to work around the Android framework itself.

    My solution is based on reflection, which accesses the array list of all objects within the ViewPager and returns the current selected object in the ViewPager. It has almost no side effects (reflection is slow, subclassing of an existing class) and it keeps the code clean.

    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");
        }
    }
    
    0 讨论(0)
  • 2020-11-27 13:33

    It is possible to save the currently active object (View, Fragment, ...) by overriding PagerAdapter.setPrimaryItem method. For example:

    private View mCurrentView;
    
    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        mCurrentView = (View)object;
    }
    
    0 讨论(0)
  • 2020-11-27 13:38

    If you examine carefully, there are at most 3 views saved by ViewPager. You can easily get the current view by

    view     = MyActivity.mViewPager.getChildAt(1);
    
    0 讨论(0)
  • 2020-11-27 13:40

    You have to register a listener to your ViewPager :

    pager.setOnPageChangeListener(new MyPageChangeListener()); 
    

    You have to customize the listener by extending a stub listener:

    private int focusedPage = 0;
    private class MyPageChangeListener extends ViewPager.SimpleOnPageChangeListener {
        @Override
        public void onPageSelected(int position) {
            focusedPage = position;
        }
    }
    

    I found this by looking at the ViewPager.java source code in the compatibility library. I read that we can do more, for example catch onPageScrollStateChanged.

    To build the adapter, I used the code on this blog post. You might want to have a look.

    0 讨论(0)
提交回复
热议问题