Probably the most powerful RecyclerView framework



GitHub | Using document | Alternate access


This framework does not affect the use of RecyclerView any function components on the basis of development. The project will also be maintained at all times


Welcome to contribute code/questions


  • Elegant function design
  • Detailed usage documentation
  • Simple sample code
  • High cohesion and low coupling
  • Refresh the screen without blinking
  • Two-way DataBinding (DataBinding)


function

  • g
  • A single data model one-to-many
  • Multiple data model
  • Add head layout and foot layout
  • Click (Anti-jitter) or hold the event
  • Grouping (Unfold fold/recursive hierarchy/unfold top/single unfold mode)
  • hover
  • Split line/uniform spacing (support official fullLayoutManager)
  • Switch mode
  • Selection mode (multiple/single/All/Cancel all/Reverse selection)
  • Drag and drop location
  • Lateral spreads to delete
  • Drop-down refresh | tensile load, extension SmartRefreshLayout that is compatible with all of its functions
  • Pull the index (UpFetch) | Preload index (Preload)
  • The default page
  • Automatic page loading
  • Extend scalable layout (FlexboxLayoutManager)
  • Extended Automated Network Request (Net), which implements automated concurrent network requests based on coroutines

The installation

Add the repository to build. Gradle in the project root directory

allprojects {
    repositories {
        // ...
        maven { url 'https://jitpack.io'}}}Copy the code

Add dependencies to build.gradle in module

android {
    / /... Turn DataBinding on even if you're not using it
    buildFeatures.dataBinding = true
}

dependencies {
    / /...
    implementation 'com. Making. Liangjingkanji: BRV: 1.3.24'
}
Copy the code

License

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Copy the code

preview

Home page

The function interface

Initialize the

class MyApplication : Application() {

