(java, android) 리사이클러뷰 footer가 보이지 않습니다ㅜ
조회수 536회
위 사진은 예시의 사진입니다.
사진처럼 초기의 빈화면에 저런 footer가 있고 저런 버튼을 통해 점점 아이템을 추가해 가는
그런기능을 만들고 싶은데요
지금 footer가 아무리 해도 보이질 않습니다.. 여러 샘플을 보았지만 어디가 문제인지 잘모르겠습니다.
기존에 액티비티에서 버튼을 생성해서 기능을 다 구현했지만 마음이 바뀌어 footer로 바꾸려고
다시 하려는데 보이질 않습니다ㅠ사진처럼 footer 버튼을 눌러서 루틴을 추가하고 footer는
아이템의 마지막에 붙어서 계속 붙어 따라내려가는 그런 형태를 구현하려 합니다.
참고로 리사이클러뷰는 멀티타입 리사이클러뷰입니다(2개 타입)
루틴 아이템과 루틴 상세를 표현하는 아이템 두가지입니다.
중첩리사이클러뷰처럼 보일수 있으나 List 에 두가지 타입을 저장하여
리사이클러뷰하나 어댑터하나로 표현합니다.
전혀 상관없는 코드 같은 것은 일부는 지웠습니다.
더 필요하신 코드있으시면 말씀해주세요
RoutineAdapter.java
public class RoutineAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
final static int TYPE_ROUTINE = 1;
final static int TYPE_ROUTINE_DETAIL = 2;
final static int TYPE_ROUTINE_FOOTER = 3;
private Context context;
private List<Object> mItems = new ArrayList<>();
OnRoutineItemClickListener routinelistener;
OnRoutineAddClickListener routineAddListener;
public void updateRoutineList(List<Object> newRoutineList) {
final RoutineDiffUtil diffCallback = new RoutineDiffUtil(this.mItems, newRoutineList);
final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);
this.mItems.clear();
this.mItems.addAll(newRoutineList);
diffResult.dispatchUpdatesTo(this);
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
context = parent.getContext();
// View itemView;
if(viewType == TYPE_ROUTINE) {
View itemView = LayoutInflater.from(context).inflate(R.layout.routine_item, parent, false);
return new RoutineViewHolder(itemView);
}
else if(viewType == TYPE_ROUTINE_DETAIL) {
View itemView = LayoutInflater.from(context).inflate(R.layout.routine_detail_item, parent, false);
return new RoutineDetailViewHolder(itemView);
}
else {
View itemView = LayoutInflater.from(context).inflate(R.layout.routine_item_add, parent, false);
return new RoutineAddFooterViewHolder(itemView);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
Object object = mItems.get(position);
if(holder instanceof RoutineAddFooterViewHolder) {
RoutineAddFooterViewHolder footerVH = (RoutineAddFooterViewHolder) holder;
}
else if(object instanceof RoutineModel && holder instanceof RoutineViewHolder)
setRoutineData((RoutineViewHolder) holder, (RoutineModel) object, position);
else {
RoutineDetailModel item = (RoutineDetailModel) object;
((RoutineDetailViewHolder) holder).setDetailItem(item);
}
}
private void setRoutineData(RoutineViewHolder holder, RoutineModel routineItem, int position){
holder.routine.setText(routineItem.getRoutine());
holder.addSet.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(routinelistener != null) routinelistener.OnAddBtnClick(position);
}
});
holder.deleteSet.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(routinelistener != null) routinelistener.OnDeleteBtnClick(position);
}
});
}
public Object getRoutineItem(int position) {
if(mItems == null || position < 0 || position >= mItems.size())
return null;
return mItems.get(position);
}
@Override
public int getItemCount() {
if(mItems == null)
return -1;
return mItems.size();
}
@Override
public int getItemViewType(int position) {
Object obj = mItems.get(position);
if(position == mItems.size())
return TYPE_ROUTINE_FOOTER;
else if(obj instanceof RoutineModel)
return TYPE_ROUTINE;
else
return TYPE_ROUTINE_DETAIL;
}
// 루틴 추가인터페이스
public interface OnRoutineAddClickListener {
public void OnAddRoutineClick();
}
public void setOnAddRoutineClickListener(OnRoutineAddClickListener listener) {
this.routineAddListener = listener;
}
// 상세 추가/삭제 인터페이스
public interface OnRoutineItemClickListener {
public void OnAddBtnClick(int curRoutinePos);
public void OnDeleteBtnClick(int curRoutinePos);
}
public void setOnRoutineClickListener(OnRoutineItemClickListener listener) {
this.routinelistener = listener;
}
public class RoutineViewHolder extends RecyclerView.ViewHolder {
public TextView routine;
public Button addSet;
public Button deleteSet;
public RoutineViewHolder(@NonNull View itemView) {
super(itemView);
routine = itemView.findViewById(R.id.routine);
addSet = itemView.findViewById(R.id.add_set);
deleteSet = itemView.findViewById(R.id.delete_set);
}
}
public class RoutineDetailViewHolder extends RecyclerView.ViewHolder {
public TextView set;
public TextView weight;
public RoutineDetailViewHolder(@NonNull View itemView) {
super(itemView);
set = itemView.findViewById(R.id.set);
weight = itemView.findViewById(R.id.weight);
}
public void setDetailItem(RoutineDetailModel item) {
set.setText(item.getSet().toString() + "세트");
}
}
// footer 뷰홀더
public class RoutineAddFooterViewHolder extends RecyclerView.ViewHolder {
TextView textView;
public RoutineAddFooterViewHolder(@NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.add_text);
ConstraintLayout regionForClick = itemView.findViewById(R.id.clickable_layout);
regionForClick.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (routineAddListener != null) {
routineAddListener.OnAddRoutineClick();
}
}
});
}
}
}
MainActivity
public class WriteRoutineActivity extends AppCompatActivity {
Button add_routine_btn;
TextView title;
RecyclerView routine_rv;
LinearLayoutManager routineLayoutManger;
RoutineAdapter routineAdapter;
List<RoutineModel> items;
List<String> titleData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_write_routine);
items = new ArrayList<>();
routineAdapter = new RoutineAdapter();
routine_rv.setAdapter(routineAdapter);
//루틴 추가
routineAdapter.setOnAddRoutineClickListener(new RoutineAdapter.OnRoutineAddClickListener() {
@Override
public void OnAddRoutineClick() {
WorkoutListDialogFragment routineDialog = new WorkoutListDialogFragment();
routineDialog.show(getSupportFragmentManager(), "RoutineListDialog");
}
});
// 루틴 상세 추가,삭제
routineAdapter.setOnRoutineClickListener(new RoutineAdapter.OnRoutineItemClickListener() {
@Override
public void OnAddBtnClick(int routinePos) {
Object obj = routineAdapter.getRoutineItem(routinePos);
if(obj instanceof RoutineModel) {
RoutineModel item = (RoutineModel) obj;
item.addDetail(new RoutineDetailModel(((RoutineModel) obj).getDetailItemSize()));
routineAdapter.updateRoutineList(getDataToBeDisplayed());
// routineAdapter.updateData(getDataToBeDisplayed());
}
else
Toast.makeText(getApplicationContext(), "This is Wrong Type" ,Toast.LENGTH_SHORT).show();
}
@Override
public void OnDeleteBtnClick(int routinePos) {
Object item = routineAdapter.getRoutineItem(routinePos);
if(item instanceof RoutineModel) {
RoutineModel routineModel = (RoutineModel) item;
if(routineModel.getDetailItemSize() > 1) {
try {
routineModel.removeDetails(routineModel.getDetailItemSize() - 1);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "잘못된 값입니다.", Toast.LENGTH_SHORT).show();
}
}
else { // 상세아이템이 한개 남았을때 루틴까지 삭제
items.remove(routineModel);
}
routineAdapter.updateRoutineList(getDataToBeDisplayed());
}
}
});
}
public void addRoutine(String routine) {
RoutineModel routineModel = new RoutineModel(routine);
RoutineDetailModel routineDetailModel = new RoutineDetailModel();
routineModel.addDetail(routineDetailModel);
items.add(routineModel);
routineAdapter.updateRoutineList(getDataToBeDisplayed());
}
// 보여질 데이터
private List<Object> getDataToBeDisplayed() {
List<Object> mixedList = new ArrayList<>();
for(RoutineModel rm: items){
mixedList.add(rm);
if(rm.getDetailItemList() != null && rm.getDetailItemSize() > 0){
for(RoutineDetailModel rmdetilas: rm.getDetailItemList()){
mixedList.add(rmdetilas);
}
}
}
return mixedList;
}
}
1 답변
-
@Override public int getItemCount() { if(mItems == null) return -1; return mItems.size(); } @Override public int getItemViewType(int position) { Object obj = mItems.get(position); if(position == mItems.size()) return TYPE_ROUTINE_FOOTER; else if(obj instanceof RoutineModel) return TYPE_ROUTINE; else return TYPE_ROUTINE_DETAIL; }
items.size()
가 10일 경우 index (position) 은 0~9 까지 이므로getItemViewType()
에서if(position == mItems.size())
조건이 타지 않을 것으로 보이네요.-
(•́ ✖ •̀)
알 수 없는 사용자
- 답변감사합니다. 그런데 mitems 사이즈가 실행했을때 0이면 position도 0이라 처음에는 보여야하는것 아닌가요? codeslave 2021.2.19 04:08
- mItems 사이즈가 0 이라면 getItemViewType() 은 호출 되지 않습니다 :) 또한 position 이 0 인 경우는 리스트 사이즈가 1일 때 입니다. footer 처리를 위해 여러 방법이 있겠으나 getItemCount() 에서 mItems.size() + 1 로 처리 하거나 mItems.size() 로 그대로두고 데이터셋에 footer 를 위한 더미 데이터를 추가 한 후 데이터셋의 object 로 footer 처리를 구분하는 방식도 있겠네요. 알 수 없는 사용자 2021.2.19 15:23
- 아.. 아이템 사이즈가 아예 0이니 어댑터에서 데이터가 없다고 판단하고 뷰가 보이지를 않는거군요? 그래서 처음에 footer가 보이려면 말씀대로 getItemCount()에서 사이즈 +1해서 어댑터에서 데이터가 한개 존재하게 한다는거군요.. codeslave 2021.2.20 01:51
- 네 그렇습니다 :) 알 수 없는 사용자 2021.2.23 11:56
-
댓글 입력