【问题标题】:Android: ListView position and DatePickerAndroid:ListView 位置和 DatePicker
【发布时间】:2013-09-22 20:32:33
【问题描述】:

我有 onItemClickListener 用于在单击项目时打开 DatePicker 对话框的 ListView

list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        showDatePickerDialog(view);
    }
});

public void showDatePickerDialog(View v) {
    DialogFragment newFragment = new DatePickerFragment();
    newFragment.show(getFragmentManager(), "datePicker");
}

在 DatePicker 中设置日期后,我有 onDateSet 方法,我想用它来更新数据库并为在 ListView 中单击的项目设置日期:

public void onDateSet(DatePicker view, int year, int month, int day) {
    ...
    dataSource.updateDate(adapter.getItemId(position), month + "/" + day + "/" + year);
    ...
} 

如何将被点击项目的 ListView 位置传递给 onDateSet,以便我的数据库助手知道要更新哪条记录?


编辑:这是 DatePickerFragment 类:

public static class DatePickerFragment extends DialogFragment
        implements DatePickerDialog.OnDateSetListener {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Use the current date as the default date in the picker
        final Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH);
        int day = c.get(Calendar.DAY_OF_MONTH);

        // Create a new instance of DatePickerDialog and return it
        return new DatePickerDialog(getActivity(), this, year, month, day);
    }

    public void onDateSet(DatePicker view, int year, int month, int day) {
        ...
        dataSource.updateDate(adapter.getItemId(position), month + "/" + day + "/" + year);
        ...
    }
}

谢谢!

【问题讨论】:

    标签: android android-listview android-datepicker


    【解决方案1】:

    position 发送到DatePickerFragment - 我想这是您自己的课程。通过参数发送此参数(因为这是在片段重新创建中保护代码的最佳实践):

    public class DatePickerFragment extends Fragment {
    
        private DatePickerListener datePickerListener;
        private int listPosition = -1;
        private static final String POSITION_ARG_KEY = "POSITION_ARG_KEY";
    
        public static DatePickerFragment newInstance(int position) {
            DatePickerFragment fragment = new DatePickerFragment();
            Bundle args = new Bundle();
            args.putInt(POSITION_ARG_KEY, position);
            fragment.setArguments(args);
            return fragment;
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Bundle args = getArguments();
            if (args != null) {
                listPosition = args.getInt(POSITION_ARG_KEY);
            }
        }
    
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            if (activity instanceof DatePickerListener) {
                datePickerListener = (DatePickerListener) activity;
            }
        }
    
        @Override
        public void onDetach() {
            super.onDetach();
            datePickerListener = null;
        }
    
        public void methodThatCallsActivity() {
            if(datePickerListener) {
                datePickerListener.onDateSet(datePicker, year, month, day, this.listPosition);
            }
        }
    
        // / the rest of the code
    
        public static interface DatePickerListener {
            public void onDateSet(DatePicker view, int year, int month, int day, int listPosition);
        }
    }
    

    然后在显示fragment的activity中,(必须实现DatePickerListener):

    A.发送列表位置:

    public void showDatePickerDialog(int listPosition) {
        DialogFragment newFragment = DatePickerFragment.newInstance(listPosition);
        newFragment.show(getFragmentManager(), "datePicker");
    }
    

    B.从列表项单击调用此方法:

    list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            showDatePickerDialog(position);
        }
    });
    

    C.您在onDateSet 实现中的列表位置:

    public void onDateSet(DatePicker view, int year, int month, int day, int listPosition) {
        // your relevant code
    }
    

    简述:通过参数和参数将列表位置从列表视图发送到片段,然后从那里发送到父活动。

    【讨论】:

    • 当我尝试将位置传递给 onDateSet 时,我收到消息说我需要 实现抽象方法 onDateSet(DatePicker, int, int, int)我>。它不喜欢我在方法签名中添加另一个参数,因为我正在实现 DatePickerDialog.OnDateSetListener扩展 DialogFragment 并实现 DatePickerDialog.OnDateSetListener 时有什么方法吗?如果我无法弄清楚,我会给你一个机会,谢谢!
    • onDateSet(DatePicker, int, int, int) 属于你定义的接口?还是 Android 定义的?
    • 它在DatePickerDialog.OnDateSetListener 中由Android 定义。
    • 然后创建一个新接口LocalDatePickerListener 并使用我描述的相同方法。区别在于DatePickerListener是由fragment实现的,而LocalDatePickerListener是由宿主activity实现的。
    【解决方案2】:

    通过以下方式解决:

    使DatePickerFragment 成为自己的类(不嵌套在MainActivity 类中):

    public class DatePickerFragment extends DialogFragment {
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            // Use the current date as the default date in the picker
            final Calendar c = Calendar.getInstance();
            int year = c.get(Calendar.YEAR);
            int month = c.get(Calendar.MONTH);
            int day = c.get(Calendar.DAY_OF_MONTH);
    
            // Create a new instance of DatePickerDialog and return it
            return new DatePickerDialog(getActivity(), (MainActivity)getActivity(), year, month, day);
        }
    }
    

    这就是我的MainActivity 班级最终的样子:

    public class MainActivity extends ListActivity implements DatePickerDialog.OnDateSetListener {
        private long listId = -1;
        private int listPosition = -1;
        private String date;
        ...
    
        protected void onCreate(Bundle savedInstanceState) {
            list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    listId = id;
                    listPosition = position;
                    showDatePickerDialog(view);
        ...
    
        // Show DatePicker when clicking on contact in ListView
        public void showDatePickerDialog(View view) {
            DialogFragment newFragment = new DatePickerFragment();
            newFragment.show(getFragmentManager(), "datePicker");
        }
    
        // Update database and ListView adapter with selected date
        public void onDateSet(DatePicker view, int year, int month, int day) {
            date = (month + 1) + " " + day + ", " + year;
            ...
            dataSource.updateDate(listId, date);
            adapter.setDate(listPosition, date);
            ...
            adapter.notifyDataSetChanged();
            dataSource.close();
        }
    

    旁注:按下 DatePicker 的取消按钮(和 Android 后退按钮)仍会将默认日期保存到数据库并更新适配器。这是解决此问题的帖子:https://stackoverflow.com/a/15289569/1261256

    【讨论】:

    • 如果对话框打开,同时您接到电话或任何使您的活动进入后台的操作,则活动有资格被销毁。如果它被销毁然后你的活动被重新创建listId 被重置为零。此外,像您一样依赖状态流中字段的状态是一种不好的做法。通过参数而不是状态感知来维持数据通信。
    • 如果活动被破坏,为什么listId被重置很重要?当用户再次选择 ListView 行时,它会得到适当的设置,对吗?不过,我认为您的观点是,取决于字段状态是不好的做法。关于如何通过参数传递位置/id来解决我当前的方法的任何想法?谢谢。
    • 我说的是对话框打开时的情况——实际上显示对话框的片段已添加并可见。因此,此时您有一个 listId,假设为 10。当 Activity 在此状态下销毁然后恢复时,将打开对话框(Android 会处理)并且 listId 是......零!这个问题的作者必须改变当前的onDateSet,所以它会接受一个额外的int - 列表位置。
    猜你喜欢
    • 2018-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多