在 Android 日历视图中首先显示年份选择

Posted

技术标签:

【中文标题】在 Android 日历视图中首先显示年份选择【英文标题】:Show year selection first in Android Calendar View 【发布时间】:2016-11-23 10:41:50 【问题描述】:

在 Lollipop 之后,DatePicker 有一个非常漂亮的日历视图来选择日期。但问题是选择年份。大多数老百姓都面临着选择年份的麻烦。他们只是滚动。滚动变化的年份需要很长时间。所以我需要在 android 中打开 Datepicker Dialog 时首先显示年份选择。

日期选择器正常打开如下:

但它应该从年份选择开始。如下图:

【问题讨论】:

请参考这个链接github.com/wdullaer/MaterialDateTimePicker使用这个showYearPickerFirst方法 谢谢。使用 MaterialDateTimePicker 插件成功获得 这是一个很常见的问题,我每周都会收到几封来自用户的支持电子邮件,告诉我日期选择器是多么愚蠢,因为他们必须滚动 40 年。从一年开始可能会解决这个问题。但我认为这个对话框的用户体验很差。 【参考方案1】:

您可以获得对年视图的引用,然后只需模拟用户单击即可打开它。

dataPicker.getTouchables().get( 0 ).performClick();

更新: 如果不清楚,我会解释每一步。您需要先有 datePicker 参考。使用 datePicker 参考,您可以使用 getTouchables() 方法获取 datePicker 组件。 组件年份位于首位,因此需要调用 .get(0) 来获取对年份的引用。 之后只需模拟用户单击以在开始时打开年份视图,而不是等待用户单击它。

【讨论】:

更具体的是什么?如果不清楚,我会解释每一步。他需要先有 datePicker 参考。通过 datePicker 参考,他可以使用 getTouchables() 方法获取 datePicker 组件。组件年位于首位,因此需要调用 get(0) 来获取对它的引用。之后只需模拟用户单击以在开始时打开年份视图,而不是等待用户单击它。 这是我 6 年来在 Android 上找到的最有效的解决方法。太棒了!【参考方案2】:

扩展@MatejVukosav 的回答

 if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Build.VERSION.SDK_INT < Build.VERSION_CODES.M) 
        LogUtil.LogToConsole(TAG, "Date picker select");
        datePickerDialog.getDatePicker().getTouchables().get(1).performClick();
     else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
        LogUtil.LogToConsole(TAG, "Date picker select post lollipop");
        datePickerDialog.getDatePicker().getTouchables().get(0).performClick();
    

然后显示对话框。

【讨论】:

【参考方案3】:

扩展@Giovanny Piñeros 答案我想建议遍历所有可触摸对象并通过 id 选择相应的对象,以确保选择正确的视图。

int viewId = 0;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.M) 
            viewId = Resources.getSystem().getIdentifier("date_picker_year",  "id", "android");
 else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
            viewId = Resources.getSystem().getIdentifier("date_picker_header_year",  "id", "android"); 

然后,如果 (viewId > 0),我们可以遍历 datePickerDialog.getDatePicker().getTouchables() 并将它们的 id 与 viewId 进行比较。

【讨论】:

【参考方案4】:

没有非常可靠的方法来做到这一点:

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    DatePicker datePicker = (DatePicker) findViewById(R.id.test);

    openYearView(datePicker);


private void openYearView(DatePicker datePicker) 
    try 
        Field mDelegateField = datePicker.getClass().getDeclaredField("mDelegate");
        mDelegateField.setAccessible(true);
        Object delegate = mDelegateField.get(datePicker);
        Method setCurrentViewMethod = delegate.getClass().getDeclaredMethod("setCurrentView", int.class);
        setCurrentViewMethod.setAccessible(true);
        setCurrentViewMethod.invoke(delegate, 1);
     catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) 
    

【讨论】:

日期选择器对话框怎么样? @JohnSardinha 使用 openYearView(dialog.getDatePicker());在你打电话之前 dialog.show(); 是的,这适用于所有操作系统版本。 performClick() 方法在 Marshmallow 及以下为我崩溃了。 @ElhananMishraky 我可以处理确定的点击并取消,当我点击一年时?请【参考方案5】:

kotlin 用户基于此线程上的现有答案供将来参考。

    var viewId = 0
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.M) 
        viewId = Resources.getSystem().getIdentifier("date_picker_year", "id", "android")
     else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
        viewId = Resources.getSystem().getIdentifier("date_picker_header_year", "id", "android")
    

    yourDatePickerDialog.show()


    for (touchable in yourDatePickerDialog.getDatePicker().getTouchables()) 
        if (touchable.id.equals(viewId))
        
            touchable.performClick()
            break
        

    

【讨论】:

完美运行。【参考方案6】:

我正在使用 react-native 并且 DateTimePicker 组件具有 display="spinner" 选项。在这种情况下,日历呈现如下图所示。

【讨论】:

【参考方案7】:

您可以通过在 dialog.show() 之前仅包含一行来做到这一点

    editext.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View view) 
            calendar=Calendar.getInstance();
            int day=calendar.get(Calendar.DAY_OF_MONTH);
            int month=calendar.get(Calendar.MONTH);
            int year=calendar.get(Calendar.YEAR);
            calendar.add(Calendar.DAY_OF_YEAR, 1);
            datePickerDialog=new DatePickerDialog(ActivityDoctorDetails.this, R.style.DialogTheme, new DatePickerDialog.OnDateSetListener() 
                @Override
                public void onDateSet(DatePicker datePicker, int m_year, int m_month, int m_day) 
                    String Mday, Mmonth, Myear;

                    Mday=Integer.toString(m_day);
                    Mmonth=Integer.toString(m_month);

                    if (m_day < 10) 
                        // editTextDate.setText("0"+m_day+"/"+m_month+"/"+m_year);
                        Mday="0" + Integer.toString(m_day);
                    
                    if (m_month < 10) 
                        //editTextDate.setText(m_day+"/"+"0"+m_month+"/"+m_year);
                        Mmonth="0" + Integer.toString(m_month);

                    
                    if (m_day < 10 && m_month < 10) 
                        //editTextDate.setText("0" + m_day + "/" + "0" + m_month + "/" + m_year);
                        Mday="0" + Integer.toString(m_day);
                        Mmonth="0" + Integer.toString(m_month);


                    
                    if (m_day > 10 && m_month < 10) 
                        //editTextDate.setText(m_day+"/"+"0"+m_month+"/"+m_year);
                        Mmonth="0" + Integer.toString(m_month);
                        Mday=Integer.toString(m_day);


                    
                    if (m_day < 10 && m_month > 10) 
                        //editTextDate.setText(m_day+"/"+"0"+m_month+"/"+m_year);
                        Mday="0" + Integer.toString(m_day);
                        Mmonth=Integer.toString(m_month);

                    

                    editext.setText(m_year + "/" + Mmonth + "/" + Mday);


                
            , day, month, year);
            //datePickerDialog.getDatePicker().setMinDate(System.currentTimeMillis() - 1000);
            datePickerDialog.getDatePicker().getTouchables().get(0).performClick();
            datePickerDialog.show();
        

【讨论】:

以上是关于在 Android 日历视图中首先显示年份选择的主要内容,如果未能解决你的问题,请参考以下文章

android有月份选择器吗?或者怎么让日期选择器的日期不显示,只显示年份和月份

在输入字段 c# 中的 Unity 上显示从日历中选择的日期

日期选择器的 Android 日历视图

只有年/月视图的 PyQt 日历

在 PostgreSQL 视图中显示最近 3 个日历年的记录

android日历控件