SlideShare a Scribd company logo
Creating a Facebook Clone - Part VII
Next we have the name entry stage in the signup wizard
© Codename One 2017 all rights reserved
The name entry stage in the signup wizard is pretty trivial, there is just one interesting aspect here: The text input.
© Codename One 2017 all rights reserved
The name entry stage in the signup wizard is pretty trivial, there is just one interesting aspect here: The text input.
© Codename One 2017 all rights reserved
Notice that the text input looks different in Android when we enter text and on iOS it looks completely different. This is a part of the "magic" behind the TextComponent
class.

On Android we animate hint labels in the style of material design and in iOS we show a grouped pair.
s.content.addAll(title, rt, next);
return s;
}
public static SignupForm createName() {
SignupForm s = new SignupForm("Name", "Terms",
getCurrentForm());
Label title = new Label("What's Your Name?", "SignupSubHeader");
TextComponent first = new TextComponent().
label("First Name").columns(12);
TextComponent last = new TextComponent().
label("Last Name").columns(12);
TextModeLayout layout = new TextModeLayout(1, 2);
Container textContainer = new Container(layout, "PaddedContainer");
textContainer.add(layout.createConstraint().
widthPercentage(50), first);
textContainer.add(layout.createConstraint().
widthPercentage(50), last);
last.getField().setDoneListener(e -> createBirthday().show());
s.content.addAll(title, textContainer,
s.createNextButton(e -> createBirthday().show()));
return s;
}
SignupForm
Lets go right into the createName method. 

TextComponent is a text input component that combines the label and TextField into one component and automatically adapts it to the platform
s.content.addAll(title, rt, next);
return s;
}
public static SignupForm createName() {
SignupForm s = new SignupForm("Name", "Terms",
getCurrentForm());
Label title = new Label("What's Your Name?", "SignupSubHeader");
TextComponent first = new TextComponent().
label("First Name").columns(12);
TextComponent last = new TextComponent().
label("Last Name").columns(12);
TextModeLayout layout = new TextModeLayout(1, 2);
Container textContainer = new Container(layout, "PaddedContainer");
textContainer.add(layout.createConstraint().
widthPercentage(50), first);
textContainer.add(layout.createConstraint().
widthPercentage(50), last);
last.getField().setDoneListener(e -> createBirthday().show());
s.content.addAll(title, textContainer,
s.createNextButton(e -> createBirthday().show()));
return s;
}
SignupForm
TextModeLayout is a layout manager designed for TextComponent it uses TableLayout on Android & BoxLayout on iOS.

This will act like adding to a TableLayout when running in Android thus placing the components side by side. 



On iOS is would ignore the percentage value and stack the components vertically using a BoxLayout on the Y axis.

The TextModeLayout isn't really a layout as much as it is a delegate. When running in the Android mode (which we refer to as the "on top" mode) the layout is almost an
exact synonym of TableLayout and in fact delegates to an underlying table layout. In fact there is a public final TableLayout instance within the layout that you "can" refer
to directly...

There is one small difference between the TextModeLayout and the underlying TableLayout and that's our choice to default to align entries to TOP with this mode. It's
important for error handling which I didn't use here.

When working in the non-android environment we use a BoxLayout on the Y axis as the basis. There is one thing we do here that's different from a default box layout and
that's grouping. Grouping allows the labels to align by setting them to the same width, internally it just invokes Component.setSameWidth(). Since text components hide
the labels there is a special group method there that can be used. However, this is implicit with the TextModeLayout which is pretty cool.
s.content.addAll(title, rt, next);
return s;
}
public static SignupForm createName() {
SignupForm s = new SignupForm("Name", "Terms",
getCurrentForm());
Label title = new Label("What's Your Name?", "SignupSubHeader");
TextComponent first = new TextComponent().
label("First Name").columns(12);
TextComponent last = new TextComponent().
label("Last Name").columns(12);
TextModeLayout layout = new TextModeLayout(1, 2);
Container textContainer = new Container(layout, "PaddedContainer");
textContainer.add(layout.createConstraint().
widthPercentage(50), first);
textContainer.add(layout.createConstraint().
widthPercentage(50), last);
last.getField().setDoneListener(e -> createBirthday().show());
s.content.addAll(title, textContainer,
s.createNextButton(e -> createBirthday().show()));
return s;
}
SignupForm
This listens to the done button in the virtual keyboard and automatically treats it as a click on next button
FloatingHint {
font-family: "native:MainRegular";
font-size: 2mm;
padding: 2mm 2mm 0.5mm 2mm;
margin: 0px;
color: black;
}
theme.css
For this form I need to add one change to the CSS. This is the text that appears on top of the Android field when we have input there. 

