如何从适配器到片段获取复选框值

时间:2018-07-11 23:01:39

标签: android android-fragments android-recyclerview android-checkbox

我有一个cardView自定义布局,里面有一个复选框,我在片段的recyclerView中使用这个cardView(我有3个片段和一个适配器)。

我尝试通过不同的教程为复选框实现setOnCheckedListener,因为我需要知道是否已检查recyclerView内部的所有复选框,并将每个复选框的布尔值放入片段的SparseBooleanArray中。

我的适配器:

public class WarmupProgramAdapter extends RecyclerView.Adapter<WarmupProgramAdapter.ProductViewHolder> {

private Context mCtx;
private List<Program> warmupProgramList;

public WarmupProgramAdapter(Context mCtx, List<Program> warmupProgramList) {
    this.mCtx = mCtx;
    this.warmupProgramList = warmupProgramList;
}

@NonNull
@Override
public ProductViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    //inflating and returning our view holder
    LayoutInflater inflater = LayoutInflater.from(mCtx);
    View view = inflater.inflate(R.layout.custom_program_card_layout, null);
    ProductViewHolder holder = new ProductViewHolder(view);
    return holder;
}

@Override
public void onBindViewHolder(@NonNull final ProductViewHolder holder, final int position) {
    //getting the program of the specified position
    final Program program = warmupProgramList.get(position);

    //binding the data with the viewholder views
    holder.imageView.setImageDrawable(mCtx.getResources().getDrawable(program.getImage()));
    holder.tvName.setText(program.getName());
    holder.tvHow.setText(program.getHow());
    holder.tvHint.setText(program.getHint());
    holder.checkBox.setChecked(program.getDone());

    holder.checkBox.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (program.getDone()) {
                program.setDone(false);
                cbWarmupProgramStateArray.put(position, false);
            } else {
                program.setDone(true);
                cbWarmupProgramStateArray.put(position, true);
            }

            int trueCount = 0;
            for (int i = 0; i < cbWarmupProgramStateArray.size(); i++) {
                if (cbWarmupProgramStateArray.get(i)) {
                    trueCount++;
                }
                if ((trueCount == WarmupFragment.programWarmupList.size())) {
                    Toast.makeText(mCtx, " ## Program done !", Toast.LENGTH_SHORT).show();
                    break;
                }
            }
        }
    });
}

@Override
public int getItemCount() {
    return warmupProgramList.size();
}

static class ProductViewHolder extends RecyclerView.ViewHolder{

    TextView tvName, tvHow, tvHint;
    ImageView imageView;
    CheckBox checkBox;

    ProductViewHolder(View itemView) {
        super(itemView);

        imageView = itemView.findViewById(R.id.iv_type_program);
        tvName = itemView.findViewById(R.id.tv_name_program);
        tvHow = itemView.findViewById(R.id.tv_how_program);
        tvHint = itemView.findViewById(R.id.tv_hint_program);
        checkBox = itemView.findViewById(R.id.cb_program);
    }
}
}

如您所见,我尝试使用setOnClickListener作为复选框,我将所有值都放入了SparseBooleanArray中,但是我不知道是否可以在Fragment中获取此数组,以及这样做是否正确。< / p>

我的片段:

public class WarmupFragment extends Fragment {

RecyclerView recyclerViewWarmup;
RecyclerView.LayoutManager layoutManagerWarmup;
ProgramAdapter programAdapterWarmup;
public static List<Program> programWarmupList;
ArrayList<Program> programWarmupObject;

private OnFragmentInteractionListener mListener;

public WarmupFragment() {
    // Required empty public constructor
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    final View warmupView = inflater.inflate(R.layout.fragment_warmup, container, false);

    programWarmupObject = new ArrayList<>();
    programWarmupObject.clear();

    if (getArguments() != null) {
        programWarmupObject = getArguments().getParcelableArrayList("warmupProgramListForFragment");
    }

    recyclerViewWarmup = warmupView.findViewById(R.id.warmup_recycler_view);
    recyclerViewWarmup.setHasFixedSize(false);
    layoutManagerWarmup = new LinearLayoutManager(getContext());
    recyclerViewWarmup.setLayoutManager(layoutManagerWarmup);

    programWarmupList = new ArrayList<>();

    programWarmupList.addAll(programWarmupObject);

    programAdapterWarmup = new ProgramAdapter(getContext(), programWarmupList);
    recyclerViewWarmup.setAdapter(programAdapterWarmup);

    return warmupView;
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    if (context instanceof OnFragmentInteractionListener) {
        mListener = (OnFragmentInteractionListener) context;
    } else {
        throw new RuntimeException(context.toString()
                + " must implement OnFragmentInteractionListener");
    }
}

@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}

