Thursday, December 5, 2019

Carousel Effect in Android using View Pager.


What is the carousel effect?

The carousel is a slideshow for cycling through a series of content, built with CSS 3D transforms and a bit of JavaScript. It works with a series of images, text, or custom markup.

What is View Pager?
A layout manager that allows the user to flip left and right through pages of data. You supply an implementation of a PagerAdapter to generate the pages that the view shows.
ViewPager is most often used in conjunction with Fragment, which is a convenient way to supply and manage the lifecycle of each page. There are standard adapters implemented for using fragments with the ViewPager, which cover the most common use cases. These are FragmentPagerAdapter and FragmentStatePagerAdapter; each of these classes has a sample code showing how to build a full user interface with them.
Using this blog we are going to perform carousel effect in android using view pager. 
We need 2 view pager to perform the carousel effect with the help of a custom class.
Here is xml of the activity.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center" />

    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#B07986CB" />


    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewpagerTop"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:layout_gravity="center"
        android:clipToPadding="false"
        android:paddingLeft="50dp"
        android:paddingTop="100dp"
        android:paddingRight="50dp"
        android:paddingBottom="100dp" />

</androidx.constraintlayout.widget.ConstraintLayout>
And here is Activity Class. And pager_margin is 20dp in the below code.
public class SampleActivity extends AppCompatActivity {

    ViewPager mPager, viewpagerTop;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample);

        getSupportActionBar().setTitle("");

        mPager = findViewById(R.id.pager);
        viewpagerTop = findViewById(R.id.viewpagerTop);
        viewpagerTop.setClipChildren(false);
        viewpagerTop.setPageMargin(getResources().getDimensionPixelOffset(R.dimen.pager_margin));
        viewpagerTop.setOffscreenPageLimit(3);
        viewpagerTop.setPageTransformer(false, new CarouselEffectTransformer(this)); // Set transformer

        MyViewAdapter pagerAdapter = new MyViewAdapter(this);
        viewpagerTop.setAdapter(pagerAdapter);
        mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                int width = mPager.getWidth();
                mPager.scrollTo((int) (width * position + width * positionOffset), 0);
            }

            @Override
            public void onPageSelected(int position) {

            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }
}
And here is MyViewAdapter Class.
 public class MyViewAdapter extends PagerAdapter {
        private LayoutInflater layoutInflater;

        public MyViewAdapter(Context context) {
            layoutInflater = LayoutInflater.from(context);
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            View view = layoutInflater.inflate(R.layout.item, container, false);
            container.addView(view, 0);
            return view;
        }

        @Override
        public int getCount() {
            return 10;
        }

        @Override
        public boolean isViewFromObject(View view, Object obj) {

            return view == obj;
        }


        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            View view = (View) object;
            container.removeView(view);
        }
    }
And here is item.xml.
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/image" />
And here is CarouselEffectTransformer Class.
class CarouselEffectTransformer implements ViewPager.PageTransformer {

        private int maxTranslateOffsetX;
        private ViewPager viewPager;

        public CarouselEffectTransformer(Context context) {
            this.maxTranslateOffsetX = dp2px(context, 180);
        }

        public void transformPage(View view, float position) {
            if (viewPager == null) {
                viewPager = (ViewPager) view.getParent();
            }

            int leftInScreen = view.getLeft() - viewPager.getScrollX();
            int centerXInViewPager = leftInScreen + view.getMeasuredWidth() / 2;
            int offsetX = centerXInViewPager - viewPager.getMeasuredWidth() / 2;
            float offsetRate = (float) offsetX * 0.38f / viewPager.getMeasuredWidth(); // change 0.38 accordingly to your requirment
            float scaleFactor = 1 - Math.abs(offsetRate);

            if (scaleFactor > 0) {
                view.setScaleX(scaleFactor);
                view.setScaleY(scaleFactor);
                view.setTranslationX(-maxTranslateOffsetX * offsetRate);
                //ViewCompat.setElevation(view, 0.0f);
            }
            ViewCompat.setElevation(view, scaleFactor);

        }

        /**
         * Dp to pixel conversion
         */
        private int dp2px(Context context, float dipValue) {
            float m = context.getResources().getDisplayMetrics().density;
            return (int) (dipValue * m + 0.5f);// gap between item
        }

    }
And Finally the Output of the code.

That is all. If any help related to this post please comment.
Thank you, guys.
Enjoy coding.

No comments:

Post a Comment