自定义 RecyclerView 适配器,用于扩展和折叠组,支持多种视图类型。

1. 效果图:

展开

多选

单选

多种类型

使用步骤

添加依赖

ExpandableRecyclerView:

compile 'com.thoughtbot:expandablerecyclerview:1.3'

ExpandableCheckRecyclerView:

compile 'com.thoughtbot:expandablecheckrecyclerview:1.4'

自定义 ExpandableGroup 类:

/**

* Created on 2019/5/15 4:55 PM

*

* @author Scarf Gong

*/

public class Genre extends ExpandableGroup {

private int iconResId;

public Genre(String title, List items, int iconResId) {

super(title, items);

this.iconResId = iconResId;

}

public int getIconResId() {

return iconResId;

}

@Override

public boolean equals(Object o) {

if (this == o) {

return true;

}

if (!(o instanceof Genre)) {

return false;

}

Genre genre = (Genre) o;

return getIconResId() == genre.getIconResId();

}

@Override

public int hashCode() {

return getIconResId();

}

}

/**

* Created on 2019/5/15 4:56 PM

*

* @author Scarf Gong

*/

public class Artist implements Parcelable {

private String name;

private boolean isFavorite;

public Artist(String name, boolean isFavorite) {

this.name = name;

this.isFavorite = isFavorite;

}

protected Artist(Parcel in) {

name = in.readString();

}

public String getName() {

return name;

}

public boolean isFavorite() {

return isFavorite;

}

@Override

public boolean equals(Object o) {

if (this == o) return true;

if (!(o instanceof Artist)) return false;

Artist artist = (Artist) o;

if (isFavorite() != artist.isFavorite()) return false;

return getName() != null ? getName().equals(artist.getName()) : artist.getName() == null;

}

@Override

public int hashCode() {

int result = getName() != null ? getName().hashCode() : 0;

result = 31 * result + (isFavorite() ? 1 : 0);

return result;

}

@Override

public void writeToParcel(Parcel dest, int flags) {

dest.writeString(name);

}

@Override

public int describeContents() {

return 0;

}

public static final Creator CREATOR = new Creator() {

@Override

public Artist createFromParcel(Parcel in) {

return new Artist(in);

}

@Override

public Artist[] newArray(int size) {

return new Artist[size];

}

};

}

创建 ChildViewHolder 和 HeaderViewHolder 。

/**

* Created on 2019/5/15 4:52 PM

*

* @author Scarf Gong

*/

public class HeaderViewHolder extends GroupViewHolder {

private TextView genreName;

private ImageView arrow;

private ImageView icon;

public HeaderViewHolder(View itemView) {

super(itemView);

genreName = itemView.findViewById(R.id.list_item_genre_name);

arrow = itemView.findViewById(R.id.list_item_genre_arrow);

icon = itemView.findViewById(R.id.list_item_genre_icon);

}

public void setGenreTitle(ExpandableGroup genre) {

if (genre instanceof Genre) {

genreName.setText(genre.getTitle());

icon.setBackgroundResource(((Genre) genre).getIconResId());

}

}

@Override

public void expand() {

animateExpand();

}

@Override

public void collapse() {

animateCollapse();

}

private void animateExpand() {

RotateAnimation rotate =

new RotateAnimation(360, 180, RELATIVE_TO_SELF, 0.5f, RELATIVE_TO_SELF, 0.5f);

rotate.setDuration(300);

rotate.setFillAfter(true);

arrow.setAnimation(rotate);

}

private void animateCollapse() {

RotateAnimation rotate =

new RotateAnimation(180, 360, RELATIVE_TO_SELF, 0.5f, RELATIVE_TO_SELF, 0.5f);

rotate.setDuration(300);

rotate.setFillAfter(true);

arrow.setAnimation(rotate);

}

}

/**

* Created on 2019/5/15 4:59 PM

*

* @author Scarf Gong

*/

public class ItemViewHolder extends ChildViewHolder {

public TextView childTextView;

public ItemViewHolder(View itemView) {

super(itemView);

childTextView = itemView.findViewById(R.id.list_item_artist_name);

}

public void setArtistName(String name) {

childTextView.setText(name);

}

/**

* 子 item 的点击事件。

* @param position

*/

public void click(final int position) {

childTextView.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Log.d("TAG", "onClick: " + position);

}

});

}

}

创建 GenreAdapter 类