public interface OnFragmentInteractionListener {
    // TODO: Update argument type and name
    void onFragmentInteraction(Uri uri);
}
}

我的程序对象:

public class Program implements Parcelable {
private int image;
private String name;
private String how;
private String hint;
private boolean isDone;

public Program(Parcel in) {
    super();
    readFromParcel(in);
}

public static final Parcelable.Creator<Program> CREATOR = new Creator<Program>() {
    @Override
    public Program createFromParcel(Parcel in) {
        return new Program(in);
    }

    @Override
    public Program[] newArray(int size) {
        return new Program[size];
    }
};

public Program(int image, String name, String how, String hint) {
    this.image = image;
    this.name = name;
    this.how = how;
    this.hint = hint;
}

public void readFromParcel(Parcel in) {
    image = in.readInt();
    name = in.readString();
    how = in.readString();
    hint = in.readString();
}

@Override
public void writeToParcel(Parcel dest, int i) {
    dest.writeInt(image);
    dest.writeString(name);
    dest.writeString(how);
    dest.writeString(hint);
}

@Override
public String toString() {
    return image + " , " + name + " , " + how + " , " + hint;
}

public int getImage() {
    return image;
}

public String getName() {
    return name;
}

public String getHow() {
    return how;
}

public String getHint() {
    return hint;
}

public boolean getDone() {
    return isDone;
}

public void setDone(boolean done) {
    isDone = done;
}

@Override
public int describeContents() {
    return 0;
}
}

谢谢。

(对不起,我不能点英语)

1 个答案:

答案 0 :(得分:1)

好的,您需要做的很简单。

首先,我不知道cbWarmupProgramStateArray变量来自何处,我看到您正在使用它在Adapter中存储布尔值,但在任何地方都看不到它被声明为字段。根据名称和使用该变量的方式,我的猜测是某种List<Boolean>

您不需要具有List<Boolean>List<Program>Program已经有一个布尔字段,您应该使用它来跟踪用户是否检查了程序。

关于与片段的通信。您需要在适配器中声明一个回调接口,例如:

public class WarmupProgramAdapter ... {

    interface AdapterCallback {
        void isAllChecked();
        void programChecked(Program program);
    }

    ...

}

您可以像这样调用回调:

//Do this..

warmupProgramList.get(position).setDone(checkBox.isChecked());
//IDK if your fragment needs to know about individual checks, just added this in case
fragmentCallback.programChecked(warmupProgramList.get(position), checkBox.isChecked());

//Instead of..
//if (checkBox.isChecked()) {
//  checkBox.setChecked(true); //There's no need to programatically set the checkbox checked, the checkbox is check before triggering the View.OnClick listener
//  cbWarmupProgramStateArray.put(position, true);
//} else {
//  checkBox.setChecked(false);
//  cbWarmupProgramStateArray.put(position, false);
//}

//And do this..

Boolean allTrue = true;
for (Program program : warmupProgramList) {
    if (!program.getDone()) {
        allTrue = false;
        break;
    }
}

if (allTrue) {
    fragmentCallback.isAllChecked();
}

//Instead of this...

//int trueCount = 0;
//for (int i = 0; i < cbWarmupProgramStateArray.size(); i++) {
//  if (cbWarmupProgramStateArray.get(i)) {
//      trueCount++;
//  }
//  if ((trueCount == WarmupFragment.programWarmupList.size())) {
//      Toast.makeText(mCtx, " ## Program done !", Toast.LENGTH_SHORT).show();
//      break;
//  }
//}

fragmentCallback字段是接口AdapterCallback。它应该由片段实现,并且应该将其传递给适配器的构造函数。