SlideShare a Scribd company logo
Creating an Uber Clone - Part V
In this part we’ll finally leave the confines of the login form and move to the simpler forms of social login and the country picker UI. I’ll start with the social login mockup
since it’s so small and simple
Social Login
© Codename One 2017 all rights reserved
This is the form you see when you choose the social login option, I cropped the bottom as it’s just white. This is a pretty trivial UI…
public class FacebookOrGoogleLoginForm extends Form {
public FacebookOrGoogleLoginForm() {
super(BoxLayout.y());
Form previous = getCurrentForm();
getToolbar().setBackCommand("",
Toolbar.BackCommandPolicy.AS_ARROW,
e -> previous.showBack());
add(new Label("Choose an account", "FlagButton"));
Button facebook = new Button("Facebook",
Resources.getGlobalResources().getImage("facebook.png"),
"FlagButton");
Button google = new Button("Google",
Resources.getGlobalResources().getImage("google.png"),
“FlagButton");
add(facebook).add(google);
}
}
FacebookOrGoogleLoginForm
There isn’t that much to say about this form, it’s trivial. We use two icons for Facebook and Google and define the back arrow. Thanks to all the theming work we did up
to this point everything “just works” and looks like the Uber app.

We do need to define the FlagButton through as it’s a UIID that I reuse in several forms. It got the name from the countries picker form which we’ll go into next.
FlagButton
© Codename One 2017 all rights reserved
The flag button is just a label in terms of padding etc.
FlagButton
© Codename One 2017 all rights reserved
It has a subtly larger font at 3.2 millimeters not much larger
Country Picker
© Codename One 2017 all rights reserved
The country picker form lists the countries next to their flags. The first letter of the country name is highlighted between the countries and when you scroll down the title
area collapses to make more room. It does that with a smooth animation effect. Speaking of the title area it’s while on black instead of black on white…

We reach this form when we click the Country Picker button but that only happens in the phone number entry form which we will discuss shortly.
public class CountryPickerForm extends Form {
public CountryPickerForm(Button sourceButton, Resources flags) {
super(BoxLayout.y());
CommonCode.initBlackTitleForm(this, "Select a Country", val -> search(val));
Image blankIcon = Image.createImage(100, 70, 0);
char lastChar = (char)-1;
for(int iter = 0 ; iter < ActivationForm.COUNTRY_CODES.length ; iter++) {
Button b = new Button(ActivationForm.COUNTRY_NAMES[iter], "FlagButton");
char current = b.getText().charAt(0);
if(current != lastChar) {
lastChar = current;
Label l = new Label("" + lastChar, "FlagsLetter");
add(l);
}
b.setIcon(flags.getImage(ActivationForm.COUNTRY_FLAGS[iter]));
if(b.getIcon() == null) {
b.setIcon(blankIcon);
}
String currentCountryCode = ActivationForm.COUNTRY_CODES[iter];
b.addActionListener(ee -> {
sourceButton.setIcon(b.getIcon());
sourceButton.setText("+" + currentCountryCode);
CountryPickerForm
Let’s jump right into the code. 

Predictably the form is a BoxLayout container on the Y axis. The initBlackTitleForm method is a static method in a common utility class. We'll cover it soon
public class CountryPickerForm extends Form {
public CountryPickerForm(Button sourceButton, Resources flags) {
super(BoxLayout.y());
CommonCode.initBlackTitleForm(this, "Select a Country", val -> search(val));
Image blankIcon = Image.createImage(100, 70, 0);
char lastChar = (char)-1;
for(int iter = 0 ; iter < ActivationForm.COUNTRY_CODES.length ; iter++) {
Button b = new Button(ActivationForm.COUNTRY_NAMES[iter], "FlagButton");
char current = b.getText().charAt(0);
if(current != lastChar) {
lastChar = current;
Label l = new Label("" + lastChar, "FlagsLetter");
add(l);
}
b.setIcon(flags.getImage(ActivationForm.COUNTRY_FLAGS[iter]));
if(b.getIcon() == null) {
b.setIcon(blankIcon);
}
String currentCountryCode = ActivationForm.COUNTRY_CODES[iter];
b.addActionListener(ee -> {
sourceButton.setIcon(b.getIcon());
sourceButton.setText("+" + currentCountryCode);
CountryPickerForm
We don't have flags for all the countries so we need a blank space icon so the elements align
public class CountryPickerForm extends Form {
public CountryPickerForm(Button sourceButton, Resources flags) {
super(BoxLayout.y());
CommonCode.initBlackTitleForm(this, "Select a Country", val -> search(val));
Image blankIcon = Image.createImage(100, 70, 0);
char lastChar = (char)-1;
for(int iter = 0 ; iter < ActivationForm.COUNTRY_CODES.length ; iter++) {
Button b = new Button(ActivationForm.COUNTRY_NAMES[iter], "FlagButton");
char current = b.getText().charAt(0);
if(current != lastChar) {
lastChar = current;
Label l = new Label("" + lastChar, "FlagsLetter");
add(l);
}
b.setIcon(flags.getImage(ActivationForm.COUNTRY_FLAGS[iter]));
if(b.getIcon() == null) {
b.setIcon(blankIcon);
}
String currentCountryCode = ActivationForm.COUNTRY_CODES[iter];
b.addActionListener(ee -> {
sourceButton.setIcon(b.getIcon());
sourceButton.setText("+" + currentCountryCode);
CountryPickerForm
Here we loop over all the country codes and create a button with the FlagsLetter UIID for every entry. 

We also need to implement the alphabet letter headers, every time the first character of a country changes we add a label representing the entry
public class CountryPickerForm extends Form {
public CountryPickerForm(Button sourceButton, Resources flags) {
super(BoxLayout.y());
CommonCode.initBlackTitleForm(this, "Select a Country", val -> search(val));
Image blankIcon = Image.createImage(100, 70, 0);
char lastChar = (char)-1;
for(int iter = 0 ; iter < ActivationForm.COUNTRY_CODES.length ; iter++) {
Button b = new Button(ActivationForm.COUNTRY_NAMES[iter], "FlagButton");
char current = b.getText().charAt(0);
if(current != lastChar) {
lastChar = current;
Label l = new Label("" + lastChar, "FlagsLetter");
add(l);
}
b.setIcon(flags.getImage(ActivationForm.COUNTRY_FLAGS[iter]));
if(b.getIcon() == null) {
b.setIcon(blankIcon);
}
String currentCountryCode = ActivationForm.COUNTRY_CODES[iter];
b.addActionListener(ee -> {
sourceButton.setIcon(b.getIcon());
sourceButton.setText("+" + currentCountryCode);
CountryPickerForm
When an entry is selected we update the text and icon of the CountryCodePicker Button that launched this form
b.setIcon(flags.getImage(ActivationForm.COUNTRY_FLAGS[iter]));
if(b.getIcon() == null) {
b.setIcon(blankIcon);
}
String currentCountryCode = ActivationForm.COUNTRY_CODES[iter];
b.addActionListener(ee -> {
sourceButton.setIcon(b.getIcon());
sourceButton.setText("+" + currentCountryCode);
});
add(b);
}
}
@Override
protected void initGlobalToolbar() {
super.initGlobalToolbar();
getToolbar().setUIID("BlackToolbar");
}
void search(String s) {
}
}
CountryPickerForm
We need to override the toolbar initialization so we can set the proper BlackToolbar UIID
BlackToolbar
© Codename One 2017 all rights reserved
Speaking of the black toolbar it is predictably styled as black and opaque
BlackToolbar
© Codename One 2017 all rights reserved
We have a 1 millimeter padding which doesn’t exist in the default toolbar. It’s helpful for the collapse animation effect so padding still remains
BlackToolbar
© Codename One 2017 all rights reserved
The margin is 0 as usual
FlagsLetter
© Codename One 2017 all rights reserved
Flags letter is the letter that appears on top of every letter change between country names. The colors and the opacity are things I just picked from the screenshot image
FlagsLetter
© Codename One 2017 all rights reserved
The other aspects of this UI are derived from Label
public static void initBlackTitleForm(Form f, String title,
SuccessCallback<String> searchResults) {
Form backTo = getCurrentForm();
f.getContentPane().setScrollVisible(false);
Button back = new Button("", "TitleCommand");
back.addActionListener(e -> backTo.showBack());
back.getAllStyles().setFgColor(0xffffff);
FontImage.setMaterialIcon(back, FontImage.MATERIAL_ARROW_BACK);
Container searchBack = null;
if(searchResults != null) {
Button search = new Button("", "TitleCommand");
search.getAllStyles().setFgColor(0xffffff);
FontImage.setMaterialIcon(search, FontImage.MATERIAL_SEARCH);
search.addActionListener(e -> {
// TODO
});
searchBack = BorderLayout.north(
BorderLayout.centerEastWest(null, search, back));
} else {
searchBack = BorderLayout.north(
BorderLayout.centerEastWest(null, null, back));
initBlackTitleForm
The form with the black title requires some work which should be more "generic" as a black title area is used in several places within the Uber application.

For this purpose we have the CommonCode class which stores common static code in the application. This is a non-trivial task as the logic needs to support the
animated collapse of the title area as the user scrolls down.

The method accepts a callback for the case of a search operation, this isn't implemented yet but if it's null a search icon isn't added.
public static void initBlackTitleForm(Form f, String title,
SuccessCallback<String> searchResults) {
Form backTo = getCurrentForm();
f.getContentPane().setScrollVisible(false);
Button back = new Button("", "TitleCommand");
back.addActionListener(e -> backTo.showBack());
back.getAllStyles().setFgColor(0xffffff);
FontImage.setMaterialIcon(back, FontImage.MATERIAL_ARROW_BACK);
Container searchBack = null;
if(searchResults != null) {
Button search = new Button("", "TitleCommand");
search.getAllStyles().setFgColor(0xffffff);
FontImage.setMaterialIcon(search, FontImage.MATERIAL_SEARCH);
search.addActionListener(e -> {
// TODO
});
searchBack = BorderLayout.north(
BorderLayout.centerEastWest(null, search, back));
} else {
searchBack = BorderLayout.north(
BorderLayout.centerEastWest(null, null, back));
initBlackTitleForm
We add the back command as a button which allows us to place it above the title in a custom way and animate the position.

We can't use the TitleCommand UIID "as is" since it uses a black on white scheme in other forms. I could have used a different UIID here.
public static void initBlackTitleForm(Form f, String title,
SuccessCallback<String> searchResults) {
Form backTo = getCurrentForm();
f.getContentPane().setScrollVisible(false);
Button back = new Button("", "TitleCommand");
back.addActionListener(e -> backTo.showBack());
back.getAllStyles().setFgColor(0xffffff);
FontImage.setMaterialIcon(back, FontImage.MATERIAL_ARROW_BACK);
Container searchBack = null;
if(searchResults != null) {
Button search = new Button("", "TitleCommand");
search.getAllStyles().setFgColor(0xffffff);
FontImage.setMaterialIcon(search, FontImage.MATERIAL_SEARCH);
search.addActionListener(e -> {
// TODO
});
searchBack = BorderLayout.north(
BorderLayout.centerEastWest(null, search, back));
} else {
searchBack = BorderLayout.north(
BorderLayout.centerEastWest(null, null, back));
initBlackTitleForm
If we have a search callback I build the layout that includes the search button otherwise I create a layout without it
} else {
searchBack = BorderLayout.north(
BorderLayout.centerEastWest(null, null, back));
}
Label titleLabel = new Label(title, "WhiteOnBlackTitle");
titleLabel.getAllStyles().setMarginTop(back.getPreferredH());
titleLabel.getAllStyles().setMarginUnit(Style.UNIT_TYPE_PIXELS,
Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS);
f.getToolbar().setTitleComponent(
LayeredLayout.encloseIn(searchBack, titleLabel));
f.getAnimationManager().onTitleScrollAnimation(
titleLabel.createStyleAnimation("WhiteOnBlackTitleLeftMargin", 200));
f.setTransitionInAnimator(CommonTransitions.
createCover(CommonTransitions.SLIDE_VERTICAL, false, 300));
f.setTransitionOutAnimator(CommonTransitions.
createCover(CommonTransitions.SLIDE_VERTICAL, true, 300));
}
initBlackTitleForm
I place the title on top of the back button container using a layered layout. It doesn't seem to be on top because I've set the top margin so it resides below the back
arrow icon. I did this so I can animate the position of the label fluidly by changing the margin value
} else {
searchBack = BorderLayout.north(
BorderLayout.centerEastWest(null, null, back));
}
Label titleLabel = new Label(title, "WhiteOnBlackTitle");
titleLabel.getAllStyles().setMarginTop(back.getPreferredH());
titleLabel.getAllStyles().setMarginUnit(Style.UNIT_TYPE_PIXELS,
Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS);
f.getToolbar().setTitleComponent(
LayeredLayout.encloseIn(searchBack, titleLabel));
f.getAnimationManager().onTitleScrollAnimation(
titleLabel.createStyleAnimation("WhiteOnBlackTitleLeftMargin", 200));
f.setTransitionInAnimator(CommonTransitions.
createCover(CommonTransitions.SLIDE_VERTICAL, false, 300));
f.setTransitionOutAnimator(CommonTransitions.
createCover(CommonTransitions.SLIDE_VERTICAL, true, 300));
}
initBlackTitleForm
This one line allows the title to collapse into place next to the arrow, it translates the style of the title which currently has a large top margin to one without top margin and
with side margin. This means that the change in the style causes the title to move next to the back arrow
} else {
searchBack = BorderLayout.north(
BorderLayout.centerEastWest(null, null, back));
}
Label titleLabel = new Label(title, "WhiteOnBlackTitle");
titleLabel.getAllStyles().setMarginTop(back.getPreferredH());
titleLabel.getAllStyles().setMarginUnit(Style.UNIT_TYPE_PIXELS,
Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS);
f.getToolbar().setTitleComponent(
LayeredLayout.encloseIn(searchBack, titleLabel));
f.getAnimationManager().onTitleScrollAnimation(
titleLabel.createStyleAnimation("WhiteOnBlackTitleLeftMargin", 200));
f.setTransitionInAnimator(CommonTransitions.
createCover(CommonTransitions.SLIDE_VERTICAL, false, 300));
f.setTransitionOutAnimator(CommonTransitions.
createCover(CommonTransitions.SLIDE_VERTICAL, true, 300));
}
initBlackTitleForm
Cover transition is used in the back title forms on iOS, notice that cover transitions expect in and out values for cover and uncover
WhiteOnBlackTitle
© Codename One 2017 all rights reserved
The white on black title is a white title style and as the name suggests it has white foreground and a transparent background as the black portion comes from the black
toolbar UIID
WhiteOnBlackTitle
© Codename One 2017 all rights reserved
The padding is pretty standard, these numbers were picked to align properly with the commands both in expanded and collapsed states
WhiteOnBlackTitle
© Codename One 2017 all rights reserved
Margin is actually 0 as we change this manually in code, it might make sense to do the margin here for some cases.
WhiteOnBlackTitle
© Codename One 2017 all rights reserved
The font is standard light font but 4 millimeters in size which should appear bigger but not huge. Subtle.
WhiteOnBlackTitleLeftMargin
© Codename One 2017 all rights reserved
The left margin version of the style does define the side margin to leave room for the arrow. This means that the collapse animation will mutate into this UIID which has no
top margin so it will effectively align with the back arrow. However, the left margin will keep it from going on top of the arrow.
WhiteOnBlackTitleLeftMargin
© Codename One 2017 all rights reserved
It also evens out the padding so things look more aligned now that they are on the same row
WhiteOnBlackTitleLeftMargin
© Codename One 2017 all rights reserved
We derive the WhiteOnBlackTitle UIID so the settings we don’t override are identical
WhiteOnBlackTitleLeftMargin
© Codename One 2017 all rights reserved
The font is the same but a smaller 3 millimeter size, this will also animate as the title slides into place. It’s subtle but noticeable.

More Related Content

Similar to Creating an Uber Clone - Part V - Transcript.pdf

Creating a Facebook Clone - Part XVI.pdf
Creating a Facebook Clone - Part XVI.pdfCreating a Facebook Clone - Part XVI.pdf
Creating a Facebook Clone - Part XVI.pdf
ShaiAlmog1
 
Creating a Facebook Clone - Part XV - Transcript.pdf
Creating a Facebook Clone - Part XV - Transcript.pdfCreating a Facebook Clone - Part XV - Transcript.pdf
Creating a Facebook Clone - Part XV - Transcript.pdf
ShaiAlmog1
 
Creating an Uber - Part VI.pdf
Creating an Uber - Part VI.pdfCreating an Uber - Part VI.pdf
Creating an Uber - Part VI.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
 
Extracting ui Design - part 4 - transcript.pdf
Extracting ui Design - part 4 - transcript.pdfExtracting ui Design - part 4 - transcript.pdf
Extracting ui Design - part 4 - transcript.pdf
ShaiAlmog1
 
UI Design From Scratch - Part 5 - transcript.pdf
UI Design From Scratch - Part 5 - transcript.pdfUI Design From Scratch - Part 5 - transcript.pdf
UI Design From Scratch - Part 5 - transcript.pdf
ShaiAlmog1
 
Creating an Uber Clone - Part III - Transcript.pdf
Creating an Uber Clone - Part III - Transcript.pdfCreating an Uber Clone - Part III - Transcript.pdf
Creating an Uber Clone - Part III - Transcript.pdf
ShaiAlmog1
 
Creating a Facebook Clone - Part VIII - Transcript.pdf
Creating a Facebook Clone - Part VIII - Transcript.pdfCreating a Facebook Clone - Part VIII - Transcript.pdf
Creating a Facebook Clone - Part VIII - Transcript.pdf
ShaiAlmog1
 
Initial UI Mockup - Part 2.pdf
Initial UI Mockup - Part 2.pdfInitial UI Mockup - Part 2.pdf
Initial UI Mockup - Part 2.pdf
ShaiAlmog1
 
Creating a Facebook Clone - Part XVI - Transcript.pdf
Creating a Facebook Clone - Part XVI - Transcript.pdfCreating a Facebook Clone - Part XVI - Transcript.pdf
Creating a Facebook Clone - Part XVI - Transcript.pdf
ShaiAlmog1
 
Creating an Uber Clone - Part VIII - Transcript.pdf
Creating an Uber Clone - Part VIII - Transcript.pdfCreating an Uber Clone - Part VIII - Transcript.pdf
Creating an Uber Clone - Part VIII - Transcript.pdf
ShaiAlmog1
 
Creating a Facebook Clone - Part VIII.pdf
Creating a Facebook Clone - Part VIII.pdfCreating a Facebook Clone - Part VIII.pdf
Creating a Facebook Clone - Part VIII.pdf
ShaiAlmog1
 
Creating a Facebook Clone - Part IV.pdf
Creating a Facebook Clone - Part IV.pdfCreating a Facebook Clone - Part IV.pdf
Creating a Facebook Clone - Part IV.pdf
ShaiAlmog1
 
Immutability and Javascript - Nadia Miętkiewicz
Immutability and Javascript - Nadia MiętkiewiczImmutability and Javascript - Nadia Miętkiewicz
Immutability and Javascript - Nadia Miętkiewicz
Visuality
 
ch20.pptx
ch20.pptxch20.pptx
Why am I getting an out of memory error and no window of my .pdf
Why am I getting an out of memory error and no window of my .pdfWhy am I getting an out of memory error and no window of my .pdf
Why am I getting an out of memory error and no window of my .pdf
aakarcreations1
 
Creating a Facebook Clone - Part XLI.pdf
Creating a Facebook Clone - Part XLI.pdfCreating a Facebook Clone - Part XLI.pdf
Creating a Facebook Clone - Part XLI.pdf
ShaiAlmog1
 
Initial UI Mockup - Part 2 - Transcript.pdf
Initial UI Mockup - Part 2 - Transcript.pdfInitial UI Mockup - Part 2 - Transcript.pdf
Initial UI Mockup - Part 2 - Transcript.pdf
ShaiAlmog1
 
2. Section 2. Implementing functionality in the PersonEntry. (1.5 ma.pdf
2. Section 2. Implementing functionality in the PersonEntry. (1.5 ma.pdf2. Section 2. Implementing functionality in the PersonEntry. (1.5 ma.pdf
2. Section 2. Implementing functionality in the PersonEntry. (1.5 ma.pdf
allwayscollection
 
Creating an Uber Clone - Part XIX - Transcript.pdf
Creating an Uber Clone - Part XIX - Transcript.pdfCreating an Uber Clone - Part XIX - Transcript.pdf
Creating an Uber Clone - Part XIX - Transcript.pdf
ShaiAlmog1
 

Similar to Creating an Uber Clone - Part V - Transcript.pdf (20)

Creating a Facebook Clone - Part XVI.pdf
Creating a Facebook Clone - Part XVI.pdfCreating a Facebook Clone - Part XVI.pdf
Creating a Facebook Clone - Part XVI.pdf
 
Creating a Facebook Clone - Part XV - Transcript.pdf
Creating a Facebook Clone - Part XV - Transcript.pdfCreating a Facebook Clone - Part XV - Transcript.pdf
Creating a Facebook Clone - Part XV - Transcript.pdf
 
Creating an Uber - Part VI.pdf
Creating an Uber - Part VI.pdfCreating an Uber - Part VI.pdf
Creating an Uber - Part VI.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
 
Extracting ui Design - part 4 - transcript.pdf
Extracting ui Design - part 4 - transcript.pdfExtracting ui Design - part 4 - transcript.pdf
Extracting ui Design - part 4 - transcript.pdf
 
UI Design From Scratch - Part 5 - transcript.pdf
UI Design From Scratch - Part 5 - transcript.pdfUI Design From Scratch - Part 5 - transcript.pdf
UI Design From Scratch - Part 5 - transcript.pdf
 
Creating an Uber Clone - Part III - Transcript.pdf
Creating an Uber Clone - Part III - Transcript.pdfCreating an Uber Clone - Part III - Transcript.pdf
Creating an Uber Clone - Part III - Transcript.pdf
 
Creating a Facebook Clone - Part VIII - Transcript.pdf
Creating a Facebook Clone - Part VIII - Transcript.pdfCreating a Facebook Clone - Part VIII - Transcript.pdf
Creating a Facebook Clone - Part VIII - Transcript.pdf
 
Initial UI Mockup - Part 2.pdf
Initial UI Mockup - Part 2.pdfInitial UI Mockup - Part 2.pdf
Initial UI Mockup - Part 2.pdf
 
Creating a Facebook Clone - Part XVI - Transcript.pdf
Creating a Facebook Clone - Part XVI - Transcript.pdfCreating a Facebook Clone - Part XVI - Transcript.pdf
Creating a Facebook Clone - Part XVI - Transcript.pdf
 
Creating an Uber Clone - Part VIII - Transcript.pdf
Creating an Uber Clone - Part VIII - Transcript.pdfCreating an Uber Clone - Part VIII - Transcript.pdf
Creating an Uber Clone - Part VIII - Transcript.pdf
 
Creating a Facebook Clone - Part VIII.pdf
Creating a Facebook Clone - Part VIII.pdfCreating a Facebook Clone - Part VIII.pdf
Creating a Facebook Clone - Part VIII.pdf
 
Creating a Facebook Clone - Part IV.pdf
Creating a Facebook Clone - Part IV.pdfCreating a Facebook Clone - Part IV.pdf
Creating a Facebook Clone - Part IV.pdf
 
Immutability and Javascript - Nadia Miętkiewicz
Immutability and Javascript - Nadia MiętkiewiczImmutability and Javascript - Nadia Miętkiewicz
Immutability and Javascript - Nadia Miętkiewicz
 
ch20.pptx
ch20.pptxch20.pptx
ch20.pptx
 
Why am I getting an out of memory error and no window of my .pdf
Why am I getting an out of memory error and no window of my .pdfWhy am I getting an out of memory error and no window of my .pdf
Why am I getting an out of memory error and no window of my .pdf
 
Creating a Facebook Clone - Part XLI.pdf
Creating a Facebook Clone - Part XLI.pdfCreating a Facebook Clone - Part XLI.pdf
Creating a Facebook Clone - Part XLI.pdf
 
Initial UI Mockup - Part 2 - Transcript.pdf
Initial UI Mockup - Part 2 - Transcript.pdfInitial UI Mockup - Part 2 - Transcript.pdf
Initial UI Mockup - Part 2 - Transcript.pdf
 
2. Section 2. Implementing functionality in the PersonEntry. (1.5 ma.pdf
2. Section 2. Implementing functionality in the PersonEntry. (1.5 ma.pdf2. Section 2. Implementing functionality in the PersonEntry. (1.5 ma.pdf
2. Section 2. Implementing functionality in the PersonEntry. (1.5 ma.pdf
 
Creating an Uber Clone - Part XIX - Transcript.pdf
Creating an Uber Clone - Part XIX - Transcript.pdfCreating an Uber Clone - Part XIX - Transcript.pdf
Creating an Uber Clone - Part XIX - Transcript.pdf
 

More from ShaiAlmog1

The Duck Teaches Learn to debug from the masters. Local to production- kill ...
The Duck Teaches  Learn to debug from the masters. Local to production- kill ...The Duck Teaches  Learn to debug from the masters. Local to production- kill ...
The Duck Teaches Learn to debug from the masters. Local to production- kill ...
ShaiAlmog1
 
create-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdfcreate-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdf
ShaiAlmog1
 
create-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdfcreate-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfcreate-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfcreate-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfcreate-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdf
ShaiAlmog1
 
create-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdfcreate-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdf
ShaiAlmog1
 
create-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfcreate-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdf
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 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
 

More from ShaiAlmog1 (20)

The Duck Teaches Learn to debug from the masters. Local to production- kill ...
The Duck Teaches  Learn to debug from the masters. Local to production- kill ...The Duck Teaches  Learn to debug from the masters. Local to production- kill ...
The Duck Teaches Learn to debug from the masters. Local to production- kill ...
 
create-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdfcreate-netflix-clone-06-client-ui.pdf
create-netflix-clone-06-client-ui.pdf
 
create-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdfcreate-netflix-clone-01-introduction_transcript.pdf
create-netflix-clone-01-introduction_transcript.pdf
 
create-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdfcreate-netflix-clone-02-server_transcript.pdf
create-netflix-clone-02-server_transcript.pdf
 
create-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdfcreate-netflix-clone-04-server-continued_transcript.pdf
create-netflix-clone-04-server-continued_transcript.pdf
 
create-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfcreate-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdf
 
create-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdfcreate-netflix-clone-06-client-ui_transcript.pdf
create-netflix-clone-06-client-ui_transcript.pdf
 
create-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfcreate-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdf
 
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 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
 

Recently uploaded

20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
Matthew Sinclair
 
“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”
Claudio Di Ciccio
 
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial IntelligenceAI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
IndexBug
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
mikeeftimakis1
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
Matthew Sinclair
 
HCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAUHCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAU
panagenda
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
Uni Systems S.M.S.A.
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Malak Abu Hammad
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
Neo4j
 
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with SlackLet's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
shyamraj55
 
Infrastructure Challenges in Scaling RAG with Custom AI models
Infrastructure Challenges in Scaling RAG with Custom AI modelsInfrastructure Challenges in Scaling RAG with Custom AI models
Infrastructure Challenges in Scaling RAG with Custom AI models
Zilliz
 
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Speck&Tech
 
Presentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of GermanyPresentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of Germany
innovationoecd
 
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAUHCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
panagenda
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
SOFTTECHHUB
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
名前 です男
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
Aftab Hussain
 
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
Neo4j
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
Neo4j
 
GraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracyGraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracy
Tomaz Bratanic
 

Recently uploaded (20)

20240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 202420240607 QFM018 Elixir Reading List May 2024
20240607 QFM018 Elixir Reading List May 2024
 
“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”
 
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial IntelligenceAI 101: An Introduction to the Basics and Impact of Artificial Intelligence
AI 101: An Introduction to the Basics and Impact of Artificial Intelligence
 
Introduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - CybersecurityIntroduction to CHERI technology - Cybersecurity
Introduction to CHERI technology - Cybersecurity
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
 
HCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAUHCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAU
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
 
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdfUnlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
Unlock the Future of Search with MongoDB Atlas_ Vector Search Unleashed.pdf
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
 
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with SlackLet's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
 
Infrastructure Challenges in Scaling RAG with Custom AI models
Infrastructure Challenges in Scaling RAG with Custom AI modelsInfrastructure Challenges in Scaling RAG with Custom AI models
Infrastructure Challenges in Scaling RAG with Custom AI models
 
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
 
Presentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of GermanyPresentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of Germany
 
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAUHCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
 
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
みなさんこんにちはこれ何文字まで入るの?40文字以下不可とか本当に意味わからないけどこれ限界文字数書いてないからマジでやばい文字数いけるんじゃないの?えこ...
 
Removing Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software FuzzingRemoving Uninteresting Bytes in Software Fuzzing
Removing Uninteresting Bytes in Software Fuzzing
 
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
 
GraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracyGraphRAG for Life Science to increase LLM accuracy
GraphRAG for Life Science to increase LLM accuracy
 

Creating an Uber Clone - Part V - Transcript.pdf

  • 1. Creating an Uber Clone - Part V In this part we’ll finally leave the confines of the login form and move to the simpler forms of social login and the country picker UI. I’ll start with the social login mockup since it’s so small and simple
  • 2. Social Login © Codename One 2017 all rights reserved This is the form you see when you choose the social login option, I cropped the bottom as it’s just white. This is a pretty trivial UI…
  • 3. public class FacebookOrGoogleLoginForm extends Form { public FacebookOrGoogleLoginForm() { super(BoxLayout.y()); Form previous = getCurrentForm(); getToolbar().setBackCommand("", Toolbar.BackCommandPolicy.AS_ARROW, e -> previous.showBack()); add(new Label("Choose an account", "FlagButton")); Button facebook = new Button("Facebook", Resources.getGlobalResources().getImage("facebook.png"), "FlagButton"); Button google = new Button("Google", Resources.getGlobalResources().getImage("google.png"), “FlagButton"); add(facebook).add(google); } } FacebookOrGoogleLoginForm There isn’t that much to say about this form, it’s trivial. We use two icons for Facebook and Google and define the back arrow. Thanks to all the theming work we did up to this point everything “just works” and looks like the Uber app. We do need to define the FlagButton through as it’s a UIID that I reuse in several forms. It got the name from the countries picker form which we’ll go into next.
  • 4. FlagButton © Codename One 2017 all rights reserved The flag button is just a label in terms of padding etc.
  • 5. FlagButton © Codename One 2017 all rights reserved It has a subtly larger font at 3.2 millimeters not much larger
  • 6. Country Picker © Codename One 2017 all rights reserved The country picker form lists the countries next to their flags. The first letter of the country name is highlighted between the countries and when you scroll down the title area collapses to make more room. It does that with a smooth animation effect. Speaking of the title area it’s while on black instead of black on white… We reach this form when we click the Country Picker button but that only happens in the phone number entry form which we will discuss shortly.
  • 7. public class CountryPickerForm extends Form { public CountryPickerForm(Button sourceButton, Resources flags) { super(BoxLayout.y()); CommonCode.initBlackTitleForm(this, "Select a Country", val -> search(val)); Image blankIcon = Image.createImage(100, 70, 0); char lastChar = (char)-1; for(int iter = 0 ; iter < ActivationForm.COUNTRY_CODES.length ; iter++) { Button b = new Button(ActivationForm.COUNTRY_NAMES[iter], "FlagButton"); char current = b.getText().charAt(0); if(current != lastChar) { lastChar = current; Label l = new Label("" + lastChar, "FlagsLetter"); add(l); } b.setIcon(flags.getImage(ActivationForm.COUNTRY_FLAGS[iter])); if(b.getIcon() == null) { b.setIcon(blankIcon); } String currentCountryCode = ActivationForm.COUNTRY_CODES[iter]; b.addActionListener(ee -> { sourceButton.setIcon(b.getIcon()); sourceButton.setText("+" + currentCountryCode); CountryPickerForm Let’s jump right into the code. Predictably the form is a BoxLayout container on the Y axis. The initBlackTitleForm method is a static method in a common utility class. We'll cover it soon
  • 8. public class CountryPickerForm extends Form { public CountryPickerForm(Button sourceButton, Resources flags) { super(BoxLayout.y()); CommonCode.initBlackTitleForm(this, "Select a Country", val -> search(val)); Image blankIcon = Image.createImage(100, 70, 0); char lastChar = (char)-1; for(int iter = 0 ; iter < ActivationForm.COUNTRY_CODES.length ; iter++) { Button b = new Button(ActivationForm.COUNTRY_NAMES[iter], "FlagButton"); char current = b.getText().charAt(0); if(current != lastChar) { lastChar = current; Label l = new Label("" + lastChar, "FlagsLetter"); add(l); } b.setIcon(flags.getImage(ActivationForm.COUNTRY_FLAGS[iter])); if(b.getIcon() == null) { b.setIcon(blankIcon); } String currentCountryCode = ActivationForm.COUNTRY_CODES[iter]; b.addActionListener(ee -> { sourceButton.setIcon(b.getIcon()); sourceButton.setText("+" + currentCountryCode); CountryPickerForm We don't have flags for all the countries so we need a blank space icon so the elements align
  • 9. public class CountryPickerForm extends Form { public CountryPickerForm(Button sourceButton, Resources flags) { super(BoxLayout.y()); CommonCode.initBlackTitleForm(this, "Select a Country", val -> search(val)); Image blankIcon = Image.createImage(100, 70, 0); char lastChar = (char)-1; for(int iter = 0 ; iter < ActivationForm.COUNTRY_CODES.length ; iter++) { Button b = new Button(ActivationForm.COUNTRY_NAMES[iter], "FlagButton"); char current = b.getText().charAt(0); if(current != lastChar) { lastChar = current; Label l = new Label("" + lastChar, "FlagsLetter"); add(l); } b.setIcon(flags.getImage(ActivationForm.COUNTRY_FLAGS[iter])); if(b.getIcon() == null) { b.setIcon(blankIcon); } String currentCountryCode = ActivationForm.COUNTRY_CODES[iter]; b.addActionListener(ee -> { sourceButton.setIcon(b.getIcon()); sourceButton.setText("+" + currentCountryCode); CountryPickerForm Here we loop over all the country codes and create a button with the FlagsLetter UIID for every entry. We also need to implement the alphabet letter headers, every time the first character of a country changes we add a label representing the entry
  • 10. public class CountryPickerForm extends Form { public CountryPickerForm(Button sourceButton, Resources flags) { super(BoxLayout.y()); CommonCode.initBlackTitleForm(this, "Select a Country", val -> search(val)); Image blankIcon = Image.createImage(100, 70, 0); char lastChar = (char)-1; for(int iter = 0 ; iter < ActivationForm.COUNTRY_CODES.length ; iter++) { Button b = new Button(ActivationForm.COUNTRY_NAMES[iter], "FlagButton"); char current = b.getText().charAt(0); if(current != lastChar) { lastChar = current; Label l = new Label("" + lastChar, "FlagsLetter"); add(l); } b.setIcon(flags.getImage(ActivationForm.COUNTRY_FLAGS[iter])); if(b.getIcon() == null) { b.setIcon(blankIcon); } String currentCountryCode = ActivationForm.COUNTRY_CODES[iter]; b.addActionListener(ee -> { sourceButton.setIcon(b.getIcon()); sourceButton.setText("+" + currentCountryCode); CountryPickerForm When an entry is selected we update the text and icon of the CountryCodePicker Button that launched this form
  • 11. b.setIcon(flags.getImage(ActivationForm.COUNTRY_FLAGS[iter])); if(b.getIcon() == null) { b.setIcon(blankIcon); } String currentCountryCode = ActivationForm.COUNTRY_CODES[iter]; b.addActionListener(ee -> { sourceButton.setIcon(b.getIcon()); sourceButton.setText("+" + currentCountryCode); }); add(b); } } @Override protected void initGlobalToolbar() { super.initGlobalToolbar(); getToolbar().setUIID("BlackToolbar"); } void search(String s) { } } CountryPickerForm We need to override the toolbar initialization so we can set the proper BlackToolbar UIID
  • 12. BlackToolbar © Codename One 2017 all rights reserved Speaking of the black toolbar it is predictably styled as black and opaque
  • 13. BlackToolbar © Codename One 2017 all rights reserved We have a 1 millimeter padding which doesn’t exist in the default toolbar. It’s helpful for the collapse animation effect so padding still remains
  • 14. BlackToolbar © Codename One 2017 all rights reserved The margin is 0 as usual
  • 15. FlagsLetter © Codename One 2017 all rights reserved Flags letter is the letter that appears on top of every letter change between country names. The colors and the opacity are things I just picked from the screenshot image
  • 16. FlagsLetter © Codename One 2017 all rights reserved The other aspects of this UI are derived from Label
  • 17. public static void initBlackTitleForm(Form f, String title, SuccessCallback<String> searchResults) { Form backTo = getCurrentForm(); f.getContentPane().setScrollVisible(false); Button back = new Button("", "TitleCommand"); back.addActionListener(e -> backTo.showBack()); back.getAllStyles().setFgColor(0xffffff); FontImage.setMaterialIcon(back, FontImage.MATERIAL_ARROW_BACK); Container searchBack = null; if(searchResults != null) { Button search = new Button("", "TitleCommand"); search.getAllStyles().setFgColor(0xffffff); FontImage.setMaterialIcon(search, FontImage.MATERIAL_SEARCH); search.addActionListener(e -> { // TODO }); searchBack = BorderLayout.north( BorderLayout.centerEastWest(null, search, back)); } else { searchBack = BorderLayout.north( BorderLayout.centerEastWest(null, null, back)); initBlackTitleForm The form with the black title requires some work which should be more "generic" as a black title area is used in several places within the Uber application. For this purpose we have the CommonCode class which stores common static code in the application. This is a non-trivial task as the logic needs to support the animated collapse of the title area as the user scrolls down. The method accepts a callback for the case of a search operation, this isn't implemented yet but if it's null a search icon isn't added.
  • 18. public static void initBlackTitleForm(Form f, String title, SuccessCallback<String> searchResults) { Form backTo = getCurrentForm(); f.getContentPane().setScrollVisible(false); Button back = new Button("", "TitleCommand"); back.addActionListener(e -> backTo.showBack()); back.getAllStyles().setFgColor(0xffffff); FontImage.setMaterialIcon(back, FontImage.MATERIAL_ARROW_BACK); Container searchBack = null; if(searchResults != null) { Button search = new Button("", "TitleCommand"); search.getAllStyles().setFgColor(0xffffff); FontImage.setMaterialIcon(search, FontImage.MATERIAL_SEARCH); search.addActionListener(e -> { // TODO }); searchBack = BorderLayout.north( BorderLayout.centerEastWest(null, search, back)); } else { searchBack = BorderLayout.north( BorderLayout.centerEastWest(null, null, back)); initBlackTitleForm We add the back command as a button which allows us to place it above the title in a custom way and animate the position. We can't use the TitleCommand UIID "as is" since it uses a black on white scheme in other forms. I could have used a different UIID here.
  • 19. public static void initBlackTitleForm(Form f, String title, SuccessCallback<String> searchResults) { Form backTo = getCurrentForm(); f.getContentPane().setScrollVisible(false); Button back = new Button("", "TitleCommand"); back.addActionListener(e -> backTo.showBack()); back.getAllStyles().setFgColor(0xffffff); FontImage.setMaterialIcon(back, FontImage.MATERIAL_ARROW_BACK); Container searchBack = null; if(searchResults != null) { Button search = new Button("", "TitleCommand"); search.getAllStyles().setFgColor(0xffffff); FontImage.setMaterialIcon(search, FontImage.MATERIAL_SEARCH); search.addActionListener(e -> { // TODO }); searchBack = BorderLayout.north( BorderLayout.centerEastWest(null, search, back)); } else { searchBack = BorderLayout.north( BorderLayout.centerEastWest(null, null, back)); initBlackTitleForm If we have a search callback I build the layout that includes the search button otherwise I create a layout without it
  • 20. } else { searchBack = BorderLayout.north( BorderLayout.centerEastWest(null, null, back)); } Label titleLabel = new Label(title, "WhiteOnBlackTitle"); titleLabel.getAllStyles().setMarginTop(back.getPreferredH()); titleLabel.getAllStyles().setMarginUnit(Style.UNIT_TYPE_PIXELS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS); f.getToolbar().setTitleComponent( LayeredLayout.encloseIn(searchBack, titleLabel)); f.getAnimationManager().onTitleScrollAnimation( titleLabel.createStyleAnimation("WhiteOnBlackTitleLeftMargin", 200)); f.setTransitionInAnimator(CommonTransitions. createCover(CommonTransitions.SLIDE_VERTICAL, false, 300)); f.setTransitionOutAnimator(CommonTransitions. createCover(CommonTransitions.SLIDE_VERTICAL, true, 300)); } initBlackTitleForm I place the title on top of the back button container using a layered layout. It doesn't seem to be on top because I've set the top margin so it resides below the back arrow icon. I did this so I can animate the position of the label fluidly by changing the margin value
  • 21. } else { searchBack = BorderLayout.north( BorderLayout.centerEastWest(null, null, back)); } Label titleLabel = new Label(title, "WhiteOnBlackTitle"); titleLabel.getAllStyles().setMarginTop(back.getPreferredH()); titleLabel.getAllStyles().setMarginUnit(Style.UNIT_TYPE_PIXELS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS); f.getToolbar().setTitleComponent( LayeredLayout.encloseIn(searchBack, titleLabel)); f.getAnimationManager().onTitleScrollAnimation( titleLabel.createStyleAnimation("WhiteOnBlackTitleLeftMargin", 200)); f.setTransitionInAnimator(CommonTransitions. createCover(CommonTransitions.SLIDE_VERTICAL, false, 300)); f.setTransitionOutAnimator(CommonTransitions. createCover(CommonTransitions.SLIDE_VERTICAL, true, 300)); } initBlackTitleForm This one line allows the title to collapse into place next to the arrow, it translates the style of the title which currently has a large top margin to one without top margin and with side margin. This means that the change in the style causes the title to move next to the back arrow
  • 22. } else { searchBack = BorderLayout.north( BorderLayout.centerEastWest(null, null, back)); } Label titleLabel = new Label(title, "WhiteOnBlackTitle"); titleLabel.getAllStyles().setMarginTop(back.getPreferredH()); titleLabel.getAllStyles().setMarginUnit(Style.UNIT_TYPE_PIXELS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS, Style.UNIT_TYPE_DIPS); f.getToolbar().setTitleComponent( LayeredLayout.encloseIn(searchBack, titleLabel)); f.getAnimationManager().onTitleScrollAnimation( titleLabel.createStyleAnimation("WhiteOnBlackTitleLeftMargin", 200)); f.setTransitionInAnimator(CommonTransitions. createCover(CommonTransitions.SLIDE_VERTICAL, false, 300)); f.setTransitionOutAnimator(CommonTransitions. createCover(CommonTransitions.SLIDE_VERTICAL, true, 300)); } initBlackTitleForm Cover transition is used in the back title forms on iOS, notice that cover transitions expect in and out values for cover and uncover
  • 23. WhiteOnBlackTitle © Codename One 2017 all rights reserved The white on black title is a white title style and as the name suggests it has white foreground and a transparent background as the black portion comes from the black toolbar UIID
  • 24. WhiteOnBlackTitle © Codename One 2017 all rights reserved The padding is pretty standard, these numbers were picked to align properly with the commands both in expanded and collapsed states
  • 25. WhiteOnBlackTitle © Codename One 2017 all rights reserved Margin is actually 0 as we change this manually in code, it might make sense to do the margin here for some cases.
  • 26. WhiteOnBlackTitle © Codename One 2017 all rights reserved The font is standard light font but 4 millimeters in size which should appear bigger but not huge. Subtle.
  • 27. WhiteOnBlackTitleLeftMargin © Codename One 2017 all rights reserved The left margin version of the style does define the side margin to leave room for the arrow. This means that the collapse animation will mutate into this UIID which has no top margin so it will effectively align with the back arrow. However, the left margin will keep it from going on top of the arrow.
  • 28. WhiteOnBlackTitleLeftMargin © Codename One 2017 all rights reserved It also evens out the padding so things look more aligned now that they are on the same row
  • 29. WhiteOnBlackTitleLeftMargin © Codename One 2017 all rights reserved We derive the WhiteOnBlackTitle UIID so the settings we don’t override are identical
  • 30. WhiteOnBlackTitleLeftMargin © Codename One 2017 all rights reserved The font is the same but a smaller 3 millimeter size, this will also animate as the title slides into place. It’s subtle but noticeable.