Can I use view pager with views (not with fragments)

前端 未结 7 1941
情深已故
情深已故 2020-11-28 01:39

I am using ViewPager for swiping between Fragments, but can I use ViewPager to swipe between Views simple XML layout?

相关标签:
7条回答
  • 2020-11-28 02:11

    Use this example

    You can use a single XML layout nesting the children views.

     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
    
            <android.support.v4.view.ViewPager
                android:id="@+id/pager"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
    
                <LinearLayout
                    android:id="@+id/page_one"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="vertical" >
                            <TextView
                            android:text="PAGE ONE IN"
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            android:textColor="#fff"
                            android:textSize="24dp"/>
                </LinearLayout>
    
                <LinearLayout
                    android:id="@+id/page_two"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="vertical" >
                            <TextView
                            android:text="PAGE TWO IN"
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            android:textColor="#fff"
                            android:textSize="24dp"/>
                </LinearLayout>
    
        </android.support.v4.view.ViewPager>
    </LinearLayout>
    

    BUT... you need handle this with an adapter also. Here we return the finded view ID without inflate any other layout.

    class WizardPagerAdapter extends PagerAdapter {
    
        public Object instantiateItem(ViewGroup collection, int position) {
    
            int resId = 0;
            switch (position) {
            case 0:
                resId = R.id.page_one;
                break;
            case 1:
                resId = R.id.page_two;
                break;
            }
            return findViewById(resId);
        }
    
        @Override
        public int getCount() {
            return 2;
        }
    
        @Override
        public boolean isViewFromObject(View arg0, Object arg1) {
            return arg0 == arg1;
        }
    
        @Override public void destroyItem(ViewGroup container, int position, Object object) {
            // No super
        }
    }
    

    // Set the ViewPager adapter

    WizardPagerAdapter adapter = new WizardPagerAdapter();
    ViewPager pager = (ViewPager) findViewById(R.id.pager);
    pager.setAdapter(adapter);
    
    0 讨论(0)
  • 2020-11-28 02:15

    yes...you can use View instead of Fragment in viewpager. Here you can Find Whole example that will help you to achieve Viewpager without Fragment. Go through this documentation.

    https://www.bignerdranch.com/blog/viewpager-without-fragments/

    0 讨论(0)
  • 2020-11-28 02:21

    I would like to add my solution here. Given that you don't need to use fragments, you can still create a PagerAdapter which attaches views instead of fragments to the ViewPager.

    Extend PagerAdapter instead of FragmentPagerAdapter

    public class CustomPagerAdapter extends PagerAdapter {
    
      private Context context;
    
      public CustomPagerAdapter(Context context) {
        super();
        this.context = context;
      }
    
    
      @Override
      public Object instantiateItem(ViewGroup collection, int position) {
        LayoutInflater inflater = LayoutInflater.from(context);
        View view = null;
        switch (position){
          case 0:
            view = MemoryView.getView(context, collection);
            break;
          case 1:
            view = NetworkView.getView(context, collection);
            break;
          case 2:
            view = CpuView.getView(context, collection);
            break;
        }
    
        collection.addView(view);
        return view;
      }
    
      @Override
      public int getCount() {
        return 3;
      }
    
      @Override
      public boolean isViewFromObject(View view, Object object) {
        return view==object;
      }
    
      @Override
      public void destroyItem(ViewGroup collection, int position, Object view) {
        collection.removeView((View) view);
      }
    }
    

    Now you need to define three classes which will return the views to be inflated in the viewpager. Similar to CpuView you will have MemoryView and NetworkView classes. Each of them will inflate their respective layouts.

    public class CpuView {
    
    public static View getView(Context context, ViewGroup collection) {
    
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context
            .LAYOUT_INFLATER_SERVICE);
        return inflater.inflate(R.layout.debugger_cpu_layout, collection, false);
      }
    }
    

    And finally a layout which will be inflated in each of the views

        <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:orientation="vertical"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent">
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#000000"
            android:text="CPU"/>
    </LinearLayout>
    

    P.S.: The reason I wrote this answer is because all the solutions provided here seems to be working fine, but they are inflating the layouts in the PagerAdapter class itself. For large projects it becomes difficult to maintain if their is a lot of code related to the layouts inflated. Now in this example all the views have separate classes and separate layouts. So the project can be easily maintained.

    0 讨论(0)
  • 2020-11-28 02:28

    I'd like to elaborate on @Nicholas answer, you can get the views by id or if they're dynamically added just get the view directly given its position

    class WizardPagerAdapter extends PagerAdapter {
    
        public Object instantiateItem(View collection, int position) {
    
            View v = pager.getChildAt(position);
    
            return v;
        }
    
        @Override
        public int getCount() {
            return 3;
        }
    
        @Override
        public boolean isViewFromObject(View arg0, Object arg1) {
            return arg0 == ((View) arg1);
        }
    }
    
    0 讨论(0)
  • 2020-11-28 02:29

    Based on the previous answers, I made the following class to achieve that in a proper and clearest way (I hope):

    public class MyViewPagerAdapter extends PagerAdapter {
    
        ArrayList<ViewGroup> views;
        LayoutInflater inflater;
    
        public MyViewPagerAdapter(ActionBarActivity ctx){
            inflater = LayoutInflater.from(ctx);
            //instantiate your views list
            views = new ArrayList<ViewGroup>(5);
        }
    
        /**
         * To be called by onStop
         * Clean the memory
         */
        public void release(){
         views.clear();
            views = null;
        }
    
        /**
         * Return the number of views available.
         */
        @Override
        public int getCount() {
            return 5;
        }
    
        /**
         * Create the page for the given position. The adapter is responsible
         * for adding the view to the container given here, although it only
         * must ensure this is done by the time it returns from
         * {@link #finishUpdate(ViewGroup)}.
         *
         * @param container The containing View in which the page will be shown.
         * @param position The page position to be instantiated.
         * @return Returns an Object representing the new page. This does not
         *         need to be a View, but can be some other container of
         *         the page.  ,container
         */
        public Object instantiateItem(ViewGroup container, int position) {
            ViewGroup currentView;
            Log.e("MyViewPagerAdapter", "instantiateItem for " + position);
            if(views.size()>position&&views.get(position) != null){
                Log.e("MyViewPagerAdapter",
                      "instantiateItem views.get(position) " +
                      views.get(position));
                currentView = views.get(position);
            }
            else{
                Log.e("MyViewPagerAdapter", "instantiateItem need to create the View");
                int rootLayout = R.layout.view_screen;
                currentView = (ViewGroup) inflater.inflate(rootLayout, container, false);
    
                ((TextView)currentView.findViewById(R.id.txvTitle)).setText("My Views " + position);
                ((TextView)currentView.findViewById(R.id.btnButton)).setText("Button");
                ((ImageView)currentView.findViewById(R.id.imvPicture)).setBackgroundColor(0xFF00FF00);
            }
            container.addView(currentView);
            return currentView;
        }
    
        /**
         * Remove a page for the given position. The adapter is responsible
         * for removing the view from its container, although it only must ensure
         * this is done by the time it returns from {@link #finishUpdate(ViewGroup)}.
         *
         * @param container The containing View from which the page will be removed.
         * @param position The page position to be removed.
         * @param object The same object that was returned by
         * {@link #instantiateItem(View, int)}.
         */
        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View)object);
    
        }
    
        /**
         * Determines whether a page View is associated with a specific key object
         * as returned by {@link #instantiateItem(ViewGroup, int)}. This method is
         * required for a PagerAdapter to function properly.
         *
         * @param view   Page View to check for association with <code>object</code>
         * @param object Object to check for association with <code>view</code>
         * @return true if <code>view</code> is associated with the key object <code>object</code>
         */
        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view==((View)object);
        }
    }
    

    And you have to set it in your activity:

    public class ActivityWithViewsPaged extends ActionBarActivity {
    
        /**
         * The page Adapter: Manage the list of views (in fact here, its fragments)
         * And send them to the ViewPager
         */
        private MyViewPagerAdapter pagerAdapter;
    
        /**
         * The ViewPager is a ViewGroup that manage the swipe from left
         * to right to left.
         * Like a listView with a gesture listener...
         */
        private ViewPager viewPager;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
    
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_with_views);
    
            // Find the viewPager
            viewPager = (ViewPager) super.findViewById(R.id.viewpager);
    
            // Instantiate the PageAdapter
            pagerAdapter = new MyViewPagerAdapter(this);
    
            // Affectation de l'adapter au ViewPager
            viewPager.setAdapter(pagerAdapter);
            viewPager.setClipToPadding(false);
            viewPager.setPageMargin(12);
    
            // Add animation when the page are swiped
            // this instanciation only works with honeyComb and more
            // if you want it all version use AnimatorProxy of the nineoldAndroid lib
            //@see:http://stackoverflow.com/questions/15767729/backwards-compatible-pagetransformer
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
                viewPager.setPageTransformer(true, new PageTransformer());
            }
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            pagerAdapter.release();
        }
    

    Where the XML files are obvious view_screen.xml:

    <xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/screen"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
     <TextView
            android:id="@+id/txvTitle"
            android:layout_width="wrap_content"
            android:layout_gravity="center"
            android:layout_height="wrap_content"
            android:layout_marginBottom="5dp"
            android:layout_marginTop="5dp"
            android:shadowColor="#FF00FF"
            android:shadowDx="10"
            android:shadowDy="10"
            android:shadowRadius="5"
            android:textSize="32dp"
            android:textStyle="italic"
            android:background="#FFFFF000"/>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#FFFF00F0">
            <TextView
                android:id="@+id/txvLeft"
                android:layout_width="wrap_content"
                android:layout_gravity="left"
                android:layout_height="wrap_content"
                android:layout_marginBottom="5dp"
                android:layout_marginTop="5dp"/>
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"/>
            <TextView
                android:id="@+id/txvRight"
                android:layout_width="wrap_content"
                android:layout_gravity="right"
                android:layout_height="wrap_content"
                android:layout_marginBottom="5dp"
                android:layout_marginTop="5dp"/>
        </LinearLayout>
        <Button
            android:id="@+id/btnButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"/>
        <ImageView
            android:id="@+id/imvPicture"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center"/>
    </LinearLayout>
    

    And ActivtyMain has the following layout:

    <?xml version="1.0" encoding="utf-8"?>
    
    <android.support.v4.view.ViewPager
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:paddingLeft="24dp"
        android:paddingRight="24dp"
        android:id="@+id/viewpager"
        android:background="#FF00F0F0">
    </android.support.v4.view.ViewPager>
    

    Big thanks to Brian and Nicholas for your answer, I hope I add some clearest information and hightlight some good practices for this feature.

    0 讨论(0)
  • 2020-11-28 02:30

    You need to override these two methods rather than getItem():

    @Override
    public Object instantiateItem(ViewGroup collection, int position) {
        View v = layoutInflater.inflate(...);
        ...
        collection.addView(v,0);
        return v;
    }
    
    @Override
    public void destroyItem(ViewGroup collection, int position, Object view) {
        collection.removeView((View) view);
    }
    
    0 讨论(0)
提交回复
热议问题