본문 바로가기
개발 공부 기록하기/- Android

RecyclerView 내부 CheckBox 체크 상태 유지시키기

by soulduse 2017. 5. 18.
반응형




개인 개발을 하다 RecyclerView 내부에 CheckBox를 추가할 일이 있었는데,


체크박스에 체크를 하고 스크롤을 내렸다가 다시 올리면 체크해놓은 아이템의 체크값이 초기화 되는 문제점이 있었다.


이를 어떻게 해결할까 구글링 해본결과 역시 해결책을 찾을 수 있었다.


내 소스는 xml과 Java 파일의 내용이 길어 짧은 스택오브플로우의 구글링한 코드를 가져왔다.


xml layout 파일이다. RecyclerView 내부에 포함될 CardView 안에 TextView, CheckBox이 포함되어 있음을 볼 수 있다.

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/cvItems"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:layout_margin="2dp"
    card_view:cardElevation="0dp"
    card_view:contentPadding="0dp"
    card_view:cardBackgroundColor="#FFFFFF"
>

<LinearLayout
android:orientation="horizontal"
android:layout_height="fill_parent"
android:layout_width="fill_parent">
<TextView
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="0.8"
android:id="@+id/tvContent"
android:textSize="15dp"
android:paddingLeft="5dp"
android:paddingRight="5dp" />
<CheckBox
android:id="@+id/cbSelect"
android:layout_width="0dip"
android:layout_weight="0.2"
android:layout_height="match_parent"
android:button="@drawable/cb_checked"
android:gravity="center_horizontal"
android:textAlignment="center"
android:layout_gravity="center_horizontal" />
</LinearLayout>
</android.support.v7.widget.CardView>


해당 Java 파일이다. RecyclerView를 사용할때 보통 다음과 같이 구성할 것이다.

public class AdapterTrashIncome extends RecyclerView.Adapter<AdapterTrashIncome.ViewHolder> {

private ArrayList<ObjectIncome> myItems = new ArrayList<>();

public AdapterTrashIncome(ArrayList<ObjectIncome> getItems, Context context){
mContext = context
;
myItems = getItems;
}

public class ViewHolder extends RecyclerView.ViewHolder {
public TextView tvContent;
public CheckBox cbSelect;

public ViewHolder(View v) {
super(v);
tvContent = (TextView) v.findViewById(R.id.tvContent);
cbSelect = (CheckBox) v.findViewById(R.id.cbSelect);
}
}

@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
final ObjectIncome objIncome = myItems.get(position);
String content = "<b>lalalla</b>";
holder.tvContent.setText(Html.fromHtml(content));

//if true, your checkbox will be selected, else unselected
holder.cbSelect.setChecked(objIncome.isSelected());

holder.cbSelect.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//set your object's last status
objIncome.setSelected(isChecked);
}
})
;
}
}


나의 경우에 위의 소스코드와 비슷하게 작성 하였는데 


//if true, your checkbox will be selected, else unselected
holder.cbSelect.setChecked(objIncome.isSelected());


소스를 보면 체크값들을 읽어 RecyclerView 안에 CheckBox 값을 초기화 해준 뒤, 앞으로 사용자가 체크할 값에 대해서 

Check Event를 달아서 setSelected를 해줌으로써 CheckBox에 체크를 할 수 있게 하였다.


그런데 위의 소스대로 해보면 RecyclerView를 아래로 스크롤 했다 다시 위로 올렸을시, 체크값이 초기화가 되는 문제가 발생한다.


해결책은 다음과 같다.


//in some cases, it will prevent unwanted situations
holder.cbSelect.setOnCheckedChangeListener(null);

//if true, your checkbox will be selected, else unselected
holder.cbSelect.setChecked(objIncome.isSelected());

holder.cbSelect.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//set your object's last status
objIncome.setSelected(isChecked);
}
});


위의 소스와 같이 아래의 해당 코드를 넣어 setOnCheckedChangeListener에 null 값으로 우선 초기화를 해준 뒤 

holder.cbSelect.setOnCheckedChangeListener(null);


기존 의 setChecked와 리스너를 사용하게되면 정상 작동함을 알 수 있다.



반응형