I want to implement sections in my list. I have a list of tasks. List has a custom adapter which extends recyclerview swipe adapter as I have implemented swipe gesture to the recyclerview.
So now tasks list is shown together with completed and pending tasks. Each list item has a check box which shows task is completed or pending.
If check box is checked then task is completed and vise versa. Now I want to make two sections in this with header. One For completed tasks and another for pending tasks.
So completed tasks should be shown inside completed section and vise versa. Also if the task is unchecked i.e pending and if user checks the check box then the item should get removed from the pending section and should get added to the completed section and vise versa.
I checked with one library for sections.
https://github.com/afollestad/sectioned-recyclerview
But when I tried to implement the library I got the error that adapter can not extend two classes as I have extended recyclerview swipe library before.
onBindViewHolder method after extending sectionedRecyclerview adapter I get the error as IAdapter should implement onBindViewHolder(VH,int)
How to solve this?
Adapter:
public class IAdapter extends RecyclerSwipeAdapter<IAdapter.ItemViewHolder> , SectionedRecyclerViewAdapter<IAdapter.ItemViewHolder> {
public ArrayList<Task> items;
Context conext;
public int _mId;
List<Task> itemsPendingRemoval = new ArrayList<>();
public IAdapter(Context context, ArrayList<Task> item) {
this.conext=context;
this.items=item;
}
@Override
public int getSectionCount() {
return 2;
}
@Override
public int getItemCount(int section) {
return items.size();
}
public static class ItemViewHolder extends RecyclerView.ViewHolder {
Task task;
CheckBox cb;
SwipeLayout swipeLayout;
TaskTableHelper taskTableHelper;
ItemViewHolder(final View itemView) {
super(itemView);
taskTableHelper= new TaskTableHelper(itemView.getContext());
swipeLayout = (SwipeLayout) itemView.findViewById(R.id.swipe);
cb = (CheckBox) itemView.findViewById(R.id.checkbox);
}
}
@Override
public void onBindViewHolder(final ItemViewHolder itemViewHolder, int section,final int i, int absolutePosition) {
itemViewHolder.cb.setText(items.get(i).getTitle());
itemViewHolder.task = items.get(i);
int taskId = itemViewHolder.task.getId();
itemViewHolder.task = itemViewHolder.taskTableHelper.getTask(taskId);
int status = itemViewHolder.task.getStatus();
if(status == 0)
{
itemViewHolder.cb.setTextColor(Color.WHITE);
}
else {
itemViewHolder.cb.setChecked(true);
itemViewHolder.cb.setTextColor(Color.parseColor("#B0BEC5"));
}
itemViewHolder.cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
itemViewHolder.cb.setTextColor(Color.parseColor("#B0BEC5"));
itemViewHolder.task.setStatus(1);
itemViewHolder.taskTableHelper.updateStatus(itemViewHolder.task);
}
else
{
itemViewHolder.cb.setTextColor(Color.WHITE);
itemViewHolder.task.setStatus(0);
itemViewHolder.taskTableHelper.updateStatus(itemViewHolder.task);
}
}
});
final Task item = items.get(i);
itemViewHolder.swipeLayout.addDrag(SwipeLayout.DragEdge.Right,itemViewHolder.swipeLayout.findViewById(R.id.bottom_wrapper_2));
itemViewHolder.swipeLayout.setShowMode(SwipeLayout.ShowMode.LayDown);
itemViewHolder.swipeLayout.setOnDoubleClickListener(new SwipeLayout.DoubleClickListener() {
@Override
public void onDoubleClick(SwipeLayout layout, boolean surface) {
Toast.makeText(conext, "DoubleClick", Toast.LENGTH_SHORT).show();
}
});
itemViewHolder.swipeLayout.findViewById(R.id.trash2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mItemManger.removeShownLayouts(itemViewHolder.swipeLayout);
items.remove(i);
notifyItemRemoved(i);
notifyItemRangeChanged(i, items.size());
mItemManger.closeAllItems();
itemViewHolder.taskTableHelper.deleteTask(item);
_mId = item.getAlertId();
cancelNotification();
Toast.makeText(view.getContext(), "Deleted " + itemViewHolder.cb.getText().toString() + "!", Toast.LENGTH_SHORT).show();
}
});
itemViewHolder.swipeLayout.findViewById(R.id.done).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
itemViewHolder.task.setStatus(1);
itemViewHolder.taskTableHelper.updateStatus(itemViewHolder.task);
itemViewHolder.cb.setChecked(true);
Toast.makeText(conext, "Task Completed.", Toast.LENGTH_SHORT).show();
}
});
itemViewHolder.swipeLayout.getSurfaceView().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean mEditMode;
int id = item.getId();
int priority = item.getTaskPriority();
String title = item.getTitle();
String alertDate = item.getAlertDate();
String alertTime = item.getAlertTime();
String dueDate = item.getDueDate();
String dueTime = item.getDueTime();
_mId = item.getAlertId();
int listId = item.getList();
mEditMode = true;
Intent i = new Intent(conext, AddTaskActivity.class);
i.putExtra("taskId", id);
i.putExtra("taskTitle", title);
i.putExtra("taskPriority", priority);
i.putExtra("taskAlertTime", alertTime);
i.putExtra("taskAlertDate", alertDate);
i.putExtra("taskDueDate", dueDate);
i.putExtra("taskDueTime", dueTime);
i.putExtra("taskListId", listId);
i.putExtra("EditMode", mEditMode);
i.putExtra("AlertId",_mId);
conext.startActivity(i);
}
});
mItemManger.bindView(itemViewHolder.itemView, i);
}
@Override
public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup,int position) {
View itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.card_layout, viewGroup, false);
return new ItemViewHolder(itemView);
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
public void remove(int position) {
Task item = items.get(position);
if (itemsPendingRemoval.contains(item)) {
itemsPendingRemoval.remove(item);
}
if (items.contains(item)) {
items.remove(position);
notifyItemRemoved(position);
}
}
public void cancelNotification()
{
AlarmManager alarmManager = (AlarmManager)conext.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(conext, NotificationReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(conext,_mId, intent, 0);
alarmManager.cancel(pendingIntent);
}
@Override
public int getSwipeLayoutResourceId(int position) {
return R.id.swipe;
}
}
Please help.. Thank you..
You can easily achieve this with the library SectionedRecyclerViewAdapter.
First create a Section class to group your tasks:
class TaskSection extends StatelessSection {
String title;
List<Task> list;
public TaskSection(String title, List<Task> list) {
// call constructor with layout resources for this Section header, footer and items
super(R.layout.section_header, R.layout.section_item);
this.title = title;
this.list = list;
}
@Override
public int getContentItemsTotal() {
return list.size(); // number of items of this section
}
public int addTask(Task task) {
return list.add(task;
}
public int removeTask(Task task) {
return list.remove(task;
}
@Override
public RecyclerView.ViewHolder getItemViewHolder(View view) {
// return a custom instance of ViewHolder for the items of this section
return new MyItemViewHolder(view);
}
@Override
public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) {
MyItemViewHolder itemHolder = (MyItemViewHolder) holder;
// bind your view here
itemHolder.tvItem.setText(list.get(position).getTitle());
}
@Override
public RecyclerView.ViewHolder getHeaderViewHolder(View view) {
return new SimpleHeaderViewHolder(view);
}
@Override
public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder) {
MyHeaderViewHolder headerHolder = (MyHeaderViewHolder) holder;
// bind your header view here
headerHolder.tvItem.setText(title);
}
}
Then you set up the RecyclerView with your Sections:
// Create an instance of SectionedRecyclerViewAdapter
SectionedRecyclerViewAdapter sectionAdapter = new SectionedRecyclerViewAdapter();
// Create your sections with the list of data
TaskSection compSection = new TaskSection("Completed", compList);
TaskSection pendSection = new TaskSection("Pending", pendList);
// Add your Sections to the adapter
sectionAdapter.addSection(compSection);
sectionAdapter.addSection(pendSection);
// Set up your RecyclerView with the SectionedRecyclerViewAdapter
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(sectionAdapter);
Now if you want to send a task from "Pending" section to "Completed":
pendSection.removeTask(task);
compSection.addTask(task);
sectionAdapter.notifyDataSetChanged();
This sample also posted which link you have posted. You can implement like this.
public class MainAdapter extends SectionedRecyclerViewAdapter<MainAdapter.MainVH> {
@Override
public int getSectionCount() {
return 20; // number of sections.
}
@Override
public int getItemCount(int section) {
return 8; // number of items in section (section index is parameter).
}
@Override
public void onBindHeaderViewHolder(MainVH holder, int section) {
// Setup header view.
}
@Override
public void onBindViewHolder(MainVH holder, int section, int relativePosition, int absolutePosition) {
// Setup non-header view.
// 'section' is section index.
// 'relativePosition' is index in this section.
// 'absolutePosition' is index out of all non-header items.
// See sample project for a visual of how these indices work.
}
@Override
public MainVH onCreateViewHolder(ViewGroup parent, int viewType) {
// Change inflated layout based on 'header'.
View v = LayoutInflater.from(parent.getContext())
.inflate(viewType == VIEW_TYPE_HEADER ? R.layout.header : R.layout.normal, parent, false);
return new MainVH(v);
}
public static class MainVH extends RecyclerView.ViewHolder {
public MainVH(View itemView) {
super(itemView);
// Setup view holder.
// You'd want some views to be optional, e.g. for header vs. normal.
}
}
}
The most simple way to split your recycler view into sections is by using a layout with the header and the item already in place and then changing the visibility if the header is the same.
Layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tvHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:padding="16dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/primary"
android:textStyle="bold"
tools:text="A" />
<TextView
android:id="@+id/tvName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tvHeader"
android:background="?android:attr/selectableItemBackground"
android:padding="16dp"
android:textAppearance="?android:attr/textAppearanceMedium"
tools:text="Adam" />
</RelativeLayout>
Adapter (2018 Kotlin Edition):
class ContactAdapter @Inject constructor() : RecyclerView.Adapter<ContactAdapter.ViewHolder>() {
var onItemClick: ((Contact) -> Unit)? = null
var contacts = emptyList<Contact>()
override fun getItemCount(): Int {
return contacts.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_contact, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val name = contacts[position].name
holder.header.text = name.substring(0, 1)
holder.name.text = name
// if not first item, check if item above has the same header
if (position > 0 && contacts[position - 1].name.substring(0, 1) == name.substring(0, 1)) {
holder.headerTextView.visibility = View.GONE
} else {
holder.headerTextView.visibility = View.VISIBLE
}
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val headerTextView: TextView = itemView.tvHeader
val nameTextView: TextView = itemView.tvName
init {
itemView.setOnClickListener {
onItemClick?.invoke(contacts[adapterPosition])
}
}
}
}
Might be helpful as well: RecyclerView itemClickListener in Kotlin
Old Java Adapter Version:
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.DataViewHolder> {
private List<Contact> mData;
@Inject
public RecyclerAdapter() {
mData = new ArrayList<>();
}
public void setData(List<Contact> data) {
mData = data;
}
public Contact getItem(int position){
return mData.get(position);
}
@Override
public DataViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_contact, parent, false);
return new DataViewHolder(itemView);
}
@Override
public void onBindViewHolder(final DataViewHolder holder, int position) {
Contact contact = mData.get(position);
holder.headerTextView.setText(contact.getName().substring(0, 1));
holder.nameTextView.setText(contact.getName());
// if not first item check if item above has the same header
if (position > 0 && mData.get(position - 1).getName().substring(0, 1).equals(contact.getName().substring(0, 1))) {
holder.headerTextView.setVisibility(View.GONE);
} else {
holder.headerTextView.setVisibility(View.VISIBLE);
}
}
@Override
public int getItemCount() {
return mData.size();
}
public class DataViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.text_header)
TextView headerTextView;
@BindView(R.id.text_name)
TextView nameTextView;
public DataViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
来源:https://stackoverflow.com/questions/36911276/how-to-extend-multiple-classes-in-adapter