Android Carousel View using ViewPager
This post is a demo for creating a carousel in android by using ViewPager. It involves ViewPager of course, as well as custom compound view, drawable selector xml, ViewPager adapter and Fragment. Some improvement to this would be to add custom animation to the ViewPager and adjust the ViewPager sliding speed.
1. view_pager_carousel_view.xml, the layout for the carousel view. It has a ViewPager for holding the views in the carousel, and a LinearLayout for holding the view indicators in the carousel.
<?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android"> <android.support.v4.view.ViewPager android:id="@+id/vp_carousel" android:layout_width="match_parent" android:layout_height="200dp"/> <LinearLayout android:id="@+id/ll_page_indicator_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:layout_gravity="center_horizontal" android:layout_alignBottom="@+id/vp_carousel" android:layout_marginBottom="10dp" android:orientation="horizontal"/> </merge>
2. selector_carousel_page_indicator.xml, the drawable for the carousel indicators, those little bullets/circles at the bottom on the carousel view. Dark color when selected, gray when not.
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="true" > <shape android:shape="oval"> <solid android:color="@android:color/background_dark" /> <size android:width="6dp" android:height="6dp" /> </shape> </item> <item> <shape android:shape="oval"> <solid android:color="@android:color/darker_gray" /> <size android:width="6dp" android:height="6dp" /> </shape> </item> </selector>
3. view_pager_carousel_fragment.xml, the layout for each individual view in the carousel. For demo puporse, there is only an image in it.
<?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"> <ImageView android:id="@+id/iv_carousel_image" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop"/> </LinearLayout>
4. ViewPagerCarouselFragment.java, the Fragment class for the each individual view in the carousel.
public class ViewPagerCarouselFragment extends Fragment { public static final String IMAGE_RESOURCE_ID = "image_resource_id"; private ImageView ivCarouselImage; private int imageResourceId; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.view_pager_carousel_fragment, container, false); ivCarouselImage = (ImageView) v.findViewById(R.id.iv_carousel_image); imageResourceId = getArguments().getInt(IMAGE_RESOURCE_ID, R.drawable.car1); // default to car1 image resource ivCarouselImage.setImageResource(imageResourceId); v.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(getContext(), "image: " + imageResourceId, Toast.LENGTH_SHORT).show(); } }); return v; } }
5. ViewPagerCarouselAdapter.java, the adapter for the ViewPager.
public class ViewPagerCarouselAdapter extends FragmentStatePagerAdapter { private int[] imageResourceIds; public ViewPagerCarouselAdapter(FragmentManager fm, int[] imageResourceIds) { super(fm); this.imageResourceIds = imageResourceIds; } @Override public Fragment getItem(int position) { Bundle bundle = new Bundle(); bundle.putInt(ViewPagerCarouselFragment.IMAGE_RESOURCE_ID, imageResourceIds[position]); ViewPagerCarouselFragment frag = new ViewPagerCarouselFragment(); frag.setArguments(bundle); return frag; } @Override public int getCount() { return (imageResourceIds == null) ? 0: imageResourceIds.length; } }
6. ViewPagerCarouselView.java, the compound view class for the carousel view. This class will be used to create for carousel view.
public class ViewPagerCarouselView extends RelativeLayout { private FragmentManager fragmentManager; // FragmentManager for managing the fragments withing the ViewPager private ViewPager vpCarousel; // ViewPager for the Carousel view private LinearLayout llPageIndicatorContainer; // Carousel view item indicator, the little bullets at the bottom of the carousel private ArrayList<ImageView> carouselPageIndicators; // Carousel view item, the little bullet at the bottom of the carousel private int [] imageResourceIds; // Carousel view background image private long carouselSlideInterval; // Carousel view item sliding interval private Handler carouselHandler; // Carousel view item sliding interval automation handler public ViewPagerCarouselView (Context context) { super(context); initView(context); } public ViewPagerCarouselView(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } public ViewPagerCarouselView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initView(context); } public void initView(Context context) { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); inflater.inflate(R.layout.view_pager_carousel_view, this); } @Override protected void onFinishInflate() { super.onFinishInflate(); vpCarousel = (ViewPager) this.findViewById(R.id.vp_carousel); llPageIndicatorContainer = (LinearLayout) this.findViewById(R.id.ll_page_indicator_container); } /** * Set the data and initialize the carousel view * @param fragmentManager * @param imageResourceIds * @param carouselSlideInterval */ public void setData(FragmentManager fragmentManager, int [] imageResourceIds, long carouselSlideInterval) { this.fragmentManager = fragmentManager; this.imageResourceIds = imageResourceIds; this.carouselSlideInterval = carouselSlideInterval; initData(); initCarousel(); initCarouselSlide(); } /** * Initialize the data for the carousel */ private void initData() { carouselPageIndicators = new ArrayList<>(); for (int i = 0; i < imageResourceIds.length; i++) { ImageView obj = new ImageView(getContext()); obj.setImageResource(R.drawable.selector_carousel_page_indicator); obj.setPadding(0, 0, 5, 0); // left, top, right, bottom llPageIndicatorContainer.addView(obj); carouselPageIndicators.add(obj); } } /** * Initialize carousel views, each item in the carousel view is a fragment */ private void initCarousel() { carouselPageIndicators.get(0).setSelected(true); // Update the carousel page indicator on change vpCarousel.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { for (int i = 0; i < carouselPageIndicators.size(); i++) { if (i == position) carouselPageIndicators.get(position).setSelected(true); else carouselPageIndicators.get(i).setSelected(false); } } @Override public void onPageScrollStateChanged(int state) { } }); ViewPagerCarouselAdapter viewPagerCarouselAdapter = new ViewPagerCarouselAdapter(fragmentManager, imageResourceIds); vpCarousel.setPageTransformer(false, new CustomViewPageTransformer(CustomViewPageTransformer.TransformType.SLIDE_OVER)); vpCarousel.setAdapter(viewPagerCarouselAdapter); } /** * Handler to make the view pager to slide automatically */ private void initCarouselSlide() { final int nCount = imageResourceIds.length; try { carouselHandler = new Handler(); carouselHandler.postDelayed(new Runnable() { @Override public void run() { int curPos = vpCarousel.getCurrentItem(); curPos++; if (curPos == nCount) curPos = 0; vpCarousel.setCurrentItem(curPos, true); carouselHandler.postDelayed(this, carouselSlideInterval); } }, carouselSlideInterval); } catch (Exception e) { Log.d("MainActivity", e.getMessage()); } } public void onDestroy() { if (carouselHandler != null) carouselHandler.removeCallbacksAndMessages(null); // remove call backs to prevent memory leaks } }
7. activity_main.xml, finally, we have all the things set up to support the carousel and we can use it in the layout file, just like how you would use other views such as ListView, RecyclerView, CardView, Button, TextView, etc.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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" tools:context="com.sample.viewpagercarousel.MainActivity"> <com.sample.viewpagercarousel.ViewPagerCarouselView android:id="@+id/carousel_view" android:layout_width="match_parent" android:layout_height="wrap_content"></com.sample.viewpagercarousel.ViewPagerCarouselView> </RelativeLayout>
8. MainActivity.java
MainActivity -> ViewPagerCarouselView -> ViewPagerCarouselAdapter -> ViewPagerCarouselFragment
public class MainActivity extends AppCompatActivity { ViewPagerCarouselView viewPagerCarouselView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); long carouselSlideInterval = 3000; // 3 SECONDS int [] imageResourceIds = {R.drawable.car1, R.drawable.car2, R.drawable.car3, R.drawable.car4, R.drawable.car5, R.drawable.car6}; viewPagerCarouselView = (ViewPagerCarouselView) findViewById(R.id.carousel_view); viewPagerCarouselView.setData(getSupportFragmentManager(), imageResourceIds, carouselSlideInterval); } @Override protected void onDestroy() { super.onDestroy(); viewPagerCarouselView.onDestroy(); } }
Search within Codexpedia
Search the entire web