答案 0 :(得分:6)
可以是简单的标签或位图字段扩展,具有导航事件处理功能。
您需要保存String数组,其值将在水平导航中以圆圈形式更改 如果聚焦了这样的自定义场,则绘制向上和向下阵列。
因此,DayOfWeek将会有一个这样的Field,一个用于Day,一个用于DayOfMonth,一个用于Year。
将它们全部放在HorizontalFieldManager中,它将放在PopupScreen中,弹出关闭geather所有值并组成Date值(可以通过FieldChangeListener传递)
<强>更新强>
在带有滚轮的设备上,可以轻松实现导航点击中的保存并关闭功能,但在Storm中这将是一个问题(对话框将在每个字段焦点操作上关闭)。要解决此问题,请添加“确定”和“取消”按钮。
此外,添加了touchEvent以使用触摸点击来处理正确的值更改。
您可以为RIM OS&lt; = 4.6和RIM OS&gt; = 4.7保留不同的实现,并在构建任务中替换它们。
alt text http://img519.imageshack.us/img519/7312/8300.png alt text http://img267.imageshack.us/img267/6245/9000.jpg
alt text 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;
}
}
}
}
答案 1 :(得分:1)
5.0 API中引入了一个名为SpinBoxFieldManager的新字段。对于您的具体情况,日期/时间也只有DateTimePicker。对于5.0之前的操作系统,您需要创建自己的自定义控件。
答案 2 :(得分:0)
这是对Max的帖子的评论(没有足够的学分来发表评论,所以答案会这样做)
如果您使用他的帖子,请注意日历是31天的每个月的硬编码。
mDayOfMonthField = new NumTimeField(mDayOfMonth, 1, 31);
而不是31你应该使用:
net.rim.device.api.util.DateTimeUtilities.getNumberOfDaysInMonth(month, year);