    override fun onCreate(a) {
        super.onCreate()
      
        BindingAdapter.modelId = BR.m // It is recommended to initialize or use it in Application}}Copy the code

g

Different data models

rv.linear().setup {

  addType<Model>(R.layout.item_1)
  addType<Store>(R.layout.item_2)

}.models = data
Copy the code

One-to-many data model

It is common in development to come across a list with a field for each itemType

addType<Model>{
  // Use age as a judgment to return different layouts
  when (age) {
    23 -> {
      R.layout.item_1
    }
    else -> {
      R.layout.item_2
    }
  }
}
Copy the code

The divider

Fast secant line implementation

fun RecyclerView.divider(
    @DrawableRes drawable: Int.@RecyclerView.Orientation orientation: Int = RecyclerView.VERTICAL,
    block: ((Rect.View.RecyclerView.RecyclerView.State) - >Boolean)? = null
)
Copy the code

Listen for an event

Listening events need to be added to the view you want to listen on

fun addClickable(@IdRes vararg id: Int)
// Filter repeated clicks within 500 milliseconds

fun addFastClickable(@IdRes vararg id: Int)
// The function does not filter repeated click events

fun addLongClickable(@IdRes vararg id: Int)
// Long press event
Copy the code

Event callback

onClick{

}
// Click the event

onLongClick{

}
// Long click events

onBind {
  
  false
}
Copy the code

OnBind belongs to the onBindViewHolder event listener.

Use this function if you need to set data or bind events yourself. The return value determines whether to use the Databinding binding layout that is the internal default of the frame. false indicates no binding.

A simpler example

rv.linear().setup {

    addType<Model>{
        R.layout.item_1
    }

    onClick(R.id.item, R.id.user_portrait){

    }


    onLongClick(R.id.item){

    }

}.models = data
Copy the code

Head layout/foot layout

The head and foot layouts count as one item in the RV, so they should be considered when calculating positions.

Operation head layout

fun addHeader(view: View)

fun removeHeader(view: View)

fun clearHeader(a)

fun isHeader(@IntRange(from = 0) position: Int): Boolean
Copy the code

Operator pin layout

fun addFooter(view: View)

fun removeFooter(view: View)

fun clearFooter(a)

fun isFooter(@IntRange(from = 0) position: Int): Boolean
Copy the code

To get the data

val headerCount: Int

val footerCount: Int
Copy the code

Switch mode

Switching mode provides a callback function to iterate over all items, and you can refresh each item in turn within this callback.

Often used to toggle selection modes.

fun toggle(a)
// Switch mode

fun getToggleMode(a): Boolean
// The range is currently switching mode

fun setToggleMode(toggleMode: Boolean)
// Set toggle mode, if set to the current mode will not trigger the callback
Copy the code

The callback function

onToggle { type, position, toggleMode ->  // Type position toggle Boolean values
	// Here we can refresh the item into select mode
}

// The switch is complete
onToggleEnd {
	// For example, switch the toolbar to Select mode
}
Copy the code

Select the schema

fun allChecked(a)
/ / all

fun allChecked(isAllChecked: Boolean)
// Select all or cancel all

fun clearChecked(a)
// Deselect all

fun reverseChecked(a) 
/ / the choice

fun setChecked(@IntRange(from = 0) position: Int, checked: Boolean)
// Sets the selection status of an item

fun toggleChecked(@IntRange(from = 0) position: Int)
// Toggle the selection state of an item

fun <M> getCheckedModels(a): List<M>

fun setCheckableType(@LayoutRes vararg checkableItemType: Int)
// Sets which types are allowed to enter the selection state

val checkedCount: Int
Copy the code

Drag/side slip

Only support drag and drop movement and side – slide deletion

Steps:

  1. openItemTouchHelpersupport
  2. Data model inheritanceItemModel
  3. Custom extension

The BindingAdapter provides a field to enable ItemTouchHelper support

var touchEnable = false // It is disabled by default
Copy the code

The data model then requires inheriting the ItemModel, rewriting the function as needed.

Example:

data class Model(val name: String) : ItemModel() {

    override fun getDrag(a): Int {
        return UP or DOWN
    }

    override fun getSwipe(a): Int {
        return RIGHT or LEFT
    }
    
}
Copy the code

RIGHT or LEFT is a constant that controls the direction of drag and sideslip (sideslip does not support UP/DOWN).

Dragging and dropping items automatically changes the position of the data model in the data set.

Extend the functionality

If you want to extend ItemTouchHelper, you can assign to the BindingAdapter variable ItemTouchHelper

rv.linear().setup {

  addType<Model>(R.layout.item)
  touchEnable = true
  
  itemTouchHelper = ItemTouchHelper(object : DefaultItemTouchCallback(this) {
			// We can rewrite the function here
  })

}.models = data
Copy the code

Swipe can control the view that slides to move by attaching the tag to the view.

<RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="80dp"
        android:orientation="horizontal"
        android:tag="swipe"/>
Copy the code

The default page

StateLayout internal dependence, the library support any Activity | fragments | View to carry on the functions of the default page.

The main features

  • Global configuration
  • Singleton configuration
  • Life cycle (can load animations or process events)
  • Supports activity/fragment/ View replacement
  • Support code or XML implementation
  • ShowLoading displays an incorrect layout in the absence of a network, while loading is displayed in the presence of a network

This library is already dependent and does not need to be dependent again. See GitHub for instructions.

PageRefreshLayout

This layout extends SmartRefreshLayout(highly recommended by the library) to support all of its features. This framework has the perfect default page functionality

SmartRefreshLayout ‘com.scwang.smart:refresh-layout-kernel:2.0.0-alpha-1’ has already been introduced into this library.

Request headers that are required can be subcontracted to their open source address.

Optional configuration refreshes the head layout and foot layout

implementation  'com. Scwang. Smart: refresh - footer - classics: 2.0.0 - alpha - 1'    // Classic loading
implementation  'com. Scwang. Smart: refresh header - material: 2.0.0 - alpha - 1'    // Google refresh header
// The above two types are already built in


implementation  'com. Scwang. Smart: refresh header - classics: 2.0.0 - alpha - 1'    // Classic refresh header
implementation  'com. Scwang. Smart: refresh header - radar: 2.0.0 - alpha - 1'       // The radar refresh header
implementation  'com. Scwang. Smart: refresh header - falsify: 2.0.0 - alpha - 1'     // Virtual refresh header
implementation  'com. Scwang. Smart: refresh - the header - two - level: 2.0.0 - alpha - 1'   // Level 2 refresh header
implementation  'com. Scwang. Smart: refresh - footer - ball: 2.0.0 - alpha - 1'        // Ball pulse loading
implementation 'com. Scwang. Smartrefresh: SmartRefreshHorizontal: 1.0.0 andx - 1' / / level
Copy the code

Refresh layout requirements must be initialized first, recommended in Application

SmartRefreshLayout.setDefaultRefreshHeaderCreator { context, layout -> ClassicsHeader(this) }
SmartRefreshLayout.setDefaultRefreshFooterCreator { context, layout -> ClassicsFooter(this) }
Copy the code

Add features on top of that

  • The default page
  • Automatic page loading
  • Support for KT feature
  • Code to replace

Create a way

Val page = rv.page() // 2. Layout of the package<com.drake.brv.PageRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/page"
    app:stateEnabled="true"
    android:layout_height="match_parent"
    tools:context="com.drake.brv.sample.fragment.RefreshFragment">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</com.drake.brv.PageRefreshLayout>
Copy the code

Listening state

// Drop refresh
page.onRefresh {
	// Asynchronous operations such as network requests can be performed here
}

// Pull up load
page.onLoadMore {
	// Asynchronous operations such as network requests can be performed here
}
Copy the code

If onLoadMore is not called, the pull-up load also calls back the onRefresh function, because the pull-down refresh and the pull-up load may both go through the same network request.

The default page

Trigger the refresh state (both callback function onRefresh)

  1. autoRefeshThis is the triggered drop-down refresh
  2. showLoadingThis triggers the loading of the default page, after setting loadingLayout(or reading the global default page configuration).
  3. refreshThe silent refresh does not trigger any animation

The second method is usually used to load data when first entering the page (product managers may require this), and all three methods result in index=startIndex resetting.

Default page state control

showEmpty()
showError()
showContent
showLoading()
Copy the code

Configure the global default page

This code is common to StateLayout

/ * * * recommended for global configuration default page in the Application, also, of course, each page can specify a default page alone. Specific see https://github.com/liangjingkanji/StateLayout * / *
StateConfig.apply {
  emptyLayout = R.layout.layout_empty
  errorLayout = R.layout.layout_error
  loadingLayout = R.layout.layout_loading

  onLoading {
    // This lifecycle takes the view object created by LoadingLayout, which can be animated or clicked.}}Copy the code

The singleton default page can be configured in two ways

  1. XML
<com.drake.brv.PageRefreshLayout 
    .
    app:error_layout="@layout/layout_error"
    app:empty_layout="@layout/layout_empty"
    app:loading_layout="@layout/layout_loading">
Copy the code
  1. code
page.apply {
    loadingLayout = R.layout.layout_loading
    emptyLayout = R.layout.layout_empty
    errorLayout = R.layout.layout_error
}
Copy the code

The default page will be used by default if you have set the global default page but don’t want to use it at the moment. Can use properties | function: stateEnabled

If you want to use a default page that does not cover the head layout, you can use CoordinatorLayout for head layout. Note that using NestedScrollView causes a large memory consumption after the RV loads the item at one time.

The refresh data

As mentioned earlier, PageRefreshLayout supports automatic pagination loading

// Set the index of the first page to be paged. Default =1. Triggering a refresh resets the index. If you need to change it, set it once in Application
// PageRefreshLayout.startIndex = 1

pageLayout.onRefresh { 
  // Both the pull-down refresh and the pull-up load will execute the network request unless onLoadMore is set otherwise
  get("/path") {
      param("key"."value")
      param("page", pageLayout.index) // Frame supplied properties are used here
  }.page(this) {
    // This callback function argument returns a Boolean type to determine the existence of the next page, determining the status of the pull-up load. And whether it is currently refreshing or loading more entries
    addData(data){ adapter.itemCount < data.count }}}}Copy the code

The web request here uses my other open source project, Net, which supports the extension brv. GitHub: Net.

extension

LayoutManager

The framework also provides extension functions to quickly create layout managers, as shown in the example above

rv.linear().setup {
	
}
Copy the code

function

fun RecyclerView.linear(
    @RecyclerView.Orientation orientation: Int = VERTICAL,
    reverseLayout: Boolean = false
)


fun RecyclerView.grid(
    spanCount: Int.@RecyclerView.Orientation orientation: Int = VERTICAL,
    reverseLayout: Boolean = false
)

fun RecyclerView.staggered(
    spanCount: Int.@RecyclerView.Orientation orientation: Int = VERTICAL
)
Copy the code

dividers

The framework provides quick setup of separator extension functions

fun RecyclerView.divider( 
    @DrawableRes drawable: Int.// delimiter Drawable
    @RecyclerView.Orientation orientation: Int = RecyclerView.VERTICAL, // Direction of LayoutManager
    block: ((Rect.View.RecyclerView.RecyclerView.State) - >Boolean)? = null // The getItemOffset callback is used to set the interval
)
Copy the code

The sample

rv.linear().divider(R.drawable.divider_horizontal_padding_15dp).setup {
	
}
Copy the code

dialog

Use extension functions to quickly create lists for dialogs

Dialog(context).setAdapter(bindingAdapter)
Copy the code