티스토리 뷰

728x90



이번 포스팅에서는 RecyclerView 에 header 와 footer 를 추가할 것이다.

RecyclerView 에 header, footer 를 추가하면 하단 그림과 같이 화면 상단과 하단에 별도의 view 를 지정할 수 있다.

추가한 header, footer 는 list item 에 상관없이 항상 고정으로 출력된다.

 

 

참고로, 지난 포스팅에서는 RecyclerView 에 image + text 출력, click 처리, menu 출력, Item 삽입, 수정, 삭제 하는 방법에 대해 알아 보았다.

[Android/UI] - RecyclerView (6) - RecyclerView item 추가, 수정, 삭제

[Android/UI] - RecyclerView (5) - RecyclerView item long click 시 popup menu 출력하기

[Android/UI] - RecyclerView (4) - RecyclerView item click 시 context menu 출력하기

[Android/UI] - RecyclerView (3) - RecyclerView item 의 click 처리하기

[Android/UI] - RecyclerView (2) - RecyclerView 에 image + text 출력하기



Header & footer layout resource 추가

Header, footer 에 사용될 view layout resource 를 추가하자.

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFF00"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Header" />
</LinearLayout>

 



Header & footer view holder 추가

RecyclerView 에 header, footer 를 추가하기 위해서는 하단과 같이 header, footer view holder 를 추가해야 한다.

 

public class PhHeaderViewHolder extends RecyclerView.ViewHolder {
public static int VIEW_TYPE = R.layout.content_recycler_header;
public PhHeaderViewHolder(@NonNull View a_itemView, final OnItemClickEventListener a_itemClickListener) {
super(a_itemView);
......
}
}

 

public class PhFooterViewHolder extends RecyclerView.ViewHolder {
public static int VIEW_TYPE = R.layout.content_recycler_footer;
public PhFooterViewHolder(@NonNull View a_itemView, final OnItemClickEventListener a_itemClickListener) {
super(a_itemView);
......
}
}



Header & footer view type 추가

각 view holder 를 구분하기 위해 type 을 추가한다.

예제 프로젝트에서는 각 holder 가 다른 layout resource 를 쓰고 있어서 해당 resource 를 type 에 사용했다.

 

public class PhRecyclerViewHolder extends RecyclerView.ViewHolder {
public static int VIEW_TYPE = R.layout.content_recycler_item;
......
}

 

public class PhFooterViewHolder extends RecyclerView.ViewHolder {
public static int VIEW_TYPE = R.layout.content_recycler_footer;
......
}

 

public class PhHeaderViewHolder extends RecyclerView.ViewHolder {
public static int VIEW_TYPE = R.layout.content_recycler_header;
.......
}



Adapter 의 ViewHolder 수정

지금까지의 포스팅에서는 하나의 view holder(PhRecyclerViewHolder) 를 사용했다.

Header, footer 가 추가되면 view holder 가 2개 더 추가되어 하단과 같이 부모 class 인 ViewHolder 로 수정해야 한다.

 

public class PhRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
......
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup a_viewGroup, int a_viewType) {
......
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder a_holder, int a_position) {
......
}
......
}



Adapter 에 추가된 view holder 수정사항 적용

 

