Leo*_*Leo 42 android material-design android-recyclerview
我需要在具有标题的组中对RecyclerView中的元素进行划分(如下图中的收件箱应用程序),请帮助我找出哪种方法对我的情况更好:1)我可以使用异构布局但它是在组中插入新元素不太方便(因为我需要检查是否已经添加了同一组的元素,或者我需要添加新的分隔符).因此,在这种情况下,我将所有具有此类数据结构的操作包装到一个单独的类中.
2)从理论上讲,我可以用自己的RecyclerView包装每个组,这是一个好主意吗?
the*_*les 95
例如,你可以:
使用TreeMap<Date,List<Event>>
按日期分割元素.这将是一个用于保存业务对象的集合.当然,如果你已经有类似的结构,你可以保留它.有一些东西可以轻松构建项目列表,以便用正确的元素顺序填充UI.
为List
项目定义专用抽象类型(例如ListItem
)以包装业务对象.它的实现可能是这样的:
public abstract class ListItem {
public static final int TYPE_HEADER = 0;
public static final int TYPE_EVENT = 1;
abstract public int getType();
}
Run Code Online (Sandbox Code Playgroud)为每个List元素类型定义一个类(这里我只添加了两种类型,但您可以根据需要使用多种类型):
public class HeaderItem extends ListItem {
private Date date;
// here getters and setters
// for title and so on, built
// using date
@Override
public int getType() {
return TYPE_HEADER;
}
}
public class EventItem extends ListItem {
private Event event;
// here getters and setters
// for title and so on, built
// using event
@Override
public int getType() {
return TYPE_EVENT;
}
}
Run Code Online (Sandbox Code Playgroud)按如下方式创建一个List(其中mEventsMap是第1点的地图构建):
List<ListItem> mItems;
// ...
mItems = new ArrayList<>();
for (Date date : mEventsMap.keySet()) {
HeaderItem header = new HeaderItem();
header.setDate(date);
mItems.add(header);
for (Event event : mEventsMap.get(date)) {
EventItem item = new EventItem();
item.setEvent(event);
mItems.add(item);
}
}
Run Code Online (Sandbox Code Playgroud)为您定义适配器RecyclerView
,List
在第4点定义的工作.这里重要的是重写getItemViewType
方法如下:
@Override
public int getItemViewType(int position) {
return mItems.get(position).getType();
}
Run Code Online (Sandbox Code Playgroud)
然后,您需要有两个布局和ViewHolder用于标题和事件项.适配器方法应该相应地处理:
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == ListItem.TYPE_HEADER) {
View itemView = mLayoutInflater.inflate(R.layout.view_list_item_header, parent, false);
return new HeaderViewHolder(itemView);
} else {
View itemView = mLayoutInflater.inflate(R.layout.view_list_item_event, parent, false);
return new EventViewHolder(itemView);
}
}
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
int type = getItemViewType(position);
if (type == ListItem.TYPE_HEADER) {
HeaderItem header = (HeaderItem) mItems.get(position);
HeaderViewHolder holder = (HeaderViewHolder) viewHolder;
// your logic here
} else {
EventItem event = (EventItem) mItems.get(position);
EventViewHolder holder = (EventViewHolder) viewHolder;
// your logic here
}
}
Run Code Online (Sandbox Code Playgroud)这是GitHub上的一个存储库,它提供了上述方法的实现.
j2e*_*esu 10
您可以尝试使用我编写的库来解决我的项目中的这个问题.Gradle依赖(需要包含jcenter repo):
dependencies {
//your other dependencies
compile 'su.j2e:rv-joiner:1.0.3'//latest version by now
}
Run Code Online (Sandbox Code Playgroud)
然后,在你的情况下,你可以像这样做:
//init your RecyclerView as usual
RecyclerView rv = (RecyclerView) findViewById(R.id.rv);
rv.setLayoutManager(new LinearLayoutManager(this));
//construct a joiner
RvJoiner rvJoiner = new RvJoiner();
rvJoiner.add(new JoinableLayout(R.layout.today));
YourAdapter todayAdapter = new YourAdapter();
rvJoiner.add(new JoinableAdapter(todayAdapter));
rvJoiner.add(new JoinableLayout(R.layout.yesterday));
YourAdapter yesterdayAdapter = new YourAdapter();
rvJoiner.add(new JoinableAdapter(yesterdayAdapter));
//set join adapter to your RecyclerView
rv.setAdapter(rvJoiner.getAdapter());
Run Code Online (Sandbox Code Playgroud)
当您需要添加项目时,将其添加到适当的适配器,如:
if (timeIsToday) {
todayAdapter.addItem(item);//or other func you've written
} else if (timeIsYesterday) {
yesterdayAdapter.addItem(item);
}
Run Code Online (Sandbox Code Playgroud)
如果需要动态地向Recycler视图添加新组,可以使用以下方法:
rvJoiner.add(new JoinableLayout(R.layout.tomorrow));
YourAdapter tomorrowAdapter = new YourAdapter();
rvJoiner.add(new JoinableAdapter(tomorrowAdapter));
Run Code Online (Sandbox Code Playgroud)
您可以查看此链接以获取更多库说明.我不能说这肯定是实现目标的最佳方式,但它有时对我有帮助.
UPD:
我没有使用外部库就找到了这样做的方法.使用RecyclerView.ItemDecoration类.例如,要按项目中的3个项目对项目进行分组,您可以执行以下操作:
recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
private int textSize = 50;
private int groupSpacing = 100;
private int itemsInGroup = 3;
private Paint paint = new Paint();
{
paint.setTextSize(textSize);
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
for (int i = 0; i < parent.getChildCount(); i++) {
View view = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(view);
if (position % itemsInGroup == 0) {
c.drawText("Group " + (position / itemsInGroup + 1), view.getLeft(),
view.getTop() - groupSpacing / 2 + textSize / 3, paint);
}
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if (parent.getChildAdapterPosition(view) % itemsInGroup == 0) {
outRect.set(0, groupSpacing, 0, 0);
}
}
});
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你.
归档时间: |
|
查看次数: |
30772 次 |
最近记录: |