Implementing a Meizu-style Banner View with ViewPager

Creating a Meizu-style Banner with ViewPager

Banner advertising positions are critical in mobile applications due to their revenue generation potential. High-traffic applications can generate substantial daily income from well-designed banners. This guide demonstrates how to implement a banner view similar to Meizu's implementation, which displays portions of adjacent pages during transitions.

Core Implementation Approach

The solution uses ViewPager with custom transformations to achieve the visual effect. The key technique involves manipulating the clipping behavior of the parent contianer and applying scale animations during page transitions.

Layout Configuration for Multi-Page Display

Enable the ViewPager to display multiple pages simultaneously by setting clipChildren="false" in the parent layout and applying margins to the ViewPager:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipChildren="false"
    android:orientation="vertical">
    
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/content_pager"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_marginLeft="30dp"
        android:layout_marginRight="30dp" />
</LinearLayout>

This configuration allows adjacent pages to remain visible outside the ViewPager's bounds.

Custom Page Transformation Animation

Implement a scale animation using ViewPager.PageTransformer to create the zoom effect during transitions:

public class ScalePageTransformer implements ViewPager.PageTransformer {
    private static final float MINIMUM_SCALE = 0.85f;
    
    @Override
    public void transformPage(View view, float scrollPosition) {
        if (scrollPosition < -1.0f) {
            view.setScaleY(MINIMUM_SCALE);
        } else if (scrollPosition <= 1.0f) {
            float scaleValue = Math.max(MINIMUM_SCALE, 1.0f - Math.abs(scrollPosition));
            view.setScaleY(scaleValue);
        } else {
            view.setScaleY(MINIMUM_SCALE);
        }
    }
}

Apply the transformer to the ViewPager:

ViewPager pager = findViewById(R.id.content_pager);
pager.setPageTransformer(true, new ScalePageTransformer());

Implementing Infinite Scrolling

Use the large number approach for seamless infinite scrolling by returning Integer.MAX_VALUE from the adapter's getCount() method:

public class InfiniteAdapter extends PagerAdapter {
    private List<ImageView> imageResources;
    
    @Override
    public int getCount() {
        return Integer.MAX_VALUE;
    }
    
    private int getActualCount() {
        return imageResources.size();
    }
    
    private int calculateRealPosition(int adapterPosition) {
        return adapterPosition % getActualCount();
    }
    
    @Override
    public Object instantiateItem(ViewGroup container, int adapterPosition) {
        int actualPosition = calculateRealPosition(adapterPosition);
        ImageView currentImage = imageResources.get(actualPosition);
        container.addView(currentImage);
        return currentImage;
    }
    
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((ImageView) object);
    }
    
    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }
}

Initialize the ViewPager to start near the middle of the large range:

private int getInitialPosition() {
    int startingPoint = Integer.MAX_VALUE / 2;
    while (startingPoint % adapter.getActualCount() != 0) {
        startingPoint++;
    }
    return startingPoint;
}

pager.setCurrentItem(getInitialPosition());

Auto-Scrollnig Implementation

Implement automatic scrolling using a Handler:

private final Handler scrollHandler = new Handler();
private final Runnable autoScrollTask = new Runnable() {
    @Override
    public void run() {
        if (isAutoScrollingEnabled) {
            int currentIndex = pager.getCurrentItem();
            currentIndex++;
            pager.setCurrentItem(currentIndex, true);
            scrollHandler.postDelayed(this, SCROLL_DELAY);
        }
    }
};

public void startAutoScroll() {
    isAutoScrollingEnabled = true;
    scrollHandler.postDelayed(autoScrollTask, SCROLL_DELAY);
}

public void stopAutoScroll() {
    isAutoScrollingEnabled = false;
    scrollHandler.removeCallbacks(autoScrollTask);
}

Complete Banner Component

Combine these elements into a reusable CustomBannerView component with configurable modes:

public class CustomBannerView extends LinearLayout {
    private ViewPager contentPager;
    private boolean enableMeizuEffect = true;
    private boolean enableInfiniteScroll = true;
    
    public void setDisplayMode(boolean meizuEffect, boolean infiniteScroll) {
        this.enableMeizuEffect = meizuEffect;
        this.enableInfiniteScroll = infiniteScroll;
        applyConfiguration();
    }
    
    private void applyConfiguration() {
        if (enableMeizuEffect) {
            contentPager.setPageTransformer(true, new ScalePageTransformer());
        }
        
        if (enableInfiniteScroll) {
            setupInfiniteScrolling();
        }
    }
}

Usage Example

<com.example.CustomBannerView
    android:id="@+id/banner_view"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    app:meizu_effect="true"
    app:infinite_scroll="true" />
CustomBannerView banner = findViewById(R.id.banner_view);
banner.setPages(imageList, new PageViewHolderCreator() {
    @Override
    public PageViewHolder createHolder() {
        return new ImagePageViewHolder();
    }
});

@Override
protected void onResume() {
    super.onResume();
    banner.startAutoScroll();
}

@Override
protected void onPause() {
    super.onPause();
    banner.stopAutoScroll();
}

Tags: Android ViewPager Banner UI Components animation

Posted on Fri, 08 May 2026 07:14:35 +0000 by pojr