BlackBerry - 创建自定义日期字段
-
19-09-2019 - |
解决方案
它可以是简单的标签或位图字段扩展,具有导航事件处理功能。
您将需要保存字符串数组,其值将在水平导航时以圆圈形式更改。
如果这样的自定义字段是焦点,则绘制向上和向下数组。
因此,将有一个这样的字段用于 DayOfWeek,一个用于 Month,一个用于 DayOfMonth,一个用于 Year。
将它们全部放置在 HorizontalFieldManager 中,该管理器将放置在 PopupScreen 中,在弹出窗口关闭时收集所有值并组成日期值(可以通过 FieldChangeListener 传递)
更新
风暴支持
在带有滚轮的设备上,很容易在导航单击时实现保存并关闭功能,但在 Storm 中这将是一个问题(对话框将在每个字段焦点操作时关闭)。为了解决这个问题,添加了“确定”和“取消”按钮。
此外,还添加了 touchEvent 以使用触摸单击来处理适当的值更改。
您可以为 RIM OS <= 4.6 和 RIM OS >= 4.7 保留不同的实现,并在构建任务中替换它们。
来源
替代文本 http://img519.imageshack.us/img519/7312/8300.png替代文本 http://img267.imageshack.us/img267/6245/9000.jpg
替代文本 http://img9.imageshack.us/img9/9098/9530.png
class DatePickerDialog extends PopupScreen implements FieldChangeListener {
DatePickerField mDatePicker;
ButtonField mOKButton;
ButtonField mCancelButton;
public DatePickerDialog(Date date) {
super(new VerticalFieldManager(), PopupScreen.DEFAULT_CLOSE);
add(mDatePicker = new DatePickerField(date));
// comment on RIM OS < 4.7
addButtons();
}
private void addButtons() {
HorizontalFieldManager hfm = new HorizontalFieldManager(FIELD_HCENTER);
add(hfm);
mOKButton = new ButtonField("OK", ButtonField.CONSUME_CLICK);
mOKButton.setChangeListener(this);
hfm.add(mOKButton);
mCancelButton = new ButtonField("Cancel", ButtonField.CONSUME_CLICK);
mCancelButton.setChangeListener(this);
hfm.add(mCancelButton);
}
public void setDate(Date dateValue) {
mDatePicker.setDate(dateValue);
}
public Date getDate() {
return mDatePicker.getDate();
}
public DatePickerDialog() {
this(Calendar.getInstance().getTime());
}
// comment on RIM OS < 4.7
public void fieldChanged(Field field, int context) {
if (mOKButton == field) {
getChangeListener().fieldChanged(this, 0);
close();
} else if (mCancelButton == field) {
close();
}
}
// comment on RIM OS > 4.6
// protected boolean navigationClick(int status, int time) {
// getChangeListener().fieldChanged(this, 0);
// close();
// return super.navigationClick(status, time);
// }
class DatePickerField extends HorizontalFieldManager implements
FieldChangeListener {
private String[] daysOfWeek = new String[] { "Sunday", "Monday",
"Tuesday", "Wednesday", "Thursday", "Friday",
"Saturday" };
private String[] months = new String[] { "Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov",
"Dec" };
private int mDayOfMonth = 10;
private int mMonth = 1;
private int mYear = 2009;
private StrTimeField mDayOfWeekField;
private StrTimeField mMonthField;
private NumTimeField mDayOfMonthField;
private NumTimeField mYearField;
Calendar calendar = Calendar.getInstance();
public DatePickerField(Date date) {
calendar.setTime(date);
mYear = calendar.get(Calendar.YEAR);
// Calendar.JANUARY == 0, so +1 value
mMonth = calendar.get(Calendar.MONTH);
mDayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
// think it's better to disable Day Of Week edit
mDayOfWeekField = new StrTimeField(daysOfWeek, dayOfWeek - 1,
NON_FOCUSABLE);
mDayOfWeekField.setChangeListener(this);
add(mDayOfWeekField);
mMonthField = new StrTimeField(months, mMonth);
mMonthField.setChangeListener(this);
add(mMonthField);
mDayOfMonthField = new NumTimeField(mDayOfMonth, 1, 31);
mDayOfMonthField.setChangeListener(this);
add(mDayOfMonthField);
mYearField = new NumTimeField(mYear, 1900, 2012);
mYearField.setChangeListener(this);
add(mYearField);
}
public void fieldChanged(Field field, int context) {
mDayOfMonth = mDayOfMonthField.getValue();
calendar.set(calendar.DAY_OF_MONTH, mDayOfMonth);
mMonth = mMonthField.getValue();
calendar.set(calendar.MONTH, mMonth);
mYear = mYearField.getValue();
calendar.set(calendar.YEAR, mYear);
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
mDayOfWeekField.setIndex(dayOfWeek);
}
public Date getDate() {
return calendar.getTime();
}
public void setDate(Date date) {
calendar.setTime(date);
mYear = calendar.get(Calendar.YEAR);
mMonth = calendar.get(Calendar.MONTH);
mDayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
mDayOfWeekField.setIndex(dayOfWeek - 1);
mMonthField.setIndex(mMonth);
mDayOfMonthField.setValue(mDayOfMonth);
mYearField.setValue(mYear);
}
abstract class TimeField extends LabelField {
int mWidth = 0;
public TimeField() {
super("", FOCUSABLE);
}
public TimeField(long style) {
super("", style);
}
protected abstract void switchValue(int step);
protected boolean navigationMovement(int dx, int dy,
int status, int time) {
if (Math.abs(dy) > Math.abs(dx)) {
switchValue(-dy);
return true;
} else
return super.navigationMovement(dx, dy, status, time);
}
boolean prepared = false;
protected void onFocus(int direction) {
prepared = false;
super.onFocus(direction);
}
protected void onUnfocus() {
invalidate();
super.onUnfocus();
}
// comment on RIM OS < 4.7
protected boolean touchEvent(TouchEvent msg) {
if (isFocus() && msg.getEvent() == TouchEvent.CLICK) {
if (!prepared) {
prepared = true;
} else {
int y = msg.getY(1);
int cy = getTop() + (getHeight() >> 1);
switchValue((y > cy) ? -1 : 1);
}
}
return false;
}
public int getPreferredWidth() {
return mWidth;
}
public int getPreferredHeight() {
return super.getPreferredHeight() + 24;
}
protected void layout(int width, int height) {
super.layout(width, height);
setExtent(getPreferredWidth(), getPreferredHeight());
}
protected void paint(Graphics graphics) {
String text = getText();
Font font = getFont();
int x = (getPreferredWidth()
- font.getAdvance(text)) >> 1;
int y = (getPreferredHeight() - font.getHeight()) >> 1;
graphics.drawText(text, x, y);
if (isFocus()) {
graphics.setColor(Color.WHITE);
int xc = (getPreferredWidth() >> 1);
int y1 = 10, y2 = 0, x2 = xc - 9, x1 = xc + 9;
int[] xPts = new int[] { x1, x2, xc };
int[] yPts = new int[] { y1, y1, y2 };
graphics.drawFilledPath(xPts, yPts,
null, null);
y2 = getPreferredHeight();
y1 = y2 - 10;
yPts = new int[] { y1, y1, y2 };
graphics.drawFilledPath(xPts, yPts,
null, null);
}
}
public abstract int getValue();
}
class StrTimeField extends TimeField {
String[] mValues;
int mIndex;
public StrTimeField(String[] values) {
this(values, 0);
}
public StrTimeField(String[] values, int value) {
this(values, value, FOCUSABLE);
}
public StrTimeField(String[] values, int value, long style) {
super(style);
mValues = values;
setIndex(value);
Font font = getFont();
for (int i = 0; i < mValues.length; i++) {
int width = font.getAdvance(mValues[i]);
mWidth = Math.max(mWidth, width);
}
mWidth += 10;
}
protected void switchValue(int step) {
int index = mIndex + step;
if (index < 0 || index >= mValues.length)
index += ((index > 0) ? -1 : 1)
* mValues.length;
setIndex(index);
}
private void setIndex(int index) {
if (index >= 0 && index < mValues.length) {
mIndex = index;
setText(mValues[mIndex]);
}
}
public int getValue() {
return mIndex;
}
}
class NumTimeField extends TimeField {
int mValue;
int mMinValue;
int mMaxValue;
public NumTimeField(int val, int minVal, int maxVal) {
this(val, minVal, maxVal, FOCUSABLE);
}
public NumTimeField(int val, int minVal, int maxVal,
long style) {
super(style);
mValue = val;
mMinValue = minVal;
mMaxValue = maxVal;
setText(String.valueOf(mValue));
int maxDig = String.valueOf(mMaxValue).length();
String test = "";
for (int i = 0; i < maxDig; i++)
test += "0";
mWidth = getFont().getAdvance(test);
mWidth += 10;
}
protected void switchValue(int step) {
int value = mValue + step;
if (value > mMaxValue)
value = value - (mMaxValue - mMinValue + 1);
if (value < mMinValue)
value = value + (mMaxValue - mMinValue + 1);
setValue(value);
}
private void setValue(int value) {
mValue = value;
setText(String.valueOf(mValue));
}
public int getValue() {
return mValue;
}
}
}
}
其他提示
5.0 API 中引入了一个新字段,称为 SpinBox字段管理器. 。对于您的具体情况,还有一个 日期时间选择器 仅适用于日期/时间。对于 5.0 之前的操作系统,您需要创建自己的自定义控件。
这是最大的信息发表评论(没有足够的学分发表评论这样的答案都行)
如果您使用的是被告知他的职位,日历被硬编码为31天每月。
mDayOfMonthField = new NumTimeField(mDayOfMonth, 1, 31);
代替31应该使用:
net.rim.device.api.util.DateTimeUtilities.getNumberOfDaysInMonth(month, year);