---更详细的更新问题---
我正在更新此问题以添加更多详细信息。很抱歉在此问题中报告了多个错误,但我在使用以下代码时遇到了多个问题。
首先,这是我的(新)代码来测试TextModeLayout,这很容易完全复制和测试(我改变了以前版本的这个问题的代码):
package ...;
import com.codename1.io.Log;
import static com.codename1.ui.CN.addNetworkErrorListener;
import static com.codename1.ui.CN.getCurrentForm;
import static com.codename1.ui.CN.updateNetworkThreadCount;
import com.codename1.ui.Container;
import com.codename1.ui.Dialog;
import com.codename1.ui.Form;
import com.codename1.ui.PickerComponent;
import com.codename1.ui.TextComponent;
import com.codename1.ui.Toolbar;
import com.codename1.ui.layouts.BoxLayout;
import com.codename1.ui.layouts.TextModeLayout;
import com.codename1.ui.plaf.UIManager;
import com.codename1.ui.util.Resources;
import com.codename1.ui.validation.Constraint;
import com.codename1.ui.validation.LengthConstraint;
import com.codename1.ui.validation.Validator;
import java.util.Date;
import java.util.Calendar;
public class MyApplication {
private Form current;
private Resources theme;
public void init(Object context) {
// use two network threads instead of one
updateNetworkThreadCount(2);
theme = UIManager.initFirstTheme("/theme");
// Enable Toolbar on all Forms by default
Toolbar.setGlobalToolbar(true);
// Pro only feature
Log.bindCrashProtection(true);
addNetworkErrorListener(err -> {
// prevent the event from propagating
err.consume();
if (err.getError() != null) {
Log.e(err.getError());
}
Log.sendLogAsync();
Dialog.show("Connection Error", "There was a networking error in the connection to " + err.getConnectionRequest().getUrl(), "OK", null);
});
}
public void start() {
if (current != null) {
current.show();
return;
}
MyForm test = new MyForm();
test.show();
}
public void stop() {
current = getCurrentForm();
if (current instanceof Dialog) {
((Dialog) current).dispose();
current = getCurrentForm();
}
}
public void destroy() {
}
}
class MyForm extends Form {
public MyForm() {
super("Anagrafica", BoxLayout.y());
}
/**
* Creates and shows the Registry Form
*/
@Override
public void show() {
// More info: https://www.codenameone.com/blog/pixel-perfect-text-input-part-2.html
TextModeLayout textModeLayout = new TextModeLayout(4, 1);
Container inputPersonData = new Container(textModeLayout);
TextComponent name = new TextComponent().labelAndHint("Name").errorMessage("Insert your name");
TextComponent surname = new TextComponent().labelAndHint("Surname").errorMessage("Insert your surname");
PickerComponent gender = PickerComponent.createStrings("Male", "Female", "Other", "Not specified").label("Gender").errorMessage("Please choose an option");
PickerComponent date = PickerComponent.createDate(null).label("Birthday").errorMessage("Are you at least 13 years old?");
Validator validator = new Validator();
validator.setShowErrorMessageForFocusedComponent(false);
validator.addConstraint(name, new LengthConstraint(2));
validator.addConstraint(surname, new LengthConstraint(2));
validator.addConstraint(gender, new Constraint() {
@Override
public boolean isValid(Object value) {
boolean res = false;
if (value != null && value instanceof String) {
res = true;
}
return res;
}
@Override
public String getDefaultFailMessage() {
return "Please choose an option";
}
});
validator.addConstraint(date, new Constraint() {
@Override
public boolean isValid(Object value) {
boolean res = false;
if (value != null && value instanceof Date) {
Calendar birthday = Calendar.getInstance();
birthday.setTime((Date) value);
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.YEAR, -13);
if (birthday.before(calendar)) {
res = true;
}
}
return res;
}
@Override
public String getDefaultFailMessage() {
return "You must be at least 13 years old";
}
});
inputPersonData.add(name);
inputPersonData.add(surname);
inputPersonData.add(gender);
inputPersonData.add(date);
add(inputPersonData);
//setEditOnShow(name.getField());
super.show();
Log.p("Registry Form shown correctly");
}
}
我生成了apk和ipa,我在手中的实际设备上测试了它们(不在设备场中)。为了更好地理解这些行为,我录制了两个视频。
Android 7:正如您在视频Android.mp4中看到的,无论我提供了有效的输入,都会始终显示名称(但不是姓氏)的错误消息。此外,当我使用java.lang.NullPointerException点击生日选择器时,应用程序崩溃。完整日志位于:android_date_picker_crash.txt
iPhoneX(iOS 11.2.2):正如您在视频iPhone.mp4中看到的那样,只有当输入无效时(正如我所料),才能正确显示字段右侧的红色十字,但errorMessages文本始终显示有效输入。选择性别也存在问题,因为如果我点击性别然后按OK(不滚动选项),则不会选择第一个选项(即“男性”)(在视频中我尝试了两次)。
因此,相同的代码会在Android上产生崩溃,但在iOS中则不会。此外,两个操作系统上的errorTexts显示不正确,但行为不同。
在iOS上还有一个奇怪的错误:如果你阻止屏幕然后解锁它(尝试使用iPhone X的右侧按钮,然后使用FaceID解锁),输入字段将重复,如此屏幕截图所示:{ {3}}。这个bug很容易复制。
感谢您的支持。
---老问题---
请注意以下屏幕截图(引用相同的代码):在Android上errorMessage
的{{1}}显示有效输入(TextComponent name
{ {1}}未显示有效输入,如预期的那样);在iPhoneX上,errorMessage
和TextComponent surname
的errorMessages显示有效输入。为什么?怎么了?
当然,预期的行为是没有TextComponent name
显示有效输入。
在屏幕截图下方,我复制了表格的完整代码。
真正的Android 7(在我手中)的屏幕截图: error.jpg
完整代码:
TextComponent surname
答案 0 :(得分:1)
你不应该使用验证器:
TextComponent name = new TextComponent().labelAndHint("Name").errorMessage("Insert your name");
由于您实际上将错误消息硬编码到组件中,因此它将设置为null。您应该将消息放在验证器中:
validator.addConstraint(name, new LengthConstraint(2, "Insert your name"));
答案 1 :(得分:1)
PickerComponent.createDate(null).label("Birthday");
,因为" null"参数导致报告的Android崩溃(请参阅问题中报告的日志)。如果我记得正确,你在Facebook克隆的课程中使用了createDate(null)
:只有当你不使用Validator 时它才会正常(这个问题只影响Android,而不是代码适用于iOS)。仍有一些小问题不会影响功能,例如,在用户使已经验证的输入无效后,Validator不会禁用提交按钮。
最后,这是一个(足够的)工作代码:
import com.codename1.io.Log;
import com.codename1.ui.Button;
import static com.codename1.ui.CN.addNetworkErrorListener;
import static com.codename1.ui.CN.getCurrentForm;
import static com.codename1.ui.CN.updateNetworkThreadCount;
import com.codename1.ui.Container;
import com.codename1.ui.Dialog;
import com.codename1.ui.Form;
import com.codename1.ui.PickerComponent;
import com.codename1.ui.TextComponent;
import com.codename1.ui.Toolbar;
import com.codename1.ui.layouts.BoxLayout;
import com.codename1.ui.layouts.TextModeLayout;
import com.codename1.ui.plaf.UIManager;
import com.codename1.ui.util.Resources;
import com.codename1.ui.validation.Constraint;
import com.codename1.ui.validation.LengthConstraint;
import com.codename1.ui.validation.Validator;
import java.util.Date;
import java.util.Calendar;
public class MainClass {
private Form current;
private Resources theme;
public void init(Object context) {
// use two network threads instead of one
updateNetworkThreadCount(2);
theme = UIManager.initFirstTheme("/theme");
// Enable Toolbar on all Forms by default
Toolbar.setGlobalToolbar(true);
// Pro only feature
Log.bindCrashProtection(true);
addNetworkErrorListener(err -> {
// prevent the event from propagating
err.consume();
if (err.getError() != null) {
Log.e(err.getError());
}
Log.sendLogAsync();
Dialog.show("Connection Error", "There was a networking error in the connection to " + err.getConnectionRequest().getUrl(), "OK", null);
});
}
public void start() {
if (current != null) {
current.show();
return;
}
// More info:
// https://www.codenameone.com/blog/pixel-perfect-text-input-part-2.html
// https://stackoverflow.com/questions/50250572/codename-one-errormessages-by-the-validator-shown-with-valid-inputs-update
Form hi = new Form("Anagrafica", BoxLayout.y());
TextModeLayout textModeLayout = new TextModeLayout(4, 1);
Container inputPersonData = new Container(textModeLayout);
TextComponent name = new TextComponent().labelAndHint("Name");
TextComponent surname = new TextComponent().labelAndHint("Surname");
PickerComponent gender = PickerComponent.createStrings("Male", "Female", "Other", "Not specified").label("Gender");
gender.getPicker().setSelectedString("Not specified");
PickerComponent date = PickerComponent.createDate(new Date()).label("Birthday");
Validator validator = new Validator();
validator.setShowErrorMessageForFocusedComponent(true);
validator.addConstraint(name, new LengthConstraint(2, "Insert your name"));
validator.addConstraint(surname, new LengthConstraint(2, "Insert your surname"));
validator.addConstraint(date, new Constraint() {
@Override
public boolean isValid(Object value) {
boolean res = false;
if (value != null && value instanceof Date) {
Calendar birthday = Calendar.getInstance();
birthday.setTime((Date) value);
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.YEAR, -13);
if (birthday.before(calendar)) {
res = true;
}
}
return res;
}
@Override
public String getDefaultFailMessage() {
return "Are you at least 13 years old?";
}
});
inputPersonData.add(name);
inputPersonData.add(surname);
inputPersonData.add(gender);
inputPersonData.add(date);
hi.add(inputPersonData);
Button button = new Button("Send");
hi.add(button);
validator.addSubmitButtons(button);
hi.setEditOnShow(name.getField());
hi.show();
}
public void stop() {
current = getCurrentForm();
if (current instanceof Dialog) {
((Dialog) current).dispose();
current = getCurrentForm();
}
}
public void destroy() {
}
}