BGABanner-Android

repository·master·Indexed 26 days ago

https://github.com/bingoogolapple/bgabanner-android

An Android library providing a highly customizable banner/slider component for onboarding screens or advertisements. It supports infinite looping, various transition animations, and multiple data source configurations including Adapters, View collections, and image resources. The library is migrated to AndroidX and requires minSdk 21.

Tokens
5K
Snippets
8
Records
17
Agent score
38%

What's inside bgabanner-android

  1. Understand the BGABanner architecture

    master

    BGABanner is a composite custom view that extends RelativeLayout. Instead of inheriting from ViewPager, it uses a composition pattern to wrap a BGAViewPager (a custom ViewPager) along with other UI elements like indicators, text tips, and placeholder images. This design allows indicators and text to be positioned freely as sibling views within the RelativeLayout container without interfering with the ViewPager logic.

    Core Components:

    • BGAViewPager: A custom ViewPager that handles auto-play callbacks, user scroll permissions, and custom transition durations.
    • mPointContainerRl: A RelativeLayout container for indicators (dots or numbers) and text tips (mTipTv).
    • mPlaceholderIv: An ImageView used as a placeholder while network images are loading.
    • BGAPageTransformer: An abstract class used to define custom page transition animations.
    • BGAOnNoDoubleClickListener: A utility used to prevent double-click events on banner items.
  2. Memory Management and Lifecycle Best Practices

    master

    The library follows several patterns to ensure stability and prevent memory leaks:

    • Auto-play Safety: Uses WeakReference within AutoPlayTask to prevent the Runnable from holding a strong reference to the BGABanner, allowing the Activity/Fragment to be garbage collected.
    • Lifecycle Awareness: Automatic playback and animations are tied to the view's visibility. They start in onAttachedToWindow or onVisibilityChanged(VISIBLE) and stop in onDetachedFromWindow or when the view becomes invisible.
    • Image Loading Optimization: To prevent OutOfMemoryError (OOM), the library uses inJustDecodeBounds to check image dimensions, calculates an inSampleSize for downsampling, and can fallback to RGB_565 configuration or retry with half-sized dimensions if an OOM occurs.
  3. Add BGABanner to layout files

    master

    Include the BGABanner view in your XML layout. You can use custom attributes to configure page change duration, auto-play settings, indicator styles, and transition effects.

    <cn.bingoogolapple.bgabanner.BGABanner
        android:id="@+id/banner_guide_content"
        style="@style/MatchMatch"
        app:banner_pageChangeDuration="1000"
        app:banner_pointAutoPlayAble="false"
        app:banner_pointContainerBackground="@android:color/transparent"
        app:banner_pointDrawable="@drawable/bga_banner_selector_point_hollow"
        app:banner_pointTopBottomMargin="15dp"
        app:banner_transitionEffect="alpha" />
  4. Manage Banner Lifecycle and Visibility

    master

    To prevent memory leaks and unnecessary battery consumption, BGABanner automatically manages its auto-play task based on the view's lifecycle and visibility:

    • Start Auto-play: Triggered when the view is attached to a window (onAttachedToWindow) or becomes visible (onVisibilityChanged(VISIBLE)).
    • Stop Auto-play: Triggered when the view is detached (onDetachedFromWindow) or becomes invisible (onVisibilityChanged(INVISIBLE/GONE)).

    Note for RecyclerView users: If the banner is inside a RecyclerView, the library includes a fix for potential UI stutters when a cell becomes visible again. If the banner was left at a partial scroll position, it performs a quick reset (setCurrentItem(-1) followed by setCurrentItem(+1)) to force a clean layout.

  5. Configure BGABanner data sources

    master

    There are three primary ways to provide data to the banner depending on your use case:

    1. Using an Adapter (Best for network images or infinite loop with < 3 pages): Pass a data model and an adapter to handle item binding (e.g., using Glide).
    2. Using a View collection (Best for custom layouts): Pass a list of pre-inflated Views.
    3. Using Image Resources (Best for simple image-only banners): Pass resource IDs and a BGALocalImageSize object.
    // Method 1: Adapter with data models (e.g., for Glide)
    mContentBanner.setAdapter(new BGABanner.Adapter<ImageView, String>() {
        @Override
        public void fillBannerItem(BGABanner banner, ImageView itemView, String model, int position) {
            Glide.with(MainActivity.this)
                    .load(model)
                    .placeholder(R.drawable.holder)
                    .error(R.drawable.holder)
                    .centerCrop()
                    .dontAnimate()
                    .into(itemView);
        }
    });
    mContentBanner.setData(Arrays.asList("URL1", "URL2"), Arrays.asList("Text1", "Text2"));
    
    // Method 2: Direct View list
    List<View> views = new ArrayList<>();
    views.add(View.inflate(context, R.layout.layout_guide_one, null));
    mContentBanner.setData(views);
    
    // Method 3: Image Resource IDs
    BGALocalImageSize localImageSize = new BGALocalImageSize(720, 1280, 320, 640);
    mContentBanner.setData(localImageSize, ImageView.ScaleType.CENTER_CROP, 
            R.drawable.img1, R.drawable.img2);
  6. Implement a minimal BGABanner setup

    master

    To use BGABanner, add the view to your XML layout and then configure the adapter and data in your Activity or Fragment. The setData method is the primary entry point for populating the banner.

    1. XML Layout:
    <cn.bingoogolapple.bgabanner.BGABanner
        android:id="@+id/banner"
        android:layout_width="match_parent"
        android:layout_height="180dp" />
    1. Java Implementation: Set an adapter to handle how each item is rendered (e.g., using Glide to load images) and then call setData with your data list and optional tip strings.
    // 1. In your layout, place BGABanner
    // <cn.bingoogolapple.bgabanner.BGABanner
    //     android:id="@+id/banner"
    //     android:layout_width="match_parent"
    //     android:layout_height="180dp" />
    
    // 2. Populate data in code
    List<String> tips = Arrays.asList("提示一", "提示二", "提示三");
    banner.setAdapter(new BGABanner.Adapter<ImageView, String>() {
        @Override
        public void fillBannerItem(BGABanner banner, ImageView itemView, String model, int position) {
            // Use Glide or similar to load network images into itemView
        }
    });
    banner.setData(Arrays.asList("url1", "url2", "url3"), tips);
  7. Set data in BGABanner using setData()

    master

    To populate the banner with content, use the setData method. The library provides several overloads, but they all converge to a core method that accepts a list of views, a list of models, and a list of tip strings: setData(List<View> views, List<models> models, List<String> tips).

    Key behaviors during setData:

    • Reconstruction: Every call to setData reconstructs the BGAViewPager (removing the old one and creating a new one) to ensure a clean state.
    • Hacky Views for Small Lists: If auto-play is enabled but you have fewer than 3 pages, the library automatically creates hackyViews (copies of your real views) to ensure there are at least 3 pages. This prevents animation issues in the underlying ViewPager during infinite scrolling.
    • Placeholder Management: The library automatically handles the removal of placeholder images once real data is set.
  8. Implement Click Debouncing with BGAOnNoDoubleClickListener

    master

    To prevent rapid multiple clicks (e.g., accidental double-taps on a banner item), use BGAOnNoDoubleClickListener. This class implements a "throttle" pattern that only allows the first event within a specific time window (defaulting to 1 second) to pass through.

    To use it, extend the class and implement the onNoDoubleClick(View v) method.

  9. Configure Page Transition Animations with PageTransformer

    master

    Custom animations are implemented using the PageTransformer interface. The transformPage(View page, float position) method provides a position value that drives the animation:

    • position == 0: The page currently being displayed.
    • position < 0: The page to the left.
    • position > 0: The page to the right.
    • position in range [-1, 1]: The page is within the visible viewport.

    To create a custom effect, implement the BGAPageTransformer abstract class and override methods like handleLeftPage, handleRightPage, or handleInvisiblePage. Use the position value to map to properties like alpha, scale, rotation, or translation.

    public void handleRightPage(View view, float position) {
        // Example: Fade out and scale down as the page moves right
        ViewCompat.setAlpha(view, 1 - position);
        float scale = mMinScale + (1 - mMinScale) * (1 - position);
        ViewCompat.setScaleX(view, scale);
        ViewCompat.setScaleY(view, scale);
    }
  10. Configure Enter and Skip buttons

    master

    Use setEnterSkipViewIdAndDelegate to link 'Enter' and 'Skip' UI controls. If a button does not exist, pass 0. The library manages the visibility and click prevention for these buttons.

    mContentBanner.setEnterSkipViewIdAndDelegate(R.id.btn_guide_enter, R.id.tv_guide_skip, new BGABanner.GuideDelegate() {
        @Override
        public void onClickEnterOrSkip() {
            startActivity(new Intent(GuideActivity.this, MainActivity.class));
            finish();
        }
    });