It's a really small label that uses regular font for visibility instead of light.

With that we finished the name form and it should "just work”...
© Codename One 2017 all rights reserved
Birthday is the form I'm currently least happy with. We are in the process of rewriting the Picker component which would hopefully allow a much better looking UI for this
Form. For now I compromised on this. When the UI is clicked on the device you will see a nice looking date picker UI though...
last.getField().setDoneListener(e -> createBirthday().show());
s.content.addAll(title, textContainer,
s.createNextButton(e -> createBirthday().show()));
return s;
}
public static SignupForm createBirthday() {
SignupForm s = new SignupForm("Birthday",
"Name",
getCurrentForm());
Label title = new Label("What's Your Birthday?", "SignupSubHeader");
Picker datePicker = new Picker();
datePicker.setType(PICKER_TYPE_DATE);
int twentyYears = 60000 * 60 * 24 * 365 * 20;
datePicker.setDate(new Date(System.currentTimeMillis() -
twentyYears));
s.content.addAll(title, datePicker,
s.createNextButton(e -> createGender().show()));
return s;
}
private static RadioButton createGenderButton(ButtonGroup bg,
String label, String icon) {
Style unselectedIconStyle = UIManager.getInstance().
SignupForm
The flip side is that the code is super simple.
last.getField().setDoneListener(e -> createBirthday().show());
s.content.addAll(title, textContainer,
s.createNextButton(e -> createBirthday().show()));
return s;
}
public static SignupForm createBirthday() {
SignupForm s = new SignupForm("Birthday",
"Name",
getCurrentForm());
Label title = new Label("What's Your Birthday?", "SignupSubHeader");
Picker datePicker = new Picker();
datePicker.setType(PICKER_TYPE_DATE);
int twentyYears = 60000 * 60 * 24 * 365 * 20;
datePicker.setDate(new Date(System.currentTimeMillis() -
twentyYears));
s.content.addAll(title, datePicker,
s.createNextButton(e -> createGender().show()));
return s;
}
private static RadioButton createGenderButton(ButtonGroup bg,
String label, String icon) {
Style unselectedIconStyle = UIManager.getInstance().
SignupForm
We set the picker type to date
last.getField().setDoneListener(e -> createBirthday().show());
s.content.addAll(title, textContainer,
s.createNextButton(e -> createBirthday().show()));
return s;
}
public static SignupForm createBirthday() {
SignupForm s = new SignupForm("Birthday",
"Name",
getCurrentForm());
Label title = new Label("What's Your Birthday?", "SignupSubHeader");
Picker datePicker = new Picker();
datePicker.setType(PICKER_TYPE_DATE);
int twentyYears = 60000 * 60 * 24 * 365 * 20;
datePicker.setDate(new Date(System.currentTimeMillis() -
twentyYears));
s.content.addAll(title, datePicker,
s.createNextButton(e -> createGender().show()));
return s;
}
private static RadioButton createGenderButton(ButtonGroup bg,
String label, String icon) {
Style unselectedIconStyle = UIManager.getInstance().
SignupForm
Twenty years ago is a good place to start for an age picker by default so that’s what I did. That's trivial and includes no changes to the CSS.
© Codename One 2017 all rights reserved
The gender form is pretty simple, we have a couple of UIID’s for the gender toggle & icons.
datePicker.setDate(new Date(System.currentTimeMillis() -
twentyYears));
s.content.addAll(title, datePicker,
s.createNextButton(e -> createGender().show()));
return s;
}
private static RadioButton createGenderButton(ButtonGroup bg,
String label, String icon) {
Style unselectedIconStyle = UIManager.getInstance().
getComponentStyle("GenderIcons");
Style selectedIconStyle = UIManager.getInstance().
getComponentSelectedStyle("GenderIcons");
FontImage unIcon =
FontImage.create(icon, unselectedIconStyle);
FontImage selIcon =
FontImage.create(icon, selectedIconStyle);
RadioButton rb = RadioButton.createToggle(label, unIcon, bg);
rb.setTextPosition(BOTTOM);
rb.setRolloverIcon(selIcon);
rb.setPressedIcon(selIcon);
rb.setUIID("GenderToggle");
return rb;
}
public static SignupForm createGender() {
SignupForm
Before we can go into it I created a small helper method to make the two gender buttons. Toggle buttons in Codename One can be radio buttons. That means that we
can pick only one of them, when we click on female the male entry is deselected
datePicker.setDate(new Date(System.currentTimeMillis() -
twentyYears));
s.content.addAll(title, datePicker,
s.createNextButton(e -> createGender().show()));
return s;
}
private static RadioButton createGenderButton(ButtonGroup bg,
String label, String icon) {
Style unselectedIconStyle = UIManager.getInstance().
getComponentStyle("GenderIcons");
Style selectedIconStyle = UIManager.getInstance().
getComponentSelectedStyle("GenderIcons");
FontImage unIcon =
FontImage.create(icon, unselectedIconStyle);
FontImage selIcon =
FontImage.create(icon, selectedIconStyle);
RadioButton rb = RadioButton.createToggle(label, unIcon, bg);
rb.setTextPosition(BOTTOM);
rb.setRolloverIcon(selIcon);
rb.setPressedIcon(selIcon);
rb.setUIID("GenderToggle");
return rb;
}
public static SignupForm createGender() {
SignupForm
We create the font icon based on a separate UIID because we want it to be much bigger than the text on the button. So we can't just use setMaterialIcon.
datePicker.setDate(new Date(System.currentTimeMillis() -
twentyYears));
s.content.addAll(title, datePicker,
s.createNextButton(e -> createGender().show()));
return s;
}
private static RadioButton createGenderButton(ButtonGroup bg,
String label, String icon) {
Style unselectedIconStyle = UIManager.getInstance().
getComponentStyle("GenderIcons");
Style selectedIconStyle = UIManager.getInstance().
getComponentSelectedStyle("GenderIcons");
FontImage unIcon =
FontImage.create(icon, unselectedIconStyle);
FontImage selIcon =
FontImage.create(icon, selectedIconStyle);
RadioButton rb = RadioButton.createToggle(label, unIcon, bg);
rb.setTextPosition(BOTTOM);
rb.setRolloverIcon(selIcon);
rb.setPressedIcon(selIcon);
rb.setUIID("GenderToggle");
return rb;
}
public static SignupForm createGender() {
SignupForm
Here we create the radio button and set the text positioning. A radio button belongs to a group & only one member of the group can be selected
rb.setTextPosition(BOTTOM);
rb.setRolloverIcon(selIcon);
rb.setPressedIcon(selIcon);
rb.setUIID("GenderToggle");
return rb;
}
public static SignupForm createGender() {
SignupForm s = new SignupForm("Gender",
"Birthday",
getCurrentForm());
Label title = new Label("What's Your Gender?", "SignupSubHeader");
ButtonGroup bg = new ButtonGroup();
RadioButton female = createGenderButton(bg, "Female", "ue800");
RadioButton male = createGenderButton(bg, "Male", "ue801");
Container buttons = GridLayout.encloseIn(2, female, male);
buttons.setUIID("PaddedContainer");
s.content.addAll(title, buttons,
s.createNextButton(e -> createNumber().show()));
return s;
}
SignupForm
That's mostly simple boilerplate code. The Form code is even simpler.
rb.setTextPosition(BOTTOM);
rb.setRolloverIcon(selIcon);
rb.setPressedIcon(selIcon);
rb.setUIID("GenderToggle");
return rb;
}
public static SignupForm createGender() {
SignupForm s = new SignupForm("Gender",
"Birthday",
getCurrentForm());
Label title = new Label("What's Your Gender?", "SignupSubHeader");
ButtonGroup bg = new ButtonGroup();
RadioButton female = createGenderButton(bg, "Female", "ue800");
RadioButton male = createGenderButton(bg, "Male", "ue801");
Container buttons = GridLayout.encloseIn(2, female, male);
buttons.setUIID("PaddedContainer");
s.content.addAll(title, buttons,
s.createNextButton(e -> createNumber().show()));
return s;
}
SignupForm
We use ButtonGroup to tie two or more radio buttons together. Only one of the radio buttons in a group can be selected
rb.setTextPosition(BOTTOM);
rb.setRolloverIcon(selIcon);
rb.setPressedIcon(selIcon);
rb.setUIID("GenderToggle");
return rb;
}
public static SignupForm createGender() {
SignupForm s = new SignupForm("Gender",
"Birthday",
getCurrentForm());
Label title = new Label("What's Your Gender?", "SignupSubHeader");
ButtonGroup bg = new ButtonGroup();
RadioButton female = createGenderButton(bg, "Female", "ue800");
RadioButton male = createGenderButton(bg, "Male", "ue801");
Container buttons = GridLayout.encloseIn(2, female, male);
buttons.setUIID("PaddedContainer");
s.content.addAll(title, buttons,
s.createNextButton(e -> createNumber().show()));
return s;
}
SignupForm
GridLayout gives both buttons the exact same size
GenderIcons {
cn1-derive: IconFont;
color: #587EBE;
}
GenderIcons.selected, GenderIcons.pressed {
color: white;
}
GenderToggle {
text-align: center;
border-radius: 3mm;
padding: 4mm;
background: white;
margin: 2mm;
border-color: #cccccc;
border-width: 1px;
}
GenderToggle.selected, GenderToggle.pressed {
background: #587EBE;
border-color: #cccccc;
border-width: 1px;
}
theme.css
The last piece for this form is the CSS for the UIID's we defined.

