All Projects → baurine → Multi Type Adapter

baurine / Multi Type Adapter

Super simple and easy to use common multi-type-adapter by android data-binding

Programming Languages

java
68154 projects - #9 most used programming language

Projects that are alternatives of or similar to Multi Type Adapter

Rxbanner
一个灵活可制定的基于 Recyclerview 的轮播图控件,支持自动轮播,无限循环。 同时可关闭无限循环变成 引导页 ,带有引导完成接口回调
Stars: ✭ 77 (-24.51%)
Mutual labels:  recyclerview
Recyclerview Examples
Samples to learn about RecyclerView
Stars: ✭ 87 (-14.71%)
Mutual labels:  recyclerview
Flowlayout
An Android Layout Manager to create a gridview with cells of different sizes inspired by Flow Layout for iOS.
Stars: ✭ 98 (-3.92%)
Mutual labels:  recyclerview
Multitype
【MultiType】可以轻松地实现RecyclerView显示多种数据类型,数据对应布局一对多、多对多、多对一,可以注册全局类型、局部类型、默认类型
Stars: ✭ 80 (-21.57%)
Mutual labels:  recyclerview
Endless Recyclerview
Endless support for RecyclerView
Stars: ✭ 86 (-15.69%)
Mutual labels:  recyclerview
Recyclerviewheader
[DEPRECATED] Super fast and easy way to create header for Android RecyclerView
Stars: ✭ 1,312 (+1186.27%)
Mutual labels:  recyclerview
Gencycler
Gencycler is the fastest way to write RecyclerView adapters
Stars: ✭ 73 (-28.43%)
Mutual labels:  recyclerview
Cartlayout
🦄 使用 RecyclerView 实现店铺分组购物车。 高仿京东购物车、高仿淘宝购物车、高仿天猫购物车
Stars: ✭ 101 (-0.98%)
Mutual labels:  recyclerview
Recyclerviewpresenter
RecyclerView Adapter Library with different models and different layouts as convenient as possible.
Stars: ✭ 86 (-15.69%)
Mutual labels:  recyclerview
Banner
Android Viewpager rotation control, application guide page controls, support vertical, horizontal cycle scrolling, extended from view support animation, indicator extension and so on;Android viewpager轮播图控件、app引导页控件,支持垂直、水平循环滚动,扩展自viewpager 支持动画,指示器扩展等。
Stars: ✭ 96 (-5.88%)
Mutual labels:  recyclerview
Flexadapter
The easiest way to use a RecyclerView on Android
Stars: ✭ 80 (-21.57%)
Mutual labels:  recyclerview
Pinnedrecyclerview Android
Add a list pinned by a floating label (text or image)
Stars: ✭ 81 (-20.59%)
Mutual labels:  recyclerview
Recyclerviewdemo
Demo showing the basics to advanced use cases of Android RecyclerView
Stars: ✭ 92 (-9.8%)
Mutual labels:  recyclerview
Inifiniterecyclerview
Library for implementing endless loading list easily in Android applications
Stars: ✭ 79 (-22.55%)
Mutual labels:  recyclerview
Multi Selection
Multiselection Solution for Android in Kotlin
Stars: ✭ 1,361 (+1234.31%)
Mutual labels:  recyclerview
Elements
⚒ Modular components for RecyclerView development enforcing clean, reusable and testable code, with built-in support for paging and complex hierarchies of data.
Stars: ✭ 75 (-26.47%)
Mutual labels:  recyclerview
Videolistplayer
Play video in ListView or RecyclerView
Stars: ✭ 1,308 (+1182.35%)
Mutual labels:  recyclerview
Zoomrecyclerview
A Zoomable RecyclerView for comic
Stars: ✭ 102 (+0%)
Mutual labels:  recyclerview
Toro
Video list auto playback made simple, specially built for RecyclerView
Stars: ✭ 1,380 (+1252.94%)
Mutual labels:  recyclerview
Dragview2fill
ViewDragHelper结合RecyclerView的使用示例
Stars: ✭ 94 (-7.84%)
Mutual labels:  recyclerview

