SmartRefreshLayout

repository·main·Indexed 12 days ago

https://github.com/scwang90/smartrefreshlayout

A highly customizable and performance-optimized Android pull-to-refresh framework. It supports various view types including RecyclerView, WebView, and AbsListView, and handles complex nested scrolling scenarios. Key features include multi-touch support, automatic load-more detection, customizable bounce animations, and multiple sliding modes (translation, stretch, fixed background, top-fixed, and full-screen). The framework is modularized into core, header, and footer components for v2.x/v3.x.

Tokens
20.8K
Snippets
32
Records
51
Agent score
97%

What's inside SmartRefreshLayout

  1. Overview of SmartRefreshLayout

    main

    SmartRefreshLayout is a powerful and stable Android pull-to-refresh framework. It is designed to be 'smart' by supporting various View types (including AbsListView, RecyclerView, WebView, etc.) and complex nested view structures. Unlike standard layouts, it inherits from ViewGroup to improve performance.

    Key features include:

    • Support for multi-touch and nested layouts (LinearLayout, FrameLayout, etc.).
    • Seamless scrolling synchronization with ListView and nested scrolling with CoordinatorLayout.
    • Automatic refresh and automatic load-more detection (detects inertial scrolling to the bottom).
    • Customizable bounce animations using interpolators.
    • Multiple sliding modes: translation, stretch, fixed background, top-fixed, and full-screen.
    • Support for AndroidX and horizontal refresh.
  2. Configure Header and Footer Priority

    main

    You can specify Headers and Footers using three different methods, which have different priority levels:

    1. Java/Kotlin Code (Highest Priority): Use setRefreshHeader() and setRefreshFooter() on the RefreshLayout instance. This overrides all other settings.
    2. XML Layout (Medium Priority): Define the Header and Footer as child views of SmartRefreshLayout in your XML. This enables Android Studio preview support.
    3. Global Settings (Lowest Priority): Set a default creator in your Application class using SmartRefreshLayout.setDefaultRefreshHeaderCreator() and SmartRefreshLayout.setDefaultRefreshFooterCreator(). This acts as a fallback if no header/footer is specified elsewhere.
    // 1. Highest Priority: Java Code
    refreshLayout.setRefreshHeader(new MaterialHeader(this).setShowBezierWave(true));
    
    // 2. Medium Priority: XML (See Basic Usage)
    
    // 3. Lowest Priority: Global Application Settings
    public class App extends Application {
        public void onCreate() {
            super.onCreate();
            SmartRefreshLayout.setDefaultRefreshHeaderCreator(new DefaultRefreshHeaderCreator() {
                @Override
                public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) {
                    return new ClassicsHeader(context).setSpinnerStyle(SpinnerStyle.Translate);
                }
            });
        }
    }
  3. How SmartRefreshLayout architecture works

    main

    SmartRefreshLayout is a highly customizable and extensible refresh framework. Its architecture consists of four main components:

    • RefreshLayout: Handles the core layout functionality, including measurement, touch event processing, and parameter settings.
    • RefreshHeader: An interface for handling events and displaying the top refresh header.
    • RefreshFooter: An interface for handling events and displaying the bottom loading footer.
    • RefreshContent: A unified wrapper for different content types, providing intelligent recognition for scrollability and rebound logic.
  4. Create a custom Header using automatic layout recognition

    main

    SmartRefreshLayout automatically identifies unknown layouts within its children to determine which view acts as the Header, the Content, or the Footer.

    To create a custom Header, simply place your desired view (e.g., a TextView or a GifImageView) as the first child of SmartRefreshLayout. The library will automatically treat it as the Header. You can further customize the Header's behavior using attributes like app:layout_srlSpinnerStyle and app:layout_srlBackgroundColor.

    <SmartRefreshLayout 
        xmlns:app="http://schemas.android.com/apk/res-auto"
        app:srlDragRate="0.7"
        app:srlHeaderMaxDragRate="1.3">
        
        <!-- This view is automatically recognized as the Header -->
        <pl.droidsonroids.gif.GifImageView
            android:layout_width="match_parent"
            android:layout_height="150dp"
            android:scaleType="centerCrop"
            android:src="@mipmap/gif_header_repast"
            app:layout_srlSpinnerStyle="Scale"
            app:layout_srlBackgroundColor="@android:color/transparent"/>
    
        <!-- This view is recognized as the Content -->
        <ListView
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
        <!-- This view is recognized as the Footer -->
        <ClassicsFooter/>
    
    </SmartRefreshLayout>
  5. Restore classic mode behavior

    main

    If you prefer the behavior of older versions (disabling features like over-scroll bounce, over-scroll drag, and elastic auto-load more), you can disable them via code or XML.

    Via Code: Use setEnableAutoLoadMore(false), setEnableOverScrollDrag(false), and setEnableOverScrollBounce(false).

    Via XML: Use the following attributes on the SmartRefreshLayout component:

    • app:srlEnableOverScrollDrag="false"
    • app:srlEnableAutoLoadMore="false"
    • app:srlEnableOverScrollBounce="false"
        refreshLayout.setEnableAutoLoadMore(false);
        refreshLayout.setEnableOverScrollDrag(false);
        refreshLayout.setEnableOverScrollBounce(false);
  6. Update package and class names for V 2.0.0

    main

    Version V 2.0.0 introduced breaking changes to the package and class naming conventions. If you are upgrading from a version prior to 2.0.0, you must update your imports:

    • Package Name: Change com.scwang.smartrefresh to com.scwang.smart.refresh.
    • Listener: smartrefresh.layout.listener.OnMultiPurposeListener is now smart.refresh.layout.listener.OnMultiListener.
    • Simple Listener: smartrefresh.layout.listener.SimpleMultiListener is now smart.refresh.layout.simple.SimpleMultiListener.
  7. Set Global Default Properties and Headers

    main

    To avoid repetitive configuration, you can set global defaults in your Application class. This is useful for applying a consistent theme or header style across all SmartRefreshLayout instances in your app.

    Note: Global settings have the lowest priority and will be overridden by specific instance settings or XML attributes.

    public class App extends Application {
        static {
            // Set global default configuration
            SmartRefreshLayout.setDefaultRefreshInitializer(new DefaultRefreshInitializer() {
                @Override
                public void initialize(@NonNull Context context, @NonNull RefreshLayout layout) {
                    layout.setReboundDuration(1000);
                    layout.setFooterHeight(100);
                    layout.setPrimaryColorsId(R.color.colorPrimary, android.R.color.white);
                }
            });
    
            // Set global default Header
            SmartRefreshLayout.setDefaultRefreshHeaderCreator(new DefaultRefreshHeaderCreator() {
                @Override
                public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) {
                    layout.setEnableHeaderTranslationContent(false);
                    return new MaterialHeader(context).setColorSchemeResources(R.color.colorRed, R.color.colorGreen, R.color.colorBlue);
                }
            });
        }
    }
  8. Set Global Header and Footer via Application

    main

    You can define a default Header and Footer globally for all SmartRefreshLayout instances in your application. This is done by implementing setDefaultRefreshHeaderCreator and setDefaultRefreshFooterCreator within a static block in your Application class.

    Note: This method has the lowest priority. If you use Method 2 (XML) or Method 3 (Java code) for a specific layout, those settings will override these global defaults.

    public class App extends Application {
        // static block prevents memory leaks
        static {
            // Set global Header creator
            SmartRefreshLayout.setDefaultRefreshHeaderCreator(new DefaultRefreshHeaderCreator() {
                    @Override
                    public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) {
                        layout.setPrimaryColorsId(R.color.colorPrimary, android.R.color.white); // Set global theme colors
                        return new ClassicsHeader(context);
                    }
                });
            // Set global Footer creator
            SmartRefreshLayout.setDefaultRefreshFooterCreator(new DefaultRefreshFooterCreator() {
                    @Override
                    public RefreshFooter createRefreshFooter(Context context, RefreshLayout layout) {
                        return new ClassicsFooter(context).setDrawableSize(20);
                    }
                });
        }
    }
  9. Basic Usage of SmartRefreshLayout

    main

    Follow these three steps to implement a basic pull-to-refresh and load-more functionality:

    1. XML Layout: Wrap your scrollable view (e.g., RecyclerView) inside SmartRefreshLayout. You can include Header and Footer views directly in the XML.
    2. XML Configuration: Set android:overScrollMode="never" on your scrollable view to prevent interference with the refresh animation.
    3. Activity/Fragment Implementation: Find the RefreshLayout by ID, set your desired Header and Footer, and implement the OnRefreshListener and OnLoadMoreListener.

    Use finishRefresh(boolean success) and finishLoadMore(boolean success) to signal the completion of the refresh/load operations. Passing false indicates the operation failed.

    <!-- XML Layout -->
    <com.scwang.smart.refresh.layout.SmartRefreshLayout 
        android:id="@+id/refreshLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        
        <com.scwang.smart.refresh.header.ClassicsHeader
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
            
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:overScrollMode="never" />
            
        <com.scwang.smart.refresh.footer.ClassicsFooter
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
            
    </com.scwang.smart.refresh.layout.SmartRefreshLayout>
    // Java Implementation
    RefreshLayout refreshLayout = (RefreshLayout)findViewById(R.id.refreshLayout);
    refreshLayout.setRefreshHeader(new ClassicsHeader(this));
    refreshLayout.setRefreshFooter(new ClassicsFooter(this));
    
    refreshLayout.setOnRefreshListener(new OnRefreshListener() {
        @Override
        public void onRefresh(RefreshLayout refreshlayout) {
            // Simulate network delay
            refreshlayout.finishRefresh(2000/*,false*/);
        }
    });
    
    refreshLayout.setOnLoadMoreListener(new OnLoadMoreListener() {
        @Override
        public void onLoadMore(RefreshLayout refreshlayout) {
            refreshlayout.finishLoadMore(2000/*,false*/);
        }
    });
  10. Configure global default parameters

    main

    You can set global default configurations for all SmartRefreshLayout instances in your application using SmartRefreshLayout.setDefaultRefreshInitializer. This is useful for setting common parameters like rebound duration, interpolators, footer height, and primary colors. To prevent memory leaks, it is recommended to perform these settings within a static block in your Application class.

    Additionally, you can set a global default Header using SmartRefreshLayout.setDefaultRefreshHeaderCreator. Note that properties set within the creator are specific to the returned Header type and can override properties set in the DefaultRefreshInitializer or XML.

    public class App extends Application {
        static {
            // Set global default configuration (lowest priority)
            SmartRefreshLayout.setDefaultRefreshInitializer(new DefaultRefreshInitializer() {
                @Override
                public void initialize(@NonNull Context context, @NonNull RefreshLayout layout) {
                    layout.setReboundDuration(1000);
                    layout.setReboundInterpolator(new DropBounceInterpolator());
                    layout.setFooterHeight(100);
                    layout.setDisableContentWhenLoading(false);
                    layout.setPrimaryColorsId(R.color.colorPrimary, android.R.color.white);
                }
            });
    
            // Set global default Header
            SmartRefreshLayout.setDefaultRefreshHeaderCreator(new DefaultRefreshHeaderCreator() {
                @Override
                public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) {
                    layout.setEnableHeaderTranslationContent(false);
                    return new MaterialHeader(context).setColorSchemeResources(R.color.colorRed, R.color.colorGreen, R.color.colorBlue);
                }
            });
        }
    }
  11. Handle fixed elements within SmartRefreshLayout content

    main

    When you need to include a fixed element (like an advertisement bar) at the top of a list, do not wrap SmartRefreshLayout inside a LinearLayout. Instead, place the fixed element inside a container (like a LinearLayout) which is then placed as the direct child of SmartRefreshLayout.

    Why this works: SmartRefreshLayout performs dynamic scrolling boundary detection. If the fixed element is inside the SmartRefreshLayout content, pulling down on the fixed element will trigger the refresh animation, even if the scrollable list itself is already scrolled to the middle. This provides a more intuitive user experience compared to wrapping the entire layout in a parent container.

    <!-- CORRECT: Fixed element inside SmartRefreshLayout -->
    <SmartRefreshLayout>
        <LinearLayout
            android:orientation="vertical">
            <TextView
                android:layout_width="match_parent"
                android:layout_height="100dp"
                android:gravity="center"
                android:text="Fixed Advertisement Bar"/>
            <ListView
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
        </LinearLayout>
    </SmartRefreshLayout>