개발 공부 기록하기/- Android

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

soulduse 2017. 5. 18. 11:22




개인 개발을 하다 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와 리스너를 사용하게되면 정상 작동함을 알 수 있다.



반응형