MultiTypeAdapter

Implement a super simple, powerful, and easy to use MultiTypeAdapter for RecyclerView by android databinding, it is only about 100 lines code and just one java file, use this adapter, you can never to implement kinds of ViewHolder anymore.

I write a very detail tutorial to explain how to implement this MultiTypeAdapter, and how to use it to implement a complete sample that support refresh, load more, retry, header item, emtpy item, error item, footer item, any kinds of data item step by step.

Tutorial

  1. Escape the nightmare of adapter and viewholder by android databinding (1)
  2. Escape the nightmare of adapter and viewholder by android databinding (2)

Sample

  1. Demo HeaderItem, EmptyItem, ErrorItem, refresh, load more, load error and retry:

  2. Demo load more but has no more data:

  3. Polish the UI, add event handler for item:

The sample includes following features, I think it should fullfill 90% needs:

  1. Refresh
  2. Load more
  3. Support header item
  4. Support empty item and enable refresh again
  5. Support error item and enable refresh again
  6. Support footer item, includes 3 states: loading, load error and enable retry, no more data
  7. Support any kind of data item, here just demo ImageItem and TextItem

Download APK | GitHub

There are two folders in this project, MultiTypeAdapterSample and MultiTypeAdapterTutorial, their codes are nearly same, the latter is created for the above tutorial articles, I tag the every key step so you can easily compare the code with article.

Getting Started

Add JitPack as library source in your project build.gradle:

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

Then, add dependency in your app module build.gradle:

dependencies {
    compile 'com.github.baurine:multi-type-adapter:${latest-version}'
}

latest-version: see top jitpack badge.

And enable databinding in your app module build.gradle:

android {
    ...
    dataBinding {
        enabled = true
    }
}

Usage

Please read the above super detail tutorial to learn how exactly to use it. Following are some simple instruction extract from tutorial.

After you use this MultiTypeAdapter, you just need to implement kinds of items, and add to or remove from adapter at the right time. The item represents a whole body that display in recyclerview, includes layout, data and event, so it is a wrapper, wrap the layout, data model and event handler together, but the data model and event handler are not necessary, just layout is required, it depends on what's the kind of item. All items must inherit from IItem interface:

public interface IItem {
    // get the xml layout this type item used in
    int getLayout();

    // get the variable name in the xml
    int getVariableId();
}

getLayout() method should return the xml layout, likes R.layout.item_header, and getVariableId() return the variable name this item used in xml, likes BR.item. Becasuse we usually use a same variable name in all items, and the event handler, usually it can be a View.OnClickListener, so we define a BaseItem:

public abstract class BaseItem implements MultiTypeAdapter.IItem {
    @Override
    public int getVariableId() {
        return BR.item;
    }

    ////////////////////////////////////////////
    // handle event
    private View.OnClickListener onClickListener;

    public View.OnClickListener getOnClickListener() {
        return onClickListener;
    }

    public void setOnClickListener(View.OnClickListener onClickListener) {
        this.onClickListener = onClickListener;
    }
}

Here is an example, a most simple item - HeaderItem, just has layout, no data and no event:

public class HeaderItem extends BaseItem {
    @Override
    public int getLayout() {
        return R.layout.item_header;
    }
}

And HeaderItem used in item_header.xml:

<layout
    xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="item"
            type="com.baurine.multitypeadaptersample.item.HeaderItem"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:background="@drawable/x_border"
        android:gravity="center_horizontal"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="24dp"
            android:text="This is a HeaderItem"
            android:textSize="20sp"
            android:textStyle="bold"/>

    </LinearLayout>
</layout>

A most complex item - ImageItem, display a random image, and you can like it, hide it, and comment it, the image data from ImageModel:

ImageModel:

public class ImageModel extends BaseModel {
    @Override
    public MultiTypeAdapter.IItem createItem(MultiTypeAdapter adapter) {
        return new ImageItem(this, adapter);
    }

    ////////////////////////////////////////
    public final String url;
    public boolean liked;

