【问题标题】:How to perform this date update on my RecyclerView rows?如何在我的 RecyclerView 行上执行此日期更新?
【发布时间】:2016-08-24 01:13:42
【问题描述】:

在我的 RecyclerView 适配器中,我的行具有显示日期的 TextView。如果用户单击 TextView,则会显示一个 DialogFragment,让用户选择时间和日期,然后通过接口传回 Date。

但是我不知道如何在我添加到 TextView 的 onClick 方法中获取日期。

public class RecyclerViewHolder extends RecyclerView.ViewHolder {
        public TextView dateTextView;
        public RecyclerViewHolder(View itemView) {
            super(itemView);
            dateTextView = (TextView) itemView.findViewById(R.id.date_textview);

            dateTextView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //I can call my DialogFragment here but then what?
                }
            });

【问题讨论】:

    标签: android interface android-recyclerview adapter android-dialogfragment


    【解决方案1】:

    您可以创建一个接口来与适配器通信:

    public class RecyclerViewHolder extends RecyclerView.ViewHolder {
    
        public TextView dateTextView;
        private IAdapter adapter;
    
        public RecyclerViewHolder(View itemView, IAdapter adapter) {
            super(itemView);
            dateTextView = (TextView) itemView.findViewById(R.id.date_textview);
            this.adapter = adapter;
    
            dateTextView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    MyDialogFragment fragment = MyDialogFragment.newInstance(getAdapterPosition(), adapter);
                    FragmentTransaction ft = v.getContext().getFragmentManager().beginTransaction();
                    fragment.show(ft, "calendarDialog");
                }
            });
        }
    }
    

    适配器需要实现的接口是:

    interface IAdapter extends Serializable {
        void setDataAt(int index, Calendar date);
        void notifyItemChanged(int index);
    }
    

    由于适配器已经有了notifyItemChanged 方法,你只需要实现setDataAt 方法。

    假设您的适配器将只包含日期,下面是一个示例:

    public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewHolder> implements IAdapter {
    
        private List<Calendar> dates = new ArrayList<>();
    
        public RecyclerViewAdapter(List<Calendar> dates) {
            this.dates = dates;
        }
    
        @Override
        public void setDataAt(int index, Calendar date) {
            dates.add(index, date);
        }
    
        @Override
        public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
            View holderView = inflater.inflate(R.layout.view_holder, parent, false);
            return new RecyclerViewHolder(holderView, this); // notice how we pass this adapter's interface along with the view
        }
    
        // Include other methods (getItemCount, onBindViewHolder, etc.)
        // Adapter already has the notifyItemChanged(int index) method so no need to override it
    }
    

    这是一个使用索引位置和Calendar 对象的DialogFragment 示例:

    public static class MyDialogFragment extends DialogFragment {
        private int index;
        private IAdapter adapter;
    
    
        public static MyDialogFragment newInstance(int index, IAdapter adapter) {
            MyDialogFragment f = new MyDialogFragment();
    
            Bundle args = new Bundle();
            args.putInt("index", index);
            args.putSerializable("adapter", adapter);
            f.setArguments(args);
    
            return f;
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Bundle args = getArguments();
            index = args.getInt("index");
            adapter = args.getSerializable("adapter");
        }
    
        // Build view and set OnClickListener for setting date
    }
    

    用户更新日期后,调用以下命令:

    adapter.setDataAt(index, date);
    adapter.notifyItemChanged(index);
    

    【讨论】:

    • 我不明白,DialogFragment 仍然需要将日期传递回底层活动,因为它也需要一个接口
    • @ArukaJ 您是否需要在活动级别将其保存到某种数据库中?然后您可以创建一个RecyclerView.AdapterDataObserver,它会在数据更改时进行监听,然后您可以对数据库执行必要的操作
    • DialogFragment 有一个由用户修改的日历。 myCalendar.getTime();是我需要访问适配器中行的日期。当用户在该 DialogFragment 上按 OK 时,我必须以某种方式将其传回。
    • @ArukaJ 我更新了代码以传递Calendar 对象。适配器负责处理数据,这就是为什么您需要告诉适配器数据更新的位置以及数据是什么的原因。如果您需要活动了解这些更改(如果您想保存到数据库中),您可以使用AdapterDataObserver
    • 我又一头雾水了,我该如何从 DialogFragment 将日历发回? IAdapter 在哪里定义? setDataAt() 和 notifyItemChanged() 放在哪里?
    【解决方案2】:

    试试

    RecyclerView.notifyItemChanged(i);
    

    其中 i 是要更新的项目的索引。

    【讨论】:

    • 怎么样?接口中的覆盖函数必须放置在底层 Activity 中
    【解决方案3】:

    我想提出一个更简单的解决方案:由于单击处理程序接收视图作为参数,因此回收器适配器和选择器对话框之间的所有必要通信都可以通过视图上的标签来实现。在此处查看允许设置日期和时间的对话框序列:

    RecyclerAdapter(假设数组列表encounters为数据模型):

    @Override
    public void onBindViewHolder(
            EncounterViewHolder holder, int position) {
        final Encounter encounter = encounters.get(position);
        holder.getDate().setText(encounter.getDate());
        holder.getDate().setTag(R.string.tag_adapter, this);
        holder.getDate().setTag(R.string.tag_position, new Integer(position));
        holder.getDate().setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                showDatePickerDialog(view);
                return true;
            }
        });
    }
    
    public void showDatePickerDialog(View view) {
        DatePickerFragment datePickerFragment = new DatePickerFragment(view);
        datePickerFragment.show(((FragmentActivity) context).getSupportFragmentManager(), "datePicker");
    }
    
    public void showTimePickerDialog(View view) {
        TimePickerFragment timePickerFragment = new TimePickerFragment(view);
        timePickerFragment.show(((FragmentActivity) context).getSupportFragmentManager(), "timePicker");
    }
    
    void notifyDateTimeChanged(int position, Calendar calendar) {
        encounters.get(position).setDate(new Timestamp().get(calendar));
        notifyDataSetChanged();
    }
    

    日期选择器片段:

    public class DatePickerFragment extends DialogFragment
            implements DatePickerDialog.OnDateSetListener  {
    
    private View view;
    
    DatePickerFragment(View view) {
        this.view = view;
    }
    
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Calendar cal = Calendar.getInstance();
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH);
        int day = cal.get(Calendar.DAY_OF_MONTH);
        return new DatePickerDialog(getActivity(), this, year, month, day);
    }
    
    @Override
    public void onDateSet(DatePicker view, int year, int month, int day) {
        Calendar calendar = new GregorianCalendar();
        calendar.set(year, month, day);
        (this.view).setTag(R.string.tag_calendar, calendar);
        EncounterRecyclerAdapter adapter = (EncounterRecyclerAdapter) (this.view).getTag(R.string.tag_adapter);
        adapter.showTimePickerDialog(this.view);
    }
    }
    

    时间选择器片段:

    public class TimePickerFragment extends DialogFragment
            implements TimePickerDialog.OnTimeSetListener  {
    
    private View view;
    
    TimePickerFragment(View view)
    {
        this.view = view;
    }
    
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Calendar cal = Calendar.getInstance();
        int hour = cal.get(Calendar.HOUR_OF_DAY);
        int minute = cal.get(Calendar.MINUTE);
        return new TimePickerDialog(getActivity(), this, hour, minute,
                DateFormat.is24HourFormat(getActivity()));
    }
    
    @Override
    public void onTimeSet(TimePicker view, int hour, int minute) {
        EncounterRecyclerAdapter adapter = (EncounterRecyclerAdapter) (this.view).getTag(R.string.tag_adapter);
        int position = ((Integer) (this.view).getTag(R.string.tag_position));
        GregorianCalendar calendar = ((GregorianCalendar) (this.view).getTag(R.string.tag_calendar));
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), hour, minute);
        adapter.notifyDateTimeChanged(position, calendar);
    }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-03-21
      • 1970-01-01
      • 2011-10-01
      • 2013-04-18
      • 2022-08-11
      • 2018-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多