public class PhRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
......
@Override
pubic int getItemViewType(int a_position) {
if (a_position == 0) {
return PhHeaderViewHolder.VIEW_TYPE;
} else if (a_position == mItemList.size() + 1) {
return PhFooterViewHolder.VIEW_TYPE;
} else {
return PhRecyclerViewHolder.VIEW_TYPE;
}
}
@Override
public int getItemCount() {
return mItemList.size() + 2;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup a_viewGroup, int a_viewType) {
View view = LayoutInflater.from(a_viewGroup.getContext()).inflate(a_viewType, a_viewGroup, false);
final RecyclerView.ViewHolder viewHolder;
if (a_viewType == PhHeaderViewHolder.VIEW_TYPE) {
viewHolder = new PhHeaderViewHolder(view, mItemClickListener);
} else if (a_viewType == PhFooterViewHolder.VIEW_TYPE) {
viewHolder = new PhFooterViewHolder(view, mItemClickListener);
} else {
viewHolder = new PhRecyclerViewHolder(view, mItemClickListener);
}
return viewHolder;
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder a_holder, int a_position) {
if (a_holder instanceof PhHeaderViewHolder) {
PhHeaderViewHolder headerViewHolder = (PhHeaderViewHolder) a_holder;
} else if (a_holder instanceof PhFooterViewHolder) {
PhFooterViewHolder footerViewHolder = (PhFooterViewHolder) a_holder;
} else {
// 기본적으로 header 를 빼고 item 을 구한다.
final PhRecyclerItem item = mItemList.get(a_position - 1);
PhRecyclerViewHolder viewHolder = (PhRecyclerViewHolder) a_holder;
viewHolder.ivIcon.setImageResource(item.getImageResId());
viewHolder.tvName.setText(item.getName());
}
......
}



Click event 처리

RecyclerView 의 header, footer view 에 click 처리를 하기 위해서는 click event listener 를 직접 등록해야 한다.

 

public class PhMainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// List 설정
bindList();
}
/**
* List 설정
*/
private void bindList() {
......
// Adapter 설정
PhRecyclerViewAdapter adapter = new PhRecyclerViewAdapter(itemList);
// Recycler view item click event 처리
adapter.setOnItemClickListener(new OnItemClickEventListener() {
@Override
public void onItemClick(View a_view, int a_position) {
if (a_position == 0) {
Toast.makeText(PhMainActivity.this, "The header is selected", Toast.LENGTH_SHORT).show();
} else if (a_position == itemList.size() + 1){
Toast.makeText(PhMainActivity.this, "The footer is selected", Toast.LENGTH_SHORT).show();
} else {
final PhRecyclerItem item = itemList.get(a_position - 1);
Toast.makeText(PhMainActivity.this, item.getName() + " Click event", Toast.LENGTH_SHORT).show();
}
}
});
......
}
}

 

public class PhRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public interface OnItemClickEventListener {
void onItemClick(View a_view, int a_position);
}
private OnItemClickEventListener mItemClickListener;
......
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup a_viewGroup, int a_viewType) {
View view = LayoutInflater.from(a_viewGroup.getContext()).inflate(a_viewType, a_viewGroup, false);
final RecyclerView.ViewHolder viewHolder;
if (a_viewType == PhHeaderViewHolder.VIEW_TYPE) {
viewHolder = new PhHeaderViewHolder(view, mItemClickListener);
} else if (a_viewType == PhFooterViewHolder.VIEW_TYPE) {
viewHolder = new PhFooterViewHolder(view, mItemClickListener);
} else {
viewHolder = new PhRecyclerViewHolder(view, mItemClickListener);
}
return viewHolder;
}
......
public void setOnItemClickListener(OnItemClickEventListener a_listener) {
mItemClickListener = a_listener;
}
}

 

public class PhHeaderViewHolder extends RecyclerView.ViewHolder {
public static int VIEW_TYPE = R.layout.content_recycler_header;
public PhHeaderViewHolder(@NonNull View a_itemView, final OnItemClickEventListener a_itemClickListener) {
super(a_itemView);
a_itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View a_view) {
final int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
a_itemClickListener.onItemClick(a_view, position);
}
}
});
}
}

 

public class PhFooterViewHolder extends RecyclerView.ViewHolder {
public static int VIEW_TYPE = R.layout.content_recycler_footer;
public PhFooterViewHolder(@NonNull View a_itemView, final OnItemClickEventListener a_itemClickListener) {
super(a_itemView);
a_itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View a_view) {
final int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
a_itemClickListener.onItemClick(a_view, position);
}
}
});
}
}



Source code

https://github.com/parkho79/RecyclerView_7



728x90
댓글