更新所选RecyclerView行

时间:2017-04-23 13:50:10

标签: android android-fragments android-recyclerview android-adapter

我在片段中有一个RecyclerView,其中每一行都有一个适配器,它会使布局膨胀,如下所示:enter image description here


我想访问每行的EditText(在以下代码numberET中)的值,如果EditText不为空,则选择值。<登记/> 如何循环使用RecyclerView的每个元素(我认为在适配器内部)才能产生这种行为?如何访问每个元素的EditText以检索值并在片段中使用它们?

适配器: `

public class UserFBEditTextAdapter <T extends UserFBEditTextAdapter.ViewHolder> extends UserFBAdapter<UserFBEditTextAdapter.ViewHolder>{
public UserFBEditTextAdapter(List<UserFB> users,int layoutId, Context context) {
    super(users, layoutId, context);
}

@Override
public UserFBEditTextAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
    return new UserFBEditTextAdapter.ViewHolder(view);
}

@Override
public void onBindViewHolder(UserFBAdapter.ViewHolder holder, int position) {
    holder.userFB = users.get(position);
    holder.usernameTV.setText(holder.userFB.getName());
}

public class ViewHolder extends UserFBAdapter.ViewHolder {
    protected EditText numberET;

    public ViewHolder(View itemView) {
        super(itemView);
        numberET = (EditText) itemView.findViewById(R.id.number_et);
    }
    }
}`

片段:

public class ExpenseCustomFragment extends Fragment {

private OnFragmentInteractionListener mListener;
private UserFBAdapter adapter;
private RecyclerView userCustomList;

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

public static ExpenseCustomFragment newInstance() {
    ExpenseCustomFragment fragment = new ExpenseCustomFragment();

    return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_expense_custom, container, false);

    userCustomList = (RecyclerView) view.findViewById(R.id.amountlist_rv);
    userCustomList.setLayoutManager(new LinearLayoutManager(getContext()));

    NewExpenseDescriptionActivity activity = (NewExpenseDescriptionActivity) getActivity();
    adapter = new UserFBEditTextAdapter(activity.getUsersGroup(),  R.layout.listitem_expensecustom, getContext());

    userCustomList.setAdapter(adapter);


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

1 个答案:

答案 0 :(得分:1)

您必须在某些基于地图的数据结构中保留该数据,然后,只要需要这些值,就会迭代该数据结构。

您不能依赖在ViewHolder中保存该数据,因为只要您执行滚动就会重复使用ViewHolder。如果您当前不保存EditText中填写的数据,那么如果您有许多项目并执行滚动(例如,屏幕适合10项,但您的适配器是20项,那么您将丢失该数据)滚动到第15项后,第一项的EditText值将丢失。

private Map<Integer, String> map = new ArrayMap<>(adapterSize);

...

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
    String text = map.get(holder.getAdapterPosition());
    // maybe we haven't yet saved text for this position
    holder.editText.setText(text != null ? text : "");
    // updated value in map as soon as the `EditText` in this position changes
    holder.editText.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            map.put(holder.getAdapterPosition(), s.toString());
        }

        @Override
        public void afterTextChanged(Editable s) {
        }
    });
}

现在,您可以访问EditText中的所有RecyclerView值。您可以考虑的唯一更改是在用户停止输入后更新地图。目前,如果用户类型&#34; 123456789&#34;地图将更新9次,而我们只需要一次。一个简单的解决方案是使用 RxJava debounce operatorRxBinding库结合使用。这可能听起来很复杂,但你可以看到它是多么简单in this answer

这会奏效。但是在你来回滚动之后,很快你就会发现那里发生了一些混乱。这是因为每次onBindViewHolder()被调用时,新的TextWatcher都会添加到已附加EditText的{​​{1}}。因此,在TextWatcher被回收后,您还需要注意删除TextWatcher

但是没有API可以移除ViewHolder的所有TextWatcher。您可以使用this answer中显示的自定义EditText实施,该实施将清除此EditText附带的所有TextWatcher

EditText