Search code examples
androidandroid-viewpagerandroidxandroid-viewpager2

Proper implementation of ViewPager2 in Android


I came to know about ViewPager2 and tried to implement it, but didn't find any proper example.

Can anyone tell me how can I use it.

I am looking for proper usage, not an example.


Solution

  • UPDATE 7

    Check : Migrate from ViewPager to ViewPager2

    Check : Create swipe views with tabs using ViewPager2

    UPDATE 6

    Check out my answer if you want to implement Carousel using View Pager2

    UPDATE 5

    How to use TabLayout with ViewPager2

    SAMPLE CODE

    Use below dependencies

    implementation 'com.google.android.material:material:1.1.0-alpha08'
    implementation 'androidx.viewpager2:viewpager2:1.0.0-beta02'
    

    SAMPLE CODE

    XMl layout

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.coordinatorlayout.widget.CoordinatorLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
        <com.google.android.material.appbar.AppBarLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
    
            <androidx.appcompat.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    android:background="?attr/colorPrimary"
                    app:layout_scrollFlags="scroll|enterAlways"
                    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
    
            <com.google.android.material.tabs.TabLayout
                    android:id="@+id/tabs"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"/>
        </com.google.android.material.appbar.AppBarLayout>
    
        <androidx.viewpager2.widget.ViewPager2
                android:id="@+id/viewpager"
                app:layout_anchor="@id/tabs"
                app:layout_anchorGravity="bottom"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
        />
    
    
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    

    Activity

    import androidx.appcompat.app.AppCompatActivity
    import android.os.Bundle
    import kotlinx.android.synthetic.main.activity_main.*
    import com.google.android.material.tabs.TabLayoutMediator
    
    import com.google.android.material.tabs.TabLayout
    
    
    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
    //        setSupportActionBar(toolbar)
            viewpager.adapter = AppViewPagerAdapter(supportFragmentManager, lifecycle)
    
            TabLayoutMediator(tabs, viewpager, object : TabLayoutMediator.OnConfigureTabCallback {
                override fun onConfigureTab(tab: TabLayout.Tab, position: Int) {
                    // Styling each tab here
                    tab.text = "Tab $position"
                }
            }).attach()
    
    
        }
    }
    

    OUTPUT

    TabLayout with ViewPager2

    From Docs

    ViewPager2

    New features

    • Right-to-left (RTL) layout support
    • Vertical orientation support
    • notifyDataSetChanged fully functional

    API changes

    • FragmentStateAdapter replaces FragmentStatePagerAdapter
    • RecyclerView.Adapter replaces PagerAdapter
    • registerOnPageChangeCallback replaces addPageChangeListener

    SAMPLE CODE

    add the latest dependencies for ViewPager2

    implementation 'androidx.viewpager2:viewpager2:1.0.0-alpha01'
    

    layout

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
    
        <androidx.viewpager2.widget.ViewPager2
            android:id="@+id/view_pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
    </LinearLayout>
    

    activity

    import android.os.Bundle;
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.viewpager2.widget.ViewPager2;
    
    import java.util.ArrayList;
    
    public class MyActivity extends AppCompatActivity {
    
        ViewPager2 myViewPager2;
        MyAdapter MyAdapter;
        private ArrayList<String> arrayList = new ArrayList<>();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_my);
    
            myViewPager2 = findViewById(R.id.view_pager);
    
            arrayList.add("Item 1");
            arrayList.add("Item 2");
            arrayList.add("Item 3");
            arrayList.add("Item 4");
            arrayList.add("Item 5");
    
            MyAdapter = new MyAdapter(this, arrayList);
    
    
            myViewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);
    
            myViewPager2.setAdapter(MyAdapter);
        }
    }
    

    MyAdapter

    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    import androidx.annotation.NonNull;
    import androidx.recyclerview.widget.RecyclerView;
    
    import java.util.ArrayList;
    
    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
    
        private Context context;
        private ArrayList<String> arrayList = new ArrayList<>();
    
        public MyAdapter(Context context, ArrayList<String> arrayList) {
            this.context = context;
            this.arrayList = arrayList;
        }
    
        @NonNull
        @Override
        public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);
            return new MyViewHolder(view);
        }
    
        @Override
        public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
            holder.tvName.setText(arrayList.get(position));
        }
    
        @Override
        public int getItemCount() {
            return arrayList.size();
        }
    
        public class MyViewHolder extends RecyclerView.ViewHolder {
            TextView tvName;
    
            public MyViewHolder(@NonNull View itemView) {
                super(itemView);
                tvName = itemView.findViewById(R.id.tvName);
            }
        }
    }
    

    New features

    now we need to use ViewPager2.OnPageChangeCallback() to get Swipe event of ViewPager2

    SAMPLE CODE

        myViewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                super.onPageScrolled(position, positionOffset, positionOffsetPixels);
            }
    
            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);
    
                Log.e("Selected_Page", String.valueOf(position));
            }
    
            @Override
            public void onPageScrollStateChanged(int state) {
                super.onPageScrollStateChanged(state);
            }
        });
    

    we can set Orientation using myViewPager2.setOrientation()

    SAMPLE CODE

    For HORIZONTAL Orientation use

    myViewPager2.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
    

    For VERTICAL Orientation use

    myViewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);
    

    We can use notifyDataSetChanged same as we are using in RecyclerView.Adapter

    SAMPLE CODE to add new item

        btnAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                arrayList.add("New ITEM ADDED");
                MyAdapter.notifyDataSetChanged();
            }
        });
    

    SAMPLE CODE to remove new item

        btnRemove.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                arrayList.remove(3);
                MyAdapter.notifyItemRemoved(3);
            }
        });
    

    UPDATE

    Try this if you want to use Fragment with ViewPager2

    First create a ViewPagerFragmentAdapter class which extends FragmentStateAdapter

    import java.util.ArrayList;
    import androidx.annotation.NonNull;
    import androidx.fragment.app.Fragment;
    import androidx.fragment.app.FragmentManager;
    import androidx.viewpager2.adapter.FragmentStateAdapter;
    
    public class ViewPagerFragmentAdapter extends FragmentStateAdapter {
    
        private ArrayList<Fragment> arrayList = new ArrayList<>();
    
        public ViewPagerFragmentAdapter(@NonNull FragmentManager fragmentManager) {
            super(fragmentManager);
        }
    
        @NonNull
        @Override
        public Fragment getItem(int position) {
            return arrayList.get(position);
        }
    
        public void addFragment(Fragment fragment) {
            arrayList.add(fragment);
        }
    
        @Override
        public int getItemCount() {
            return arrayList.size();
        }
    }
    

    Now use like this in your activity

    import androidx.annotation.Nullable;
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.viewpager2.widget.ViewPager2;
    import neel.com.bottomappbar.R;
    
    public class MainActivity extends AppCompatActivity {
    
        ViewPager2 myViewPager2;
        ViewPagerFragmentAdapter myAdapter;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            myViewPager2 = findViewById(R.id.view_pager);
    
            myAdapter = new ViewPagerFragmentAdapter(getSupportFragmentManager());
    
            // add Fragments in your ViewPagerFragmentAdapter class
            myAdapter.addFragment(new FragmentOne());
            myAdapter.addFragment(new Fragmenttwo());
            myAdapter.addFragment(new FragmentThree());
    
            // set Orientation in your ViewPager2
            myViewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);
    
            myViewPager2.setAdapter(myAdapter);
    
        }
    
    }
    

    for more information check this

    UPDATE 2

    Version 1.0.0-alpha02

    New features

    • Ability to disable user input (setUserInputEnabled, isUserInputEnabled)

    API changes

    • ViewPager2 class final

    Bug fixes

    • FragmentStateAdapter stability fixes

    SAMPLE CODE to disable swiping in viewpager2

    myViewPager2.setUserInputEnabled(false);// SAMPLE CODE to disable swiping in viewpager2
    
    
    myViewPager2.setUserInputEnabled(true);//SAMPLE CODE to enable swiping in viewpager2
    

    UPDATE 3

    Version 1.0.0-alpha03

    New features

    • Ability to programmatically scroll ViewPager2: fakeDragBy(offsetPx).

    API changes

    • FragmentStateAdapter now requires a Lifecycle object. Two utility constructors added to obtain it from the host FragmentActivity or the host Fragment

    SAMPLE CODE

    ViewPagerFragmentAdapter

    import java.util.ArrayList;
    import androidx.annotation.NonNull;
    import androidx.fragment.app.Fragment;
    import androidx.fragment.app.FragmentManager;
    import androidx.lifecycle.Lifecycle;
    import androidx.viewpager2.adapter.FragmentStateAdapter;
    
    public class ViewPagerFragmentAdapter extends FragmentStateAdapter {
    
        private ArrayList<Fragment> arrayList = new ArrayList<>();
    
    
        public ViewPagerFragmentAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {
            super(fragmentManager, lifecycle);
        }
    
        @NonNull
        @Override
        public Fragment getItem(int position) {
            return arrayList.get(position);
        }
    
        public void addFragment(Fragment fragment) {
            arrayList.add(fragment);
        }
    
        @Override
        public int getItemCount() {
            return arrayList.size();
        }
    }
    

    MainActivity code

    import android.os.Bundle;
    import androidx.annotation.Nullable;
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.viewpager2.widget.ViewPager2;
    import neel.com.bottomappbar.R;
    
    public class MainActivity extends AppCompatActivity {
    
        ViewPager2 myViewPager2;
        ViewPagerFragmentAdapter myAdapter;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            myViewPager2=findViewById(R.id.view_pager);
            myAdapter = new ViewPagerFragmentAdapter(getSupportFragmentManager(), getLifecycle());
    
            // add Fragments in your ViewPagerFragmentAdapter class
            myAdapter.addFragment(new FragmentOne());
            myAdapter.addFragment(new Fragmenttwo());
            myAdapter.addFragment(new FragmentThree());
    
            myViewPager2.setOrientation(ViewPager2.ORIENTATION_VERTICAL);
    
            myViewPager2.setAdapter(myAdapter);
        }
    }
    

    UPDATE 4

    Version 1.0.0-alpha05 New features

    • ItemDecorator introduced with a behaviour consistent with RecyclerView.
    • MarginPageTransformer introduced to provide an ability to create space between pages (outside of page inset).
    • CompositePageTransformer introduced to provide an ability to combine multiple PageTransformers

    API changes

    • FragmentStateAdapter#getItem method renamed to FragmentStateAdapter#createFragment - previous method name has proven to be a source of bugs in the past.
    • OFFSCREEN_PAGE_LIMIT_DEFAULT value changed from 0 to -1. No need for a client code change if the OFFSCREEN_PAGE_LIMIT_DEFAULTconstant used.

    SAMPLE CODE

    Activity code

    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.fragment.app.Fragment;
    import androidx.recyclerview.widget.RecyclerView;
    import androidx.viewpager2.widget.MarginPageTransformer;
    import androidx.viewpager2.widget.ViewPager2;
    import neel.com.bottomappbar.R;
    
    public class MainActivity extends AppCompatActivity {
    
        ViewPager2 myViewPager2;
        ViewPagerFragmentAdapter myAdapter;
        private ArrayList<Fragment> arrayList = new ArrayList<>();
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            myViewPager2 = findViewById(R.id.myViewPager2);
    
            // add Fragments in your ViewPagerFragmentAdapter class
            arrayList.add(new FragmentOne());
            arrayList.add(new Fragmenttwo());
            arrayList.add(new FragmentThree());
    
            myAdapter = new ViewPagerFragmentAdapter(getSupportFragmentManager(), getLifecycle());
            // set Orientation in your ViewPager2
            myViewPager2.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
    
            myViewPager2.setAdapter(myAdapter);
    
            myViewPager2.setPageTransformer(new MarginPageTransformer(1500));
    
    
        }
    }
    

    ViewPagerFragmentAdapter

    import java.util.ArrayList;
    import androidx.annotation.NonNull;
    import androidx.fragment.app.Fragment;
    import androidx.fragment.app.FragmentManager;
    import androidx.lifecycle.Lifecycle;
    import androidx.viewpager2.adapter.FragmentStateAdapter;
    
    public class ViewPagerFragmentAdapter extends FragmentStateAdapter {
    
        private ArrayList<Fragment> arrayList = new ArrayList<>();
    
    
        public ViewPagerFragmentAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {
            super(fragmentManager, lifecycle);
        }
    
        @NonNull
        @Override
        public Fragment createFragment(int position) {
            switch (position) {
                case 0:
                    return new FragmentOne();
                case 1:
                    return new Fragmenttwo();
                case 2:
                    return new FragmentThree();
    
            }
            return null;
        }
    
        @Override
        public int getItemCount() {
            return 3;
        }
    }