/**

* Created on 2019/5/15 5:00 PM

*

* @author Scarf Gong

*/

public class GenreAdapter extends ExpandableRecyclerViewAdapter {

public GenreAdapter(List extends ExpandableGroup> groups) {

super(groups);

}

@Override

public HeaderViewHolder onCreateGroupViewHolder(ViewGroup parent, int viewType) {

View view = LayoutInflater.from(parent.getContext())

.inflate(R.layout.list_item_genre, parent, false);

return new HeaderViewHolder(view);

}

@Override

public ItemViewHolder onCreateChildViewHolder(ViewGroup parent, int viewType) {

View view = LayoutInflater.from(parent.getContext())

.inflate(R.layout.list_item_artist, parent, false);

return new ItemViewHolder(view);

}

@Override

public void onBindChildViewHolder(ItemViewHolder holder, final int flatPosition,

ExpandableGroup group, final int childIndex) {

final Artist artist = ((Genre) group).getItems().get(childIndex);

holder.setArtistName(artist.getName());

holder.click(childIndex);

}

@Override

public void onBindGroupViewHolder(HeaderViewHolder holder, int flatPosition,

ExpandableGroup group) {

holder.setGenreTitle(group);

}

}

在 Activity 中使用

public class ExpandActivity extends AppCompatActivity {

public GenreAdapter adapter;

@Override

protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_expand);

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

getSupportActionBar().setTitle(getClass().getSimpleName());

RecyclerView recyclerView = findViewById(R.id.recycler_view);

LinearLayoutManager layoutManager = new LinearLayoutManager(this);

RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator();

if (animator instanceof DefaultItemAnimator) {

((DefaultItemAnimator) animator).setSupportsChangeAnimations(false);

}

adapter = new GenreAdapter(makeGenres());

recyclerView.setLayoutManager(layoutManager);

recyclerView.setAdapter(adapter);

Button clear = findViewById(R.id.toggle_button);

clear.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

adapter.toggleGroup(makeJazzGenre());

}

});

}

@Override

protected void onSaveInstanceState(Bundle outState) {

super.onSaveInstanceState(outState);

adapter.onSaveInstanceState(outState);

}

@Override

protected void onRestoreInstanceState(Bundle savedInstanceState) {

super.onRestoreInstanceState(savedInstanceState);

adapter.onRestoreInstanceState(savedInstanceState);

}

}

MainActivity 跳转到 ExpandActivity

private void initView() {

Button expand = (Button) findViewById(R.id.expand_button);

expand.setOnClickListener(navogateTo(ExpandActivity.class));

}

public View.OnClickListener navogateTo(final Class> clazz) {

return new View.OnClickListener() {

@Override

public void onClick(View v) {

Intent intent = new Intent(MainActivity.this,clazz);

startActivity(intent);

}

};

}

模拟数据的封装

/**

* Created on 2019/5/15 5:14 PM

*

* @author Scarf Gong

*/

public class GenreDataFactory {

public static List makeGenres() {

return Arrays.asList(makeRockGenre(),

makeJazzGenre(),

makeClassicGenre());

}

public static Genre makeRockGenre() {

return new Genre("水果", makeRockArtists(), R.drawable.ic_banjo);

}

public static List makeRockArtists() {

Artist queen = new Artist("西瓜", true);

Artist styx = new Artist("苹果", false);

Artist reoSpeedwagon = new Artist("香蕉", false);

Artist boston = new Artist("圣女果", true);

return Arrays.asList(queen, styx, reoSpeedwagon, boston);

}

public static Genre makeJazzGenre() {

return new Genre("游戏", makeJazzArtists(), R.drawable.ic_banjo);

}

public static List makeJazzArtists() {

Artist milesDavis = new Artist("王者荣耀", true);

Artist ellaFitzgerald = new Artist("英雄联盟", true);

Artist billieHoliday = new Artist("吃鸡", false);

return Arrays.asList(milesDavis, ellaFitzgerald, billieHoliday);

}

public static Genre makeClassicGenre() {

return new Genre("运动", makeClassicArtists(), R.drawable.ic_banjo);

}

public static List makeClassicArtists() {

Artist beethoven = new Artist("篮球", false);

Artist bach = new Artist("足球", true);

Artist brahms = new Artist("乒乓球", false);

Artist puccini = new Artist("羽毛球", false);

return Arrays.asList(beethoven, bach, brahms, puccini);

}

}

效果

xgt.jpg

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