3. public class SignupForm extends Form {
Container content = new Container(BoxLayout.y(), "PaddedContainer");
Container south = new Container(BoxLayout.y());
protected SignupForm(String title, String backLabel, Form previous) {
super(title, new BorderLayout());
setUIID("SignupForm");
content.setScrollableY(true);
add(CENTER, content);
getToolbar().setBackCommand(backLabel,
Toolbar.BackCommandPolicy.WHEN_USES_TITLE_OTHERWISE_ARROW,
e -> previous.showBack());
getToolbar().getTitleComponent().setUIID("Title", "TitleLandscape");
Button problem = new Button("Report a Problem", "BlueLink");
south.add(problem);
problem.addActionListener(e ->
sendMessage("Problem with Facebook Clone",
new Message("Details..."),
"mark@facebook.com"));
add(SOUTH, south);
}
Button createNextButton(ActionListener al) {
SignupForm
The signup form is a form that encapsulates common functionality in all of these forms.
We use the content Container to place the main UI and the south Container for the links on the bottom
4. public class SignupForm extends Form {
Container content = new Container(BoxLayout.y(), "PaddedContainer");
Container south = new Container(BoxLayout.y());
protected SignupForm(String title, String backLabel, Form previous) {
super(title, new BorderLayout());
setUIID("SignupForm");
content.setScrollableY(true);
add(CENTER, content);
getToolbar().setBackCommand(backLabel,
Toolbar.BackCommandPolicy.WHEN_USES_TITLE_OTHERWISE_ARROW,
e -> previous.showBack());
getToolbar().getTitleComponent().setUIID("Title", "TitleLandscape");
Button problem = new Button("Report a Problem", "BlueLink");
south.add(problem);
problem.addActionListener(e ->
sendMessage("Problem with Facebook Clone",
new Message("Details..."),
"mark@facebook.com"));
add(SOUTH, south);
}
Button createNextButton(ActionListener al) {
SignupForm
The constructor is protected as it's used only within this class
5. public class SignupForm extends Form {
Container content = new Container(BoxLayout.y(), "PaddedContainer");
Container south = new Container(BoxLayout.y());
protected SignupForm(String title, String backLabel, Form previous) {
super(title, new BorderLayout());
setUIID("SignupForm");
content.setScrollableY(true);
add(CENTER, content);
getToolbar().setBackCommand(backLabel,
Toolbar.BackCommandPolicy.WHEN_USES_TITLE_OTHERWISE_ARROW,
e -> previous.showBack());
getToolbar().getTitleComponent().setUIID("Title", "TitleLandscape");
Button problem = new Button("Report a Problem", "BlueLink");
south.add(problem);
problem.addActionListener(e ->
sendMessage("Problem with Facebook Clone",
new Message("Details..."),
"mark@facebook.com"));
add(SOUTH, south);
}
Button createNextButton(ActionListener al) {
SignupForm
Only the content pane should be scrollable, everything else should be fixed in place
6. public class SignupForm extends Form {
Container content = new Container(BoxLayout.y(), "PaddedContainer");
Container south = new Container(BoxLayout.y());
protected SignupForm(String title, String backLabel, Form previous) {
super(title, new BorderLayout());
setUIID("SignupForm");
content.setScrollableY(true);
add(CENTER, content);
getToolbar().setBackCommand(backLabel,
Toolbar.BackCommandPolicy.WHEN_USES_TITLE_OTHERWISE_ARROW,
e -> previous.showBack());
getToolbar().getTitleComponent().setUIID("Title", "TitleLandscape");
Button problem = new Button("Report a Problem", "BlueLink");
south.add(problem);
problem.addActionListener(e ->
sendMessage("Problem with Facebook Clone",
new Message("Details..."),
"mark@facebook.com"));
add(SOUTH, south);
}
Button createNextButton(ActionListener al) {
SignupForm
This supports the back behavior where an arrow is shown on Android & backLabel is shown in iOS
7. public class SignupForm extends Form {
Container content = new Container(BoxLayout.y(), "PaddedContainer");
Container south = new Container(BoxLayout.y());
protected SignupForm(String title, String backLabel, Form previous) {
super(title, new BorderLayout());
setUIID("SignupForm");
content.setScrollableY(true);
add(CENTER, content);
getToolbar().setBackCommand(backLabel,
Toolbar.BackCommandPolicy.WHEN_USES_TITLE_OTHERWISE_ARROW,
e -> previous.showBack());
getToolbar().getTitleComponent().setUIID("Title", "TitleLandscape");
Button problem = new Button("Report a Problem", "BlueLink");
south.add(problem);
problem.addActionListener(e ->
sendMessage("Problem with Facebook Clone",
new Message("Details..."),
"mark@facebook.com"));
add(SOUTH, south);
}
Button createNextButton(ActionListener al) {
SignupForm
We give the title a different UIID when it's in landscape mode so it can shrink when we rotate the device
8. public class SignupForm extends Form {
Container content = new Container(BoxLayout.y(), "PaddedContainer");
Container south = new Container(BoxLayout.y());
protected SignupForm(String title, String backLabel, Form previous) {
super(title, new BorderLayout());
setUIID("SignupForm");
content.setScrollableY(true);
add(CENTER, content);
getToolbar().setBackCommand(backLabel,
Toolbar.BackCommandPolicy.WHEN_USES_TITLE_OTHERWISE_ARROW,
e -> previous.showBack());
getToolbar().getTitleComponent().setUIID("Title", "TitleLandscape");
Button problem = new Button("Report a Problem", "BlueLink");
south.add(problem);
problem.addActionListener(e ->
sendMessage("Problem with Facebook Clone",
new Message("Details..."),
"mark@facebook.com"));
add(SOUTH, south);
}
Button createNextButton(ActionListener al) {
SignupForm
The problems link is added to the bottom of the UI inside a container so we can add additional elements there
9. add(CENTER, content);
getToolbar().setBackCommand(backLabel,
Toolbar.BackCommandPolicy.WHEN_USES_TITLE_OTHERWISE_ARROW,
e -> previous.showBack());
getToolbar().getTitleComponent().setUIID("Title", "TitleLandscape");
Button problem = new Button("Report a Problem", "BlueLink");
south.add(problem);
problem.addActionListener(e ->
sendMessage("Problem with Facebook Clone",
new Message("Details..."),
"mark@facebook.com"));
add(SOUTH, south);
}
Button createNextButton(ActionListener al) {
Button next = new Button("Next", "NextButton");
next.addActionListener(al);
return next;
}
public static SignupForm createTerms() {
SignupForm s = new SignupForm("Create Account", "Sign In",
getCurrentForm());
Label title = new Label("Terms & Conditions", "SignupSubHeader");
RichTextView rt = new RichTextView("By signing up you agree to our "
SignupForm
This is the next button that appears in each stage. The static methods below create each stage of the wizard. Now we have all the infrastructure in place to build the
individual stages of signup…
12. next.addActionListener(al);
return next;
}
public static SignupForm createTerms() {
SignupForm s = new SignupForm("Create Account", "Sign In",
getCurrentForm());
Label title = new Label("Terms & Conditions", "SignupSubHeader");
RichTextView rt = new RichTextView("By signing up you agree to our "
+ "<a href="terms">Facebook Terms</a> and that you have "
+ "read our <a href="data-policy">Data Policy</a>, including "
+ "our <a href="cookie-use">Cookie Use</a>.");
rt.setAlignment(CENTER);
rt.setUIID("PaddedContainer");
Button next = s.createNextButton(e -> createName().show());
next.setText("I Agree");
rt.addLinkListener(e -> {
String link = (String)e.getSource();
execute("https://www.codenameone.com/");
});
s.content.addAll(title, rt, next);
return s;
}
createTerms
The code for this form is simple. The "Sign In" label appears in the iOS back button
13. next.addActionListener(al);
return next;
}
public static SignupForm createTerms() {
SignupForm s = new SignupForm("Create Account", "Sign In",
getCurrentForm());
Label title = new Label("Terms & Conditions", "SignupSubHeader");
RichTextView rt = new RichTextView("By signing up you agree to our "
+ "<a href="terms">Facebook Terms</a> and that you have "
+ "read our <a href="data-policy">Data Policy</a>, including "
+ "our <a href="cookie-use">Cookie Use</a>.");
rt.setAlignment(CENTER);
rt.setUIID("PaddedContainer");
Button next = s.createNextButton(e -> createName().show());
next.setText("I Agree");
rt.addLinkListener(e -> {
String link = (String)e.getSource();
execute("https://www.codenameone.com/");
});
s.content.addAll(title, rt, next);
return s;
}
createTerms
We center align the HTML, since it renders into FlowLayout this is pretty easy
14. next.addActionListener(al);
return next;
}
public static SignupForm createTerms() {
SignupForm s = new SignupForm("Create Account", "Sign In",
getCurrentForm());
Label title = new Label("Terms & Conditions", "SignupSubHeader");
RichTextView rt = new RichTextView("By signing up you agree to our "
+ "<a href="terms">Facebook Terms</a> and that you have "
+ "read our <a href="data-policy">Data Policy</a>, including "
+ "our <a href="cookie-use">Cookie Use</a>.");
rt.setAlignment(CENTER);
rt.setUIID("PaddedContainer");
Button next = s.createNextButton(e -> createName().show());
next.setText("I Agree");
rt.addLinkListener(e -> {
String link = (String)e.getSource();
execute("https://www.codenameone.com/");
});
s.content.addAll(title, rt, next);
return s;
}
createTerms
We need a different label for the next button, we show the createName form on the next operation
15. next.addActionListener(al);
return next;
}
public static SignupForm createTerms() {
SignupForm s = new SignupForm("Create Account", "Sign In",
getCurrentForm());
Label title = new Label("Terms & Conditions", "SignupSubHeader");
RichTextView rt = new RichTextView("By signing up you agree to our "
+ "<a href="terms">Facebook Terms</a> and that you have "
+ "read our <a href="data-policy">Data Policy</a>, including "
+ "our <a href="cookie-use">Cookie Use</a>.");
rt.setAlignment(CENTER);
rt.setUIID("PaddedContainer");
Button next = s.createNextButton(e -> createName().show());
next.setText("I Agree");
rt.addLinkListener(e -> {
String link = (String)e.getSource();
execute("https://www.codenameone.com/");
});
s.content.addAll(title, rt, next);
return s;
}
createTerms
I left this as a mockup, clicking the links isn't used but you can implement these links in any way you want...
16. next.addActionListener(al);
return next;
}
public static SignupForm createTerms() {
SignupForm s = new SignupForm("Create Account", "Sign In",
getCurrentForm());
Label title = new Label("Terms & Conditions", "SignupSubHeader");
RichTextView rt = new RichTextView("By signing up you agree to our "
+ "<a href="terms">Facebook Terms</a> and that you have "
+ "read our <a href="data-policy">Data Policy</a>, including "
+ "our <a href="cookie-use">Cookie Use</a>.");
rt.setAlignment(CENTER);
rt.setUIID("PaddedContainer");
Button next = s.createNextButton(e -> createName().show());
next.setText("I Agree");
rt.addLinkListener(e -> {
String link = (String)e.getSource();
execute("https://www.codenameone.com/");
});
s.content.addAll(title, rt, next);
return s;
}
createTerms
The content is in the center of the Form and uses BoxLayout on the Y axis. We add elements directly to it. Simple.
18. #Constants {
includeNativeBool: true;
scrollVisibleBool: false;
labelGap: 2;
capsButtonUiids: "BlueText,GreenButton,BlueButton,NextButton";
landscapeTitleUiidBool: true;
}
/** unchanged **/
Toolbar {
padding: 1mm;
border: none;
background-color: #4367b3;
}
Title {
font-family: "native:MainLight";
font-size: 4mm;
padding: 2mm 1mm 2mm 1mm;
margin: 0px;
color: white;
}
theme.css
Next lets look at the CSS needed for this. First we need to change two things in the #Constants entry.
We need to add the NextButton UIID to the list of caps buttons. landscapeTitleUiidBool indicates that we should use Landscape suffixed UIID's for the title elements.
Notice that Facebook didn't uppercase the next button on Android. I chose to do that as it fits better to the platform. I didn't do that for the problems link (or other links)
as that's not the convention on Android.
19. #Constants {
includeNativeBool: true;
scrollVisibleBool: false;
labelGap: 2;
capsButtonUiids: "BlueText,GreenButton,BlueButton,NextButton";
landscapeTitleUiidBool: true;
}
/** unchanged **/
Toolbar {
padding: 1mm;
border: none;
background-color: #4367b3;
}
Title {
font-family: "native:MainLight";
font-size: 4mm;
padding: 2mm 1mm 2mm 1mm;
margin: 0px;
color: white;
}
theme.css
Lets go over the new additions to the css now. The Toolbar just has a bit of padding and the right background color
20. /** unchanged **/
Toolbar {
padding: 1mm;
border: none;
background-color: #4367b3;
}
Title {
font-family: "native:MainLight";
font-size: 4mm;
padding: 2mm 1mm 2mm 1mm;
margin: 0px;
color: white;
}
TitleCommand {
font-family: "native:MainLight";
font-size: 2.5mm;
padding: 1mm;
margin: 0px;
color: white;
}
BackCommand {
font-family: "native:MainLight";
font-size: 2.5mm;
padding: 3mm 0.5mm 3mm 0.5mm;
theme.css
The Title is 4mm with a large font, this doesn't look like the more understated Facebook font but I think it looks better
21. /** unchanged **/
Toolbar {
padding: 1mm;
border: none;
background-color: #4367b3;
}
Title {
font-family: "native:MainLight";
font-size: 4mm;
padding: 2mm 1mm 2mm 1mm;
margin: 0px;
color: white;
}
TitleCommand {
font-family: "native:MainLight";
font-size: 2.5mm;
padding: 1mm;
margin: 0px;
color: white;
}
BackCommand {
font-family: "native:MainLight";
font-size: 2.5mm;
padding: 3mm 0.5mm 3mm 0.5mm;
theme.css
The TitleCommand is smaller than the Title so it won't take up too much space
22. }
TitleCommand {
font-family: "native:MainLight";
font-size: 2.5mm;
padding: 1mm;
margin: 0px;
color: white;
}
BackCommand {
font-family: "native:MainLight";
font-size: 2.5mm;
padding: 3mm 0.5mm 3mm 0.5mm;
margin: 0px;
color: white;
}
ToolbarLandscpae {
padding: 0.5mm;
border: none;
background-color: #4367b3;
}
TitleLandscape {
font-family: "native:MainLight";
font-size: 3mm;
padding: 0px;
margin: 0px;
theme.css
BackCommand is only used in iOS so we keep it even smaller so it will fit with the title which can be a problem with long text
24. color: white;
}
ToolbarLandscpae {
padding: 0.5mm;
border: none;
background-color: #4367b3;
}
TitleLandscape {
font-family: "native:MainLight";
font-size: 3mm;
padding: 0px;
margin: 0px;
color: white;
}
TitleCommandLandscape {
font-family: "native:MainLight";
font-size: 2.5mm;
padding: 0px 1mm 0px 1mm;
margin: 0px;
color: white;
}
BackCommandLandscape {
font-family: "native:MainLight";
font-size: 2.5mm;
padding: 0px 1mm 0px 1mm;
margin: 0px;
theme.css
It also reduces the size of the title font
25. background-color: #4367b3;
}
TitleLandscape {
font-family: "native:MainLight";
font-size: 3mm;
padding: 0px;
margin: 0px;
color: white;
}
TitleCommandLandscape {
font-family: "native:MainLight";
font-size: 2.5mm;
padding: 0px 1mm 0px 1mm;
margin: 0px;
color: white;
}
BackCommandLandscape {
font-family: "native:MainLight";
font-size: 2.5mm;
padding: 0px 1mm 0px 1mm;
margin: 0px;
color: white;
}
SignupSubHeader {
font-family: "native:MainBold";
font-size: 3mm;
theme.css
If we don't reduce the padding in the command & title area the title area as a whole won't shrink.
When I initially implemented this I didn't reduce the sizes of the title command & back command styles. The font shrank but the Toolbar maintained its height. I used the
Component Inspector tool in the simulator to look at the differences between preferred height and actual height for all the elements in order to figure out which was at
fault.
26. BackCommandLandscape {
font-family: "native:MainLight";
font-size: 2.5mm;
padding: 0px 1mm 0px 1mm;
margin: 0px;
color: white;
}
SignupSubHeader {
font-family: "native:MainBold";
font-size: 3mm;
text-align: center;
margin: 0px;
padding: 3mm;
}
SignupForm {
background-color: #F6F7F8;
cn1-derive: SplashForm;
}
NextButton {
cn1-derive: BlueButtonOnBlueBackground;
margin-top: 3.5mm;
}
BlueLink {
cn1-derive: BaseButton;
color: blue;
font-size: 2.2mm;
theme.css
We use a bold center aligned font for the subheading in the forms
27. BackCommandLandscape {
font-family: "native:MainLight";
font-size: 2.5mm;
padding: 0px 1mm 0px 1mm;
margin: 0px;
color: white;
}
SignupSubHeader {
font-family: "native:MainBold";
font-size: 3mm;
text-align: center;
margin: 0px;
padding: 3mm;
}
SignupForm {
background-color: #F6F7F8;
cn1-derive: SplashForm;
}
NextButton {
cn1-derive: BlueButtonOnBlueBackground;
margin-top: 3.5mm;
}
BlueLink {
cn1-derive: BaseButton;
color: blue;
font-size: 2.2mm;
theme.css
The signup process forms have an "off white" color which I took from the Android version of the wizard
28. BackCommandLandscape {
font-family: "native:MainLight";
font-size: 2.5mm;
padding: 0px 1mm 0px 1mm;
margin: 0px;
color: white;
}
SignupSubHeader {
font-family: "native:MainBold";
font-size: 3mm;
text-align: center;
margin: 0px;
padding: 3mm;
}
SignupForm {
background-color: #F6F7F8;
cn1-derive: SplashForm;
}
NextButton {
cn1-derive: BlueButtonOnBlueBackground;
margin-top: 3.5mm;
}
BlueLink {
cn1-derive: BaseButton;
color: blue;
font-size: 2.2mm;
theme.css
Initially I used BlueButton for this but eventually decided to create a UIID for it as I wanted more spacing from the top. I might change NextButton in the future to work
better in landscape by reducing margin in landscape mode.
29. color: white;
}
SignupSubHeader {
font-family: "native:MainBold";
font-size: 3mm;
text-align: center;
margin: 0px;
padding: 3mm;
}
SignupForm {
background-color: #F6F7F8;
cn1-derive: SplashForm;
}
NextButton {
cn1-derive: BlueButtonOnBlueBackground;
margin-top: 3.5mm;
}
BlueLink {
cn1-derive: BaseButton;
color: blue;
font-size: 2.2mm;
padding: 1.5mm;
font-family: "native:MainLight";
}
theme.css
The link at the bottom of the form is relatively small and blue. With this you can run and see the first signup Form. The rest becomes trivial by comparison...