如何使用其他日历系统提供 DatePicker 小部件?
Posted
技术标签:
【中文标题】如何使用其他日历系统提供 DatePicker 小部件?【英文标题】:How to feed DatePicker widget with other calendar sytems? 【发布时间】:2013-07-31 07:36:15 【问题描述】:是否可以将DatePicker
小部件与其他日历系统一起使用?
我需要Jalali
(波斯)日历系统的选择器,但我不知道如何为DatePicker
提供我的数据。
我研究了与DatePicker
相关的方法,但找不到任何可以让我这样做的方法。
我还发现了一个名为 android-wheel 的自定义小部件,它是一个 ios-styled
小部件,感觉不是原生的,但它允许我实现它。
那么是否有一个 native-looking DatePicker
小部件让我可以为 Jalali
日历系统选择日期并在 波斯语 中使用月份名称?
更新:我之前已经回答了我的问题,它解决了问题,但是@Mohamad Amin 为此创建了一个great library,我强烈建议您使用他的库(感谢 Mohamad阿明)。
【问题讨论】:
您好 Nevercom,您的问题得到了吗?我使用这个问题的答案,但我得到了例外,你能帮帮我吗? @Shayanpourvatan 嗨,Shayan,我实际上正在使用我在下面提供的答案,你面临什么问题? 感谢您的回复,我认为他的库有问题,在 android-numberpicker 上出现错误,在获取资源文件时 第 14 行 @xml 文件发生错误,该文件需要从库中扩展布局, @Shayanpourvatan 开始一个新问题并发布LogCat
输出,当你这样做时告诉我。
【参考方案1】:
我最终使用了NumberPicker
小部件,因为它仅适用于API 11
及更高版本,所以我使用了android-numberpicker 库。虽然有一个android-datepicker是同一作者的,但是我用不了。
这是我的代码,只需添加 android-numberpicker 作为库。
XML 布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/linlay1"
android:layout_
android:layout_
android:orientation="vertical" >
<LinearLayout
android:id="@+id/linlay2"
android:layout_
android:layout_
android:orientation="horizontal" >
<net.simonvt.numberpicker.NumberPicker
android:id="@+id/npYear"
android:layout_
android:layout_ >
</net.simonvt.numberpicker.NumberPicker>
<net.simonvt.numberpicker.NumberPicker
android:id="@+id/npMonth"
android:layout_
android:layout_ >
</net.simonvt.numberpicker.NumberPicker>
<net.simonvt.numberpicker.NumberPicker
android:id="@+id/npDay"
android:layout_
android:layout_ >
</net.simonvt.numberpicker.NumberPicker>
</LinearLayout>
<Button
android:id="@+id/btnDateFrom"
android:layout_
android:layout_
android:layout_gravity="center_horizontal"
android:text="OK" />
</LinearLayout>
Java 类:
package ir.aydangostar.supportdesk.activities;
import ir.aydangostar.supportdesk.R;
import ir.aydangostar.supportdesk.utils.JDF;
import net.simonvt.numberpicker.NumberPicker;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.actionbarsherlock.view.Window;
public class DatePickerActivity extends Activity
public static final String G_DAY = "gDay";
public static final String G_MONTH = "gMonth";
public static final String G_YEAR = "gYear";
public static final String J_DAY = "jDay";
public static final String J_MONTH = "jMonth";
public static final String J_YEAR = "jYear";
private String[] monthNames = "فروردین", "اردیبهشت", "خرداد", "تیر",
"مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند" ;
private NumberPicker npDay;
private NumberPicker npMonth;
private NumberPicker npYear;
@Override
protected void onCreate(Bundle savedInstanceState)
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.requestWindowFeature((int) Window.FEATURE_NO_TITLE);
setContentView(R.layout.date_picker);
NumberPicker.OnValueChangeListener onChangeListener = new NumberPicker.OnValueChangeListener()
@Override
public void onValueChange(NumberPicker picker, int oldVal,
int newVal)
if (picker == npMonth)
if (newVal <= 6)
npDay.setMaxValue(31);
else
npDay.setMaxValue(30);
;
npYear = (NumberPicker) findViewById(R.id.npYear);
npMonth = (NumberPicker) findViewById(R.id.npMonth);
npDay = (NumberPicker) findViewById(R.id.npDay);
Button btnOk = (Button) findViewById(R.id.btnDateFrom);
npMonth.setOnValueChangedListener(onChangeListener);
JDF jdf = new JDF();
int iranianYear = jdf.getIranianYear();
int iranianMonth = jdf.getIranianMonth();
int iranianDay = jdf.getIranianDay();
npYear.setMinValue(1390);
npYear.setMaxValue(iranianYear);
npYear.setWrapSelectorWheel(true);
npMonth.setMinValue(1);
npMonth.setMaxValue(12);
npMonth.setDisplayedValues(monthNames);
npDay.setMinValue(1);
npDay.setMaxValue(31);
npYear.setValue(iranianYear);
npMonth.setValue(iranianMonth);
npDay.setValue(iranianDay);
btnOk.setOnClickListener(new OnClickListener()
@Override
public void onClick(View v)
int newIrYear = npYear.getValue();
int newIrMonth = npMonth.getValue();
int newIrDay = npDay.getValue();
JDF jdf = new JDF();
jdf.setIranianDate(newIrYear, newIrMonth, newIrDay);
Intent returnIntent = new Intent();
returnIntent.putExtra(J_YEAR, newIrYear);
returnIntent.putExtra(J_MONTH, newIrMonth);
returnIntent.putExtra(J_DAY, newIrDay);
returnIntent.putExtra(G_YEAR, jdf.getGregorianYear());
returnIntent.putExtra(G_MONTH, jdf.getGregorianMonth());
returnIntent.putExtra(G_DAY, jdf.getGregorianDay());
setResult(RESULT_OK, returnIntent);
finish();
);
我使用JDF
类进行日期转换,这里是类:
package ir.aydangostar.supportdesk.utils;
import java.util.Calendar;
import java.util.GregorianCalendar;
public class JDF
/**
* Main: The default constructor uses the current Gregorian date to
* initialize the other private memebers of the class (Iranian and Julian
* dates).
*/
public JDF()
Calendar calendar = new GregorianCalendar();
setGregorianDate(calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH) + 1,
calendar.get(Calendar.DAY_OF_MONTH));
/**
* Main: This constructor receives a Gregorian date and initializes the
* other private members of the class accordingly.
*
* @param year
* int
* @param month
* int
* @param day
* int
* @return
*/
public JDF(int year, int month, int day)
setGregorianDate(year, month, day);
/**
* getIranianYear: Returns the 'year' part of the Iranian date.
*
* @return int
*/
public int getIranianYear()
return irYear;
/**
* getIranianMonth: Returns the 'month' part of the Iranian date.
*
* @return int
*/
public int getIranianMonth()
return irMonth;
/**
* getIranianDay: Returns the 'day' part of the Iranian date.
*
* @return int
*/
public int getIranianDay()
return irDay;
/**
* getGregorianYear: Returns the 'year' part of the Gregorian date.
*
* @return int
*/
public int getGregorianYear()
return gYear;
/**
* getGregorianMonth: Returns the 'month' part of the Gregorian date.
*
* @return int
*/
public int getGregorianMonth()
return gMonth;
/**
* getGregorianDay: Returns the 'day' part of the Gregorian date.
*
* @return int
*/
public int getGregorianDay()
return gDay;
/**
* getJulianYear: Returns the 'year' part of the Julian date.
*
* @return int
*/
public int getJulianYear()
return juYear;
/**
* getJulianMonth: Returns the 'month' part of the Julian date.
*
* @return int
*/
public int getJulianMonth()
return juMonth;
/**
* getJulianDay() Returns the 'day' part of the Julian date.
*
* @return int
*/
public int getJulianDay()
return juDay;
/**
* getIranianDate: Returns a string version of Iranian date
*
* @return String
*/
public String getIranianDate()
return (irYear + "/" + irMonth + "/" + irDay);
/**
* getGregorianDate: Returns a string version of Gregorian date
*
* @return String
*/
public String getGregorianDate()
return (gYear + "/" + gMonth + "/" + gDay);
/**
* getJulianDate: Returns a string version of Julian date
*
* @return String
*/
public String getJulianDate()
return (juYear + "/" + juMonth + "/" + juDay);
/**
* getWeekDayStr: Returns the week day name.
*
* @return String
*/
public String getWeekDayStr()
String weekDayStr[] = "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", "Sunday" ;
return (weekDayStr[getDayOfWeek()]);
/**
* toString: Overrides the default toString() method to return all dates.
*
* @return String
*/
@Override
public String toString()
return (getWeekDayStr() + ", Gregorian:[" + getGregorianDate()
+ "], Julian:[" + getJulianDate() + "], Iranian:["
+ getIranianDate() + "]");
/**
* getDayOfWeek: Returns the week day number. Monday=0..Sunday=6;
*
* @return int
*/
public int getDayOfWeek()
return (JDN % 7);
/**
* nextDay: Go to next julian day number (JDN) and adjusts the other dates.
*/
public void nextDay()
JDN++;
JDNToIranian();
JDNToJulian();
JDNToGregorian();
/**
* nextDay: Overload the nextDay() method to accept the number of days to go
* ahead and adjusts the other dates accordingly.
*
* @param days
* int
*/
public void nextDay(int days)
JDN += days;
JDNToIranian();
JDNToJulian();
JDNToGregorian();
/**
* previousDay: Go to previous julian day number (JDN) and adjusts the otehr
* dates.
*/
public void previousDay()
JDN--;
JDNToIranian();
JDNToJulian();
JDNToGregorian();
/**
* previousDay: Overload the previousDay() method to accept the number of
* days to go backward and adjusts the other dates accordingly.
*
* @param days
* int
*/
public void previousDay(int days)
JDN -= days;
JDNToIranian();
JDNToJulian();
JDNToGregorian();
/**
* setIranianDate: Sets the date according to the Iranian calendar and
* adjusts the other dates.
*
* @param year
* int
* @param month
* int
* @param day
* int
*/
public void setIranianDate(int year, int month, int day)
irYear = year;
irMonth = month;
irDay = day;
JDN = IranianDateToJDN();
JDNToIranian();
JDNToJulian();
JDNToGregorian();
/**
* setGregorianDate: Sets the date according to the Gregorian calendar and
* adjusts the other dates.
*
* @param year
* int
* @param month
* int
* @param day
* int
*/
public void setGregorianDate(int year, int month, int day)
gYear = year;
gMonth = month;
gDay = day;
JDN = gregorianDateToJDN(year, month, day);
JDNToIranian();
JDNToJulian();
JDNToGregorian();
/**
* setJulianDate: Sets the date according to the Julian calendar and adjusts
* the other dates.
*
* @param year
* int
* @param month
* int
* @param day
* int
*/
public void setJulianDate(int year, int month, int day)
juYear = year;
juMonth = month;
juDay = day;
JDN = julianDateToJDN(year, month, day);
JDNToIranian();
JDNToJulian();
JDNToGregorian();
/**
* IranianCalendar: This method determines if the Iranian (Jalali) year is
* leap (366-day long) or is the common year (365 days), and finds the day
* in March (Gregorian Calendar)of the first day of the Iranian year
* ('irYear').Iranian year (irYear) ranges from (-61 to 3177).This method
* will set the following private data members as follows: leap: Number of
* years since the last leap year (0 to 4) Gy: Gregorian year of the
* begining of Iranian year march: The March day of Farvardin the 1st (first
* day of jaYear)
*/
private void IranianCalendar()
// Iranian years starting the 33-year rule
int Breaks[] = -61, 9, 38, 199, 426, 686, 756, 818, 1111, 1181, 1210,
1635, 2060, 2097, 2192, 2262, 2324, 2394, 2456, 3178 ;
int jm, N, leapJ, leapG, jp, j, jump;
gYear = irYear + 621;
leapJ = -14;
jp = Breaks[0];
// Find the limiting years for the Iranian year 'irYear'
j = 1;
do
jm = Breaks[j];
jump = jm - jp;
if (irYear >= jm)
leapJ += (jump / 33 * 8 + (jump % 33) / 4);
jp = jm;
j++;
while ((j < 20) && (irYear >= jm));
N = irYear - jp;
// Find the number of leap years from AD 621 to the begining of the
// current
// Iranian year in the Iranian (Jalali) calendar
leapJ += (N / 33 * 8 + ((N % 33) + 3) / 4);
if (((jump % 33) == 4) && ((jump - N) == 4))
leapJ++;
// And the same in the Gregorian date of Farvardin the first
leapG = gYear / 4 - ((gYear / 100 + 1) * 3 / 4) - 150;
march = 20 + leapJ - leapG;
// Find how many years have passed since the last leap year
if ((jump - N) < 6)
N = N - jump + ((jump + 4) / 33 * 33);
leap = (((N + 1) % 33) - 1) % 4;
if (leap == -1)
leap = 4;
/**
* IranianDateToJDN: Converts a date of the Iranian calendar to the Julian
* Day Number. It first invokes the 'IranianCalender' private method to
* convert the Iranian date to Gregorian date and then returns the Julian
* Day Number based on the Gregorian date. The Iranian date is obtained from
* 'irYear'(1-3100),'irMonth'(1-12) and 'irDay'(1-29/31).
*
* @return long (Julian Day Number)
*/
private int IranianDateToJDN()
IranianCalendar();
return (gregorianDateToJDN(gYear, 3, march) + (irMonth - 1) * 31
- irMonth / 7 * (irMonth - 7) + irDay - 1);
/**
* JDNToIranian: Converts the current value of 'JDN' Julian Day Number to a
* date in the Iranian calendar. The caller should make sure that the
* current value of 'JDN' is set correctly. This method first converts the
* JDN to Gregorian calendar and then to Iranian calendar.
*/
private void JDNToIranian()
JDNToGregorian();
irYear = gYear - 621;
IranianCalendar(); // This invocation will update 'leap' and 'march'
int JDN1F = gregorianDateToJDN(gYear, 3, march);
int k = JDN - JDN1F;
if (k >= 0)
if (k <= 185)
irMonth = 1 + k / 31;
irDay = (k % 31) + 1;
return;
else
k -= 186;
else
irYear--;
k += 179;
if (leap == 1)
k++;
irMonth = 7 + k / 30;
irDay = (k % 30) + 1;
/**
* julianDateToJDN: Calculates the julian day number (JDN) from Julian
* calendar dates. This integer number corresponds to the noon of the date
* (i.e. 12 hours of Universal Time). This method was tested to be good
* (valid) since 1 March, -100100 (of both calendars) up to a few millions
* (10^6) years into the future. The algorithm is based on D.A.Hatcher,
* Q.Jl.R.Astron.Soc. 25(1984), 53-55 slightly modified by K.M. Borkowski,
* Post.Astron. 25(1987), 275-279.
*
* @param year
* int
* @param month
* int
* @param day
* int
* @return int
*/
private int julianDateToJDN(int year, int month, int day)
return (year + (month - 8) / 6 + 100100) * 1461 / 4
+ (153 * ((month + 9) % 12) + 2) / 5 + day - 34840408;
/**
* JDNToJulian: Calculates Julian calendar dates from the julian day number
* (JDN) for the period since JDN=-34839655 (i.e. the year -100100 of both
* calendars) to some millions (10^6) years ahead of the present. The
* algorithm is based on D.A. Hatcher, Q.Jl.R.Astron.Soc. 25(1984), 53-55
* slightly modified by K.M. Borkowski, Post.Astron. 25(1987), 275-279).
*/
private void JDNToJulian()
int j = 4 * JDN + 139361631;
int i = ((j % 1461) / 4) * 5 + 308;
juDay = (i % 153) / 5 + 1;
juMonth = ((i / 153) % 12) + 1;
juYear = j / 1461 - 100100 + (8 - juMonth) / 6;
/**
* gergorianDateToJDN: Calculates the julian day number (JDN) from Gregorian
* calendar dates. This integer number corresponds to the noon of the date
* (i.e. 12 hours of Universal Time). This method was tested to be good
* (valid) since 1 March, -100100 (of both calendars) up to a few millions
* (10^6) years into the future. The algorithm is based on D.A.Hatcher,
* Q.Jl.R.Astron.Soc. 25(1984), 53-55 slightly modified by K.M. Borkowski,
* Post.Astron. 25(1987), 275-279.
*
* @param year
* int
* @param month
* int
* @param day
* int
* @return int
*/
private int gregorianDateToJDN(int year, int month, int day)
int jdn = (year + (month - 8) / 6 + 100100) * 1461 / 4
+ (153 * ((month + 9) % 12) + 2) / 5 + day - 34840408;
jdn = jdn - (year + 100100 + (month - 8) / 6) / 100 * 3 / 4 + 752;
return (jdn);
/**
* JDNToGregorian: Calculates Gregorian calendar dates from the julian day
* number (JDN) for the period since JDN=-34839655 (i.e. the year -100100 of
* both calendars) to some millions (10^6) years ahead of the present. The
* algorithm is based on D.A. Hatcher, Q.Jl.R.Astron.Soc. 25(1984), 53-55
* slightly modified by K.M. Borkowski, Post.Astron. 25(1987), 275-279).
*/
private void JDNToGregorian()
int j = 4 * JDN + 139361631;
j = j + (((((4 * JDN + 183187720) / 146097) * 3) / 4) * 4 - 3908);
int i = ((j % 1461) / 4) * 5 + 308;
gDay = (i % 153) / 5 + 1;
gMonth = ((i / 153) % 12) + 1;
gYear = j / 1461 - 100100 + (8 - gMonth) / 6;
private int irYear; // Year part of a Iranian date
private int irMonth; // Month part of a Iranian date
private int irDay; // Day part of a Iranian date
private int gYear; // Year part of a Gregorian date
private int gMonth; // Month part of a Gregorian date
private int gDay; // Day part of a Gregorian date
private int juYear; // Year part of a Julian date
private int juMonth; // Month part of a Julian date
private int juDay; // Day part of a Julian date
private int leap; // Number of years since the last leap year (0 to 4)
private int JDN; // Julian Day Number
private int march; // The march day of Farvardin the first (First day of
// jaYear)
// End of Class 'Main'
更新:您还需要将此小部件的样式添加到styles.xml
文件中的Theme
:
<item name="numberPickerStyle">@style/NPWidget.Holo.NumberPicker</item>
【讨论】:
非常感谢,非常有用的实现。 (^_-) @ShaahinAshayeri 我很高兴它有帮助 @Nevercom ,非常感谢您的代码。但是我在导入部分遇到了问题,因为我是 android 编程新手,终于可以做到了。现在我想在这个日期之前设置 textview 内容,我该怎么做? @HamidTalebi 可以在调用Activity
的OnActivityResult
方法上获取所选日期
@Nevercom 感谢您分享您的宝贵经验和简单而有益的代码。是否根据选定的月份和年份停用第 29、30 和 31 天?【参考方案2】:
最近,我创建了一个新的库,它有一个波斯语 (Hijri/Shamsi) 日期选择器,它的设计基于 Material Design Pickers。 您可以在the library's github page获取更多信息。
来自 DatePickerDialog 的屏幕截图:
【讨论】:
奇怪的是Android默认不支持这个,因为在iOS上你可以强制日期选择器显示波斯日期。感谢您的贡献。 @MohamadAmin。我无法在 android studio 中运行你的项目。我从github下载它。作为提取过程,它显示“错误 0*80010135 路径太长”。那我怎么用你的cde?! @MinaDahesh 将 zip 存档解压缩到另一个路径较短的文件夹中,例如 C:\ 驱动器的根目录。该错误与 windows 相关,并且 windows 无法处理很长的路径。【参考方案3】:你可以使用这个库:
Persian Range Date Picker
步骤 1. 将 JitPack 存储库添加到您的构建文件中。将其添加到存储库末尾的根 build.gradle 中:
allprojects
repositories
maven url "https://jitpack.io"
步骤 2. 添加依赖项
dependencies
implementation 'com.github.ali-sardari:PersianRangeDatePicker:1.3.0'
然后在您的 Java 代码中,您可以像下面这样使用它。
DatePickerDialog datePickerDialog = new DatePickerDialog(MainActivity.this);
datePickerDialog.setSelectionMode(DateRangeCalendarView.SelectionMode.Range);
datePickerDialog.setEnableTimePicker(true);
datePickerDialog.setCanceledOnTouchOutside(true);
datePickerDialog.setOnRangeDateSelectedListener(new DatePickerDialog.OnRangeDateSelectedListener()
@Override
public void onRangeDateSelected(PersianCalendar startDate, PersianCalendar endDate)
txtStartDate.setText(startDate.getPersianShortDate());
txtEndDate.setText(endDate.getPersianShortDate());
);
datePickerDialog.showDialog();
(日期选择器)
【讨论】:
太棒了。 这么棒的图书馆【参考方案4】:从现在开始,您可以使用基于DroidPersianCalendar 应用程序的PersianCaldroid 库。我采用了这个出色的应用程序并对其进行了许多更改,将其变成了一个库。我还添加了许多苛刻的功能来克服我自己的需求,但在大多数应用程序中也很常见。该库为您提供波斯日历对话框,它是日期选择器,以及波斯日历片段,它是代表波斯日历上用户事件的小部件。 Persian Calendar Fragment 具有基本的 API,例如将事件添加到具有自定义颜色的日期以被圈出、设置自定义字体、日期单击侦听器、月份更改侦听器等。
有关更多信息,请参阅库的 git 存储库https://github.com/dariushm2/PersianCaldroid。
【讨论】:
以上是关于如何使用其他日历系统提供 DatePicker 小部件?的主要内容,如果未能解决你的问题,请参考以下文章
即使从日历中选择日期,如何保持 mat-datepicker 日历打开?
如何在我的 MVC 站点中制作 ExtJs DatePicker?