    public ImageModel() {
        super();
        url = "https://unsplash.it/200/200?random&" + new Random().nextInt(40);
        liked = (new Random()).nextBoolean();
    }
}

ImageItem:

public class ImageItem extends BaseItem {
    @Override
    public int getLayout() {
        return R.layout.item_image;
    }

    ///////////////////////////////////////
    public ImageItem(ImageModel imageModel, final MultiTypeAdapter adapter) {
        this.imageModel = imageModel;

        setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                switch (view.getId()) {
                    case R.id.tv_like:
                        toggleLiked();
                        adapter.notifyItemChanged(adapter.findPos(ImageItem.this));
                        break;
                    case R.id.tv_hide:
                        adapter.notifyItemRemoved(adapter.removeItem(ImageItem.this));
                        break;
                    case R.id.tv_comment:
                        CommonUtil.showToast(view.getContext(),
                                "TODO: comment image, id: " +
                                        String.valueOf(getId()));
                        break;
                }
            }
        });
    }

    ///////////////////////////////////////
    // data model part
    private final ImageModel imageModel;

    public String getUrl() {
        return imageModel.url;
    }

    public boolean isLiked() {
        return imageModel.liked;
    }

    public int getId() {
        return imageModel.id;
    }

    public void toggleLiked() {
        imageModel.liked = !imageModel.liked;
    }
}

ImageItem used in item_image.xml:

<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable
            name="item"
            type="com.baurine.multitypeadaptersample.item.ImageItem"/>
    </data>

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        app:cardCornerRadius="2dp">

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="200dp"
                android:scaleType="centerCrop"
                app:error="@{@drawable/ic_launcher}"
                app:imageUrl="@{item.url}"
                app:placeholder="@{@drawable/ic_launcher}"/>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom"
                android:background="#c0ffffff">

                <include
                    layout="@layout/include_actions"
                    app:liked="@{item.liked}"
                    app:onClickListener="@{item.onClickListener}"/>

            </LinearLayout>
        </FrameLayout>
    </android.support.v7.widget.CardView>
</layout>

<!-- include_actions.xml-->
<layout
    xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="liked"
            type="Boolean"/>
        <variable
            name="onClickListener"
            type="android.view.View.OnClickListener"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/tv_like"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:onClick="@{onClickListener::onClick}"
            android:paddingVertical="@{8}"
            android:text="@{liked ? `取消赞` : `点赞`}"
            android:textColor="@{liked ? @android:color/holo_red_light : @android:color/darker_gray}"/>

        <TextView
            android:id="@+id/tv_hide"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:onClick="@{onClickListener::onClick}"
            android:paddingVertical="@{8}"
            android:text="隐藏"/>

        <TextView
            android:id="@+id/tv_comment"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:onClick="@{onClickListener::onClick}"
            android:paddingVertical="@{8}"
            android:text="评论"/>
    </LinearLayout>
</layout>

Then call adapter.addItem(), adapter.removeItem(), adapter.notifyItemChanged(adapter.findPos(item)) to operate the adapter at the right time. Following is an example to handle the network response result:

private void retrieveItems(boolean loadMore) {
    // result = 0, network error
    // result = 1, empty
    // result = 2, last page data
    // result = 3 and other, normal result
    int resultType = (new Random()).nextInt(100) % 5;
    if (resultType == 0) {
        adapter.addItem(loadMore ? footerItem.setState(FooterItem.ERROR) : errorItem);
    } else if (resultType == 1) {
        adapter.addItem(loadMore ? footerItem.setState(FooterItem.NO_MORE) : emptyItem);
    } else if (resultType == 2) {
        addDataItems(PER_PAGE_COUNT / 2);
        // here depends whether you want to display no more data state
        // if you don't want to display this state when has no more data
        // then just don't add it back
        adapter.addItem(footerItem.setState(FooterItem.NO_MORE));
    } else {
        addDataItems(PER_PAGE_COUNT);
        // pre-display loading state to improve user experience
        adapter.addItem(footerItem.setState(FooterItem.LOADING));
    }
}

License

Copyright 2017 baurine.

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.
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].