The gender icon uses the same icon settings as the logo with a different color
GenderIcons {
cn1-derive: IconFont;
color: #587EBE;
}
GenderIcons.selected, GenderIcons.pressed {
color: white;
}
GenderToggle {
text-align: center;
border-radius: 3mm;
padding: 4mm;
background: white;
margin: 2mm;
border-color: #cccccc;
border-width: 1px;
}
GenderToggle.selected, GenderToggle.pressed {
background: #587EBE;
border-color: #cccccc;
border-width: 1px;
}
theme.css
We have a special case for the selected/pressed versions of the UIID to make the icon white
GenderIcons {
cn1-derive: IconFont;
color: #587EBE;
}
GenderIcons.selected, GenderIcons.pressed {
color: white;
}
GenderToggle {
text-align: center;
border-radius: 3mm;
padding: 4mm;
background: white;
margin: 2mm;
border-color: #cccccc;
border-width: 1px;
}
GenderToggle.selected, GenderToggle.pressed {
background: #587EBE;
border-color: #cccccc;
border-width: 1px;
}
theme.css
The GenderToggle UIID uses a round rect border with a gray line surrounding it

Once we did all of that we can run the app and we would be halfway through the wizard!

More Related Content

More from ShaiAlmog1

create-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfcreate-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdf
ShaiAlmog1
 
create-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdfcreate-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdfcreate-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfcreate-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdf
ShaiAlmog1
 
create-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdfcreate-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdfCreating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdfCreating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdfCreating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdfCreating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdfCreating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdfCreating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdfCreating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part IX.pdf
Creating a Whatsapp Clone - Part IX.pdfCreating a Whatsapp Clone - Part IX.pdf
Creating a Whatsapp Clone - Part IX.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part VI.pdf
Creating a Whatsapp Clone - Part VI.pdfCreating a Whatsapp Clone - Part VI.pdf
Creating a Whatsapp Clone - Part VI.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part III - Transcript.pdf
Creating a Whatsapp Clone - Part III - Transcript.pdfCreating a Whatsapp Clone - Part III - Transcript.pdf
Creating a Whatsapp Clone - Part III - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part XI - Transcript.pdf
Creating a Whatsapp Clone - Part XI - Transcript.pdfCreating a Whatsapp Clone - Part XI - Transcript.pdf
Creating a Whatsapp Clone - Part XI - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part VII.pdf
Creating a Whatsapp Clone - Part VII.pdfCreating a Whatsapp Clone - Part VII.pdf
Creating a Whatsapp Clone - Part VII.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part XIII - Transcript.pdf
Creating a Whatsapp Clone - Part XIII - Transcript.pdfCreating a Whatsapp Clone - Part XIII - Transcript.pdf
Creating a Whatsapp Clone - Part XIII - Transcript.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part V.pdf
Creating a Whatsapp Clone - Part V.pdfCreating a Whatsapp Clone - Part V.pdf
Creating a Whatsapp Clone - Part V.pdf
ShaiAlmog1
 
Creating a Whatsapp Clone - Part X - Transcript.pdf
Creating a Whatsapp Clone - Part X - Transcript.pdfCreating a Whatsapp Clone - Part X - Transcript.pdf
Creating a Whatsapp Clone - Part X - Transcript.pdf
ShaiAlmog1
 

More from ShaiAlmog1 (20)

create-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdfcreate-netflix-clone-04-server-continued.pdf
create-netflix-clone-04-server-continued.pdf
 
create-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdfcreate-netflix-clone-05-client-model_transcript.pdf
create-netflix-clone-05-client-model_transcript.pdf
 
create-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdfcreate-netflix-clone-03-server_transcript.pdf
create-netflix-clone-03-server_transcript.pdf
 
create-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfcreate-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdf
 
create-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdfcreate-netflix-clone-05-client-model.pdf
create-netflix-clone-05-client-model.pdf
 
Creating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdfCreating a Whatsapp Clone - Part II.pdf
Creating a Whatsapp Clone - Part II.pdf
 
Creating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdfCreating a Whatsapp Clone - Part IX - Transcript.pdf
Creating a Whatsapp Clone - Part IX - Transcript.pdf
 
Creating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdfCreating a Whatsapp Clone - Part II - Transcript.pdf
Creating a Whatsapp Clone - Part II - Transcript.pdf
 
Creating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdfCreating a Whatsapp Clone - Part V - Transcript.pdf
Creating a Whatsapp Clone - Part V - Transcript.pdf
 
Creating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdfCreating a Whatsapp Clone - Part IV - Transcript.pdf
Creating a Whatsapp Clone - Part IV - Transcript.pdf
 
Creating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdfCreating a Whatsapp Clone - Part IV.pdf
Creating a Whatsapp Clone - Part IV.pdf
 
Creating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdfCreating a Whatsapp Clone - Part I - Transcript.pdf
Creating a Whatsapp Clone - Part I - Transcript.pdf
 
Creating a Whatsapp Clone - Part IX.pdf
Creating a Whatsapp Clone - Part IX.pdfCreating a Whatsapp Clone - Part IX.pdf
Creating a Whatsapp Clone - Part IX.pdf
 
Creating a Whatsapp Clone - Part VI.pdf
Creating a Whatsapp Clone - Part VI.pdfCreating a Whatsapp Clone - Part VI.pdf
Creating a Whatsapp Clone - Part VI.pdf
 
Creating a Whatsapp Clone - Part III - Transcript.pdf
Creating a Whatsapp Clone - Part III - Transcript.pdfCreating a Whatsapp Clone - Part III - Transcript.pdf
Creating a Whatsapp Clone - Part III - Transcript.pdf
 
Creating a Whatsapp Clone - Part XI - Transcript.pdf
Creating a Whatsapp Clone - Part XI - Transcript.pdfCreating a Whatsapp Clone - Part XI - Transcript.pdf
Creating a Whatsapp Clone - Part XI - Transcript.pdf
 
Creating a Whatsapp Clone - Part VII.pdf
Creating a Whatsapp Clone - Part VII.pdfCreating a Whatsapp Clone - Part VII.pdf
Creating a Whatsapp Clone - Part VII.pdf
 
Creating a Whatsapp Clone - Part XIII - Transcript.pdf
Creating a Whatsapp Clone - Part XIII - Transcript.pdfCreating a Whatsapp Clone - Part XIII - Transcript.pdf
Creating a Whatsapp Clone - Part XIII - Transcript.pdf
 
Creating a Whatsapp Clone - Part V.pdf
Creating a Whatsapp Clone - Part V.pdfCreating a Whatsapp Clone - Part V.pdf
Creating a Whatsapp Clone - Part V.pdf
 
Creating a Whatsapp Clone - Part X - Transcript.pdf
Creating a Whatsapp Clone - Part X - Transcript.pdfCreating a Whatsapp Clone - Part X - Transcript.pdf
Creating a Whatsapp Clone - Part X - Transcript.pdf
 

Creating a Facebook Clone - Part VII - Transcript.pdf

  • 1. Creating a Facebook Clone - Part VII Next we have the name entry stage in the signup wizard
  • 2. © Codename One 2017 all rights reserved The name entry stage in the signup wizard is pretty trivial, there is just one interesting aspect here: The text input.
  • 3. © Codename One 2017 all rights reserved The name entry stage in the signup wizard is pretty trivial, there is just one interesting aspect here: The text input.
  • 4. © Codename One 2017 all rights reserved Notice that the text input looks different in Android when we enter text and on iOS it looks completely different. This is a part of the "magic" behind the TextComponent class. On Android we animate hint labels in the style of material design and in iOS we show a grouped pair.
  • 5. s.content.addAll(title, rt, next); return s; } public static SignupForm createName() { SignupForm s = new SignupForm("Name", "Terms", getCurrentForm()); Label title = new Label("What's Your Name?", "SignupSubHeader"); TextComponent first = new TextComponent(). label("First Name").columns(12); TextComponent last = new TextComponent(). label("Last Name").columns(12); TextModeLayout layout = new TextModeLayout(1, 2); Container textContainer = new Container(layout, "PaddedContainer"); textContainer.add(layout.createConstraint(). widthPercentage(50), first); textContainer.add(layout.createConstraint(). widthPercentage(50), last); last.getField().setDoneListener(e -> createBirthday().show()); s.content.addAll(title, textContainer, s.createNextButton(e -> createBirthday().show())); return s; } SignupForm Lets go right into the createName method. TextComponent is a text input component that combines the label and TextField into one component and automatically adapts it to the platform
  • 6. s.content.addAll(title, rt, next); return s; } public static SignupForm createName() { SignupForm s = new SignupForm("Name", "Terms", getCurrentForm()); Label title = new Label("What's Your Name?", "SignupSubHeader"); TextComponent first = new TextComponent(). label("First Name").columns(12); TextComponent last = new TextComponent(). label("Last Name").columns(12); TextModeLayout layout = new TextModeLayout(1, 2); Container textContainer = new Container(layout, "PaddedContainer"); textContainer.add(layout.createConstraint(). widthPercentage(50), first); textContainer.add(layout.createConstraint(). widthPercentage(50), last); last.getField().setDoneListener(e -> createBirthday().show()); s.content.addAll(title, textContainer, s.createNextButton(e -> createBirthday().show())); return s; } SignupForm TextModeLayout is a layout manager designed for TextComponent it uses TableLayout on Android & BoxLayout on iOS. This will act like adding to a TableLayout when running in Android thus placing the components side by side. 
 On iOS is would ignore the percentage value and stack the components vertically using a BoxLayout on the Y axis. The TextModeLayout isn't really a layout as much as it is a delegate. When running in the Android mode (which we refer to as the "on top" mode) the layout is almost an exact synonym of TableLayout and in fact delegates to an underlying table layout. In fact there is a public final TableLayout instance within the layout that you "can" refer to directly... There is one small difference between the TextModeLayout and the underlying TableLayout and that's our choice to default to align entries to TOP with this mode. It's important for error handling which I didn't use here. When working in the non-android environment we use a BoxLayout on the Y axis as the basis. There is one thing we do here that's different from a default box layout and that's grouping. Grouping allows the labels to align by setting them to the same width, internally it just invokes Component.setSameWidth(). Since text components hide the labels there is a special group method there that can be used. However, this is implicit with the TextModeLayout which is pretty cool.
  • 7. s.content.addAll(title, rt, next); return s; } public static SignupForm createName() { SignupForm s = new SignupForm("Name", "Terms", getCurrentForm()); Label title = new Label("What's Your Name?", "SignupSubHeader"); TextComponent first = new TextComponent(). label("First Name").columns(12); TextComponent last = new TextComponent(). label("Last Name").columns(12); TextModeLayout layout = new TextModeLayout(1, 2); Container textContainer = new Container(layout, "PaddedContainer"); textContainer.add(layout.createConstraint(). widthPercentage(50), first); textContainer.add(layout.createConstraint(). widthPercentage(50), last); last.getField().setDoneListener(e -> createBirthday().show()); s.content.addAll(title, textContainer, s.createNextButton(e -> createBirthday().show())); return s; } SignupForm This listens to the done button in the virtual keyboard and automatically treats it as a click on next button
  • 8. FloatingHint { font-family: "native:MainRegular"; font-size: 2mm; padding: 2mm 2mm 0.5mm 2mm; margin: 0px; color: black; } theme.css For this form I need to add one change to the CSS. This is the text that appears on top of the Android field when we have input there. It's a really small label that uses regular font for visibility instead of light. With that we finished the name form and it should "just work”...
  • 9. © Codename One 2017 all rights reserved Birthday is the form I'm currently least happy with. We are in the process of rewriting the Picker component which would hopefully allow a much better looking UI for this Form. For now I compromised on this. When the UI is clicked on the device you will see a nice looking date picker UI though...
  • 10. last.getField().setDoneListener(e -> createBirthday().show()); s.content.addAll(title, textContainer, s.createNextButton(e -> createBirthday().show())); return s; } public static SignupForm createBirthday() { SignupForm s = new SignupForm("Birthday", "Name", getCurrentForm()); Label title = new Label("What's Your Birthday?", "SignupSubHeader"); Picker datePicker = new Picker(); datePicker.setType(PICKER_TYPE_DATE); int twentyYears = 60000 * 60 * 24 * 365 * 20; datePicker.setDate(new Date(System.currentTimeMillis() - twentyYears)); s.content.addAll(title, datePicker, s.createNextButton(e -> createGender().show())); return s; } private static RadioButton createGenderButton(ButtonGroup bg, String label, String icon) { Style unselectedIconStyle = UIManager.getInstance(). SignupForm The flip side is that the code is super simple.
  • 11. last.getField().setDoneListener(e -> createBirthday().show()); s.content.addAll(title, textContainer, s.createNextButton(e -> createBirthday().show())); return s; } public static SignupForm createBirthday() { SignupForm s = new SignupForm("Birthday", "Name", getCurrentForm()); Label title = new Label("What's Your Birthday?", "SignupSubHeader"); Picker datePicker = new Picker(); datePicker.setType(PICKER_TYPE_DATE); int twentyYears = 60000 * 60 * 24 * 365 * 20; datePicker.setDate(new Date(System.currentTimeMillis() - twentyYears)); s.content.addAll(title, datePicker, s.createNextButton(e -> createGender().show())); return s; } private static RadioButton createGenderButton(ButtonGroup bg, String label, String icon) { Style unselectedIconStyle = UIManager.getInstance(). SignupForm We set the picker type to date
  • 12. last.getField().setDoneListener(e -> createBirthday().show()); s.content.addAll(title, textContainer, s.createNextButton(e -> createBirthday().show())); return s; } public static SignupForm createBirthday() { SignupForm s = new SignupForm("Birthday", "Name", getCurrentForm()); Label title = new Label("What's Your Birthday?", "SignupSubHeader"); Picker datePicker = new Picker(); datePicker.setType(PICKER_TYPE_DATE); int twentyYears = 60000 * 60 * 24 * 365 * 20; datePicker.setDate(new Date(System.currentTimeMillis() - twentyYears)); s.content.addAll(title, datePicker, s.createNextButton(e -> createGender().show())); return s; } private static RadioButton createGenderButton(ButtonGroup bg, String label, String icon) { Style unselectedIconStyle = UIManager.getInstance(). SignupForm Twenty years ago is a good place to start for an age picker by default so that’s what I did. That's trivial and includes no changes to the CSS.
  • 13. © Codename One 2017 all rights reserved The gender form is pretty simple, we have a couple of UIID’s for the gender toggle & icons.
  • 14. datePicker.setDate(new Date(System.currentTimeMillis() - twentyYears)); s.content.addAll(title, datePicker, s.createNextButton(e -> createGender().show())); return s; } private static RadioButton createGenderButton(ButtonGroup bg, String label, String icon) { Style unselectedIconStyle = UIManager.getInstance(). getComponentStyle("GenderIcons"); Style selectedIconStyle = UIManager.getInstance(). getComponentSelectedStyle("GenderIcons"); FontImage unIcon = FontImage.create(icon, unselectedIconStyle); FontImage selIcon = FontImage.create(icon, selectedIconStyle); RadioButton rb = RadioButton.createToggle(label, unIcon, bg); rb.setTextPosition(BOTTOM); rb.setRolloverIcon(selIcon); rb.setPressedIcon(selIcon); rb.setUIID("GenderToggle"); return rb; } public static SignupForm createGender() { SignupForm Before we can go into it I created a small helper method to make the two gender buttons. Toggle buttons in Codename One can be radio buttons. That means that we can pick only one of them, when we click on female the male entry is deselected
  • 15. datePicker.setDate(new Date(System.currentTimeMillis() - twentyYears)); s.content.addAll(title, datePicker, s.createNextButton(e -> createGender().show())); return s; } private static RadioButton createGenderButton(ButtonGroup bg, String label, String icon) { Style unselectedIconStyle = UIManager.getInstance(). getComponentStyle("GenderIcons"); Style selectedIconStyle = UIManager.getInstance(). getComponentSelectedStyle("GenderIcons"); FontImage unIcon = FontImage.create(icon, unselectedIconStyle); FontImage selIcon = FontImage.create(icon, selectedIconStyle); RadioButton rb = RadioButton.createToggle(label, unIcon, bg); rb.setTextPosition(BOTTOM); rb.setRolloverIcon(selIcon); rb.setPressedIcon(selIcon); rb.setUIID("GenderToggle"); return rb; } public static SignupForm createGender() { SignupForm We create the font icon based on a separate UIID because we want it to be much bigger than the text on the button. So we can't just use setMaterialIcon.
  • 16. datePicker.setDate(new Date(System.currentTimeMillis() - twentyYears)); s.content.addAll(title, datePicker, s.createNextButton(e -> createGender().show())); return s; } private static RadioButton createGenderButton(ButtonGroup bg, String label, String icon) { Style unselectedIconStyle = UIManager.getInstance(). getComponentStyle("GenderIcons"); Style selectedIconStyle = UIManager.getInstance(). getComponentSelectedStyle("GenderIcons"); FontImage unIcon = FontImage.create(icon, unselectedIconStyle); FontImage selIcon = FontImage.create(icon, selectedIconStyle); RadioButton rb = RadioButton.createToggle(label, unIcon, bg); rb.setTextPosition(BOTTOM); rb.setRolloverIcon(selIcon); rb.setPressedIcon(selIcon); rb.setUIID("GenderToggle"); return rb; } public static SignupForm createGender() { SignupForm Here we create the radio button and set the text positioning. A radio button belongs to a group & only one member of the group can be selected
  • 17. rb.setTextPosition(BOTTOM); rb.setRolloverIcon(selIcon); rb.setPressedIcon(selIcon); rb.setUIID("GenderToggle"); return rb; } public static SignupForm createGender() { SignupForm s = new SignupForm("Gender", "Birthday", getCurrentForm()); Label title = new Label("What's Your Gender?", "SignupSubHeader"); ButtonGroup bg = new ButtonGroup(); RadioButton female = createGenderButton(bg, "Female", "ue800"); RadioButton male = createGenderButton(bg, "Male", "ue801"); Container buttons = GridLayout.encloseIn(2, female, male); buttons.setUIID("PaddedContainer"); s.content.addAll(title, buttons, s.createNextButton(e -> createNumber().show())); return s; } SignupForm That's mostly simple boilerplate code. The Form code is even simpler.
  • 18. rb.setTextPosition(BOTTOM); rb.setRolloverIcon(selIcon); rb.setPressedIcon(selIcon); rb.setUIID("GenderToggle"); return rb; } public static SignupForm createGender() { SignupForm s = new SignupForm("Gender", "Birthday", getCurrentForm()); Label title = new Label("What's Your Gender?", "SignupSubHeader"); ButtonGroup bg = new ButtonGroup(); RadioButton female = createGenderButton(bg, "Female", "ue800"); RadioButton male = createGenderButton(bg, "Male", "ue801"); Container buttons = GridLayout.encloseIn(2, female, male); buttons.setUIID("PaddedContainer"); s.content.addAll(title, buttons, s.createNextButton(e -> createNumber().show())); return s; } SignupForm We use ButtonGroup to tie two or more radio buttons together. Only one of the radio buttons in a group can be selected
  • 19. rb.setTextPosition(BOTTOM); rb.setRolloverIcon(selIcon); rb.setPressedIcon(selIcon); rb.setUIID("GenderToggle"); return rb; } public static SignupForm createGender() { SignupForm s = new SignupForm("Gender", "Birthday", getCurrentForm()); Label title = new Label("What's Your Gender?", "SignupSubHeader"); ButtonGroup bg = new ButtonGroup(); RadioButton female = createGenderButton(bg, "Female", "ue800"); RadioButton male = createGenderButton(bg, "Male", "ue801"); Container buttons = GridLayout.encloseIn(2, female, male); buttons.setUIID("PaddedContainer"); s.content.addAll(title, buttons, s.createNextButton(e -> createNumber().show())); return s; } SignupForm GridLayout gives both buttons the exact same size
  • 20. GenderIcons { cn1-derive: IconFont; color: #587EBE; } GenderIcons.selected, GenderIcons.pressed { color: white; } GenderToggle { text-align: center; border-radius: 3mm; padding: 4mm; background: white; margin: 2mm; border-color: #cccccc; border-width: 1px; } GenderToggle.selected, GenderToggle.pressed { background: #587EBE; border-color: #cccccc; border-width: 1px; } theme.css The last piece for this form is the CSS for the UIID's we defined. The gender icon uses the same icon settings as the logo with a different color
  • 21. GenderIcons { cn1-derive: IconFont; color: #587EBE; } GenderIcons.selected, GenderIcons.pressed { color: white; } GenderToggle { text-align: center; border-radius: 3mm; padding: 4mm; background: white; margin: 2mm; border-color: #cccccc; border-width: 1px; } GenderToggle.selected, GenderToggle.pressed { background: #587EBE; border-color: #cccccc; border-width: 1px; } theme.css We have a special case for the selected/pressed versions of the UIID to make the icon white
  • 22. GenderIcons { cn1-derive: IconFont; color: #587EBE; } GenderIcons.selected, GenderIcons.pressed { color: white; } GenderToggle { text-align: center; border-radius: 3mm; padding: 4mm; background: white; margin: 2mm; border-color: #cccccc; border-width: 1px; } GenderToggle.selected, GenderToggle.pressed { background: #587EBE; border-color: #cccccc; border-width: 1px; } theme.css The GenderToggle UIID uses a round rect border with a gray line surrounding it Once we did all of that we can run the app and we would be halfway through the wizard!