我想创建一个看起来像这样的字段....任何人都可以告诉我如何做到这一点,我可以使用哪个字段,我可以通过使用轨迹球/滚轮选择值,或者在暴风雨的情况下我可以滑动。 ..
3 回答
It could be simple Label or Bitmap Field extention, with navigation event handling.
You will need to hold String array with values which will be changed in circle on horizontal navigation.
If such custom Field is focused, draw Up and Down arrays.
So, there will be one such Field for DayOfWeek, one for Month, one for DayOfMonth, one for Year.
Place them all in HorizontalFieldManager, which will be placed in PopupScreen, on popup close geather all values and compose Date value (may be passed over FieldChangeListener)
UPDATE
Storm support
On devices with wheel its easy to implement save-and-close functionality on navigation click, but in Storm that would be a problem (dialog will be closed on each field focus action). To solve this, OK and Cancel buttons added.
Also, touchEvent added to handle proper value change using touch click.
You may keep different implementations for RIM OS <= 4.6 and RIM OS >= 4.7, and replace them on build task.
Source
alt text http://img519.imageshack.us/img519/7312/8300.pngalt 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;
}
}
}
}
5.0 API 中引入了一个名为SpinBoxFieldManager的新字段。对于您的具体情况,还有一个DateTimePicker仅用于日期/时间。对于 5.0 之前的操作系统,您需要创建自己的自定义控件。
这是对 Max 帖子的评论(没有足够的积分来发表评论,所以回答就可以了)
如果您正在使用他的帖子,请注意日历正在被硬编码为每个月有 31 天。
mDayOfMonthField = new NumTimeField(mDayOfMonth, 1, 31);
而不是 31 你应该使用:
net.rim.device.api.util.DateTimeUtilities.getNumberOfDaysInMonth(month, year);