SlideShare a Scribd company logo
1 of 22
Download to read offline
Creating an Uber Clone - Part XXII
With that out of the way search should work but how does it display the result?

For that we need to add additional features to the MapForm that address these capabilities. Before we go into that lets check out what that means
Routes
© Codename One 2017 all rights reserved
The ride booking UI plots the path of the ride on the map and includes two tags one pointing at your current location and one on the destination. The first tag is divided to
a "time indication" and name. The latter only contains the name. Notice that the elements have a rounded rectangle shape with a pointy end on one side to point at the
position within the path.
private Component createNavigationTag(String location, int durationMinutes) {
Label locationLabel = new Label(location, "NavigationLabel");
if(durationMinutes > 0) {
Label duration = new Label("" + durationMinutes,
"NavigationMinuteLabel");
Label min = new Label("MIN", "NavigationMinuteDescLabel");
Container west = BoxLayout.encloseY(duration, min);
Container result = BorderLayout.centerEastWest(locationLabel,
null, west);
result.getUnselectedStyle().setBorder(BlackAndWhiteBorder.create().
blackLinePosition(west.getPreferredW()));
return result;
}
locationLabel.getUnselectedStyle().setBorder(
BlackAndWhiteBorder.create());
return locationLabel;
}
addMapListener
Lets start with creating these tags. The tag code itself is trivial it's just a Label or a Container with some details. Nothing special.

Except for one important detail, the BlackAndWhiteBorder. In order to implement the unique shape of the tag I created a new Border class. Notice I used the preferred
width of the west component to determine the black section. This is done in the blackLinePosition method.

Before we go any further I’d just like to make one point clear: I Would have Used a 9-piece Border. If this were a real application I would have just cut a 9-piece border
and moved on. However, since the point is teaching I chose to do this the "hard way"
NavigationLabel
© Codename One 2017 all rights reserved
Before we get into the BlackAndWhiteBorder there are a few UIID's we need to define.

The NavigationLabel UIID is a the black on white label that appears in the tag.
NavigationLabel
© Codename One 2017 all rights reserved
The only unique thing about it is the relatively small amount of padding so the tag doesn’t take up too much space
NavigationLabel
© Codename One 2017 all rights reserved
The margin is predictably zero
NavigationLabel
© Codename One 2017 all rights reserved
And the font is slightly smaller than usual
NavigationMinuteLabel
© Codename One 2017 all rights reserved
The NavigationMinuteLabel UIID is the white on black minute value.
NavigationMinuteLabel
© Codename One 2017 all rights reserved
It’s center aligned
NavigationMinuteLabel
© Codename One 2017 all rights reserved
It has 0 padding below to keep the text and number close together but has similar paddings on the other sides to match the NavigationLabel
NavigationMinuteLabel
© Codename One 2017 all rights reserved
It has zero margin
NavigationMinuteLabel
© Codename One 2017 all rights reserved
and it has a smaller font size than usual although not a tiny font
NavigationMinuteDescLabel
© Codename One 2017 all rights reserved
The NavigationMinuteDescLabel UIID is used for the text below that. The text with the word “MIN”. It derives from NavigationMinuteLabel
NavigationMinuteDescLabel
© Codename One 2017 all rights reserved
And has an even smaller font than that…
public class BlackAndWhiteBorder extends Border {
private static final String CACHE_KEY = "cn1$$-bwcache";
private final float shadowBlur = 10;
private final float shadowSpread;
private final int shadowOpacity = 110;
private final float cornerRadius = 1f;
private int blackLinePosition = -1;
BlackAndWhiteBorder() {
shadowSpread = Display.getInstance().convertToPixels(0.2f);
}
public static BlackAndWhiteBorder create() {
return new BlackAndWhiteBorder();
}
public BlackAndWhiteBorder blackLinePosition(int blackLinePosition) {
this.blackLinePosition = blackLinePosition;
return this;
}
private Image createTargetImage(Component c, int w, int h, boolean fast) {
Image target = Image.createImage(w, h, 0);
int shapeX = 0;
int shapeY = 0;
int shapeW = w;
int shapeH = h;
BlackAndWhiteBorder
Now that these are out of the way let's take a look at the border. Notice we can just subclass the Border class just like we can implement painters etc. This provides a
similar path for customization but is sometimes more flexible. Most of this code is based on the builtin RoundRectBorder class.

Drawing this type of border is pretty expensive so we draw onto an image and place that image in cache within the component using putClientProperty we use this value
as the key
public class BlackAndWhiteBorder extends Border {
private static final String CACHE_KEY = "cn1$$-bwcache";
private final float shadowBlur = 10;
private final float shadowSpread;
private final int shadowOpacity = 110;
private final float cornerRadius = 1f;
private int blackLinePosition = -1;
BlackAndWhiteBorder() {
shadowSpread = Display.getInstance().convertToPixels(0.2f);
}
public static BlackAndWhiteBorder create() {
return new BlackAndWhiteBorder();
}
public BlackAndWhiteBorder blackLinePosition(int blackLinePosition) {
this.blackLinePosition = blackLinePosition;
return this;
}
private Image createTargetImage(Component c, int w, int h, boolean fast) {
Image target = Image.createImage(w, h, 0);
int shapeX = 0;
int shapeY = 0;
int shapeW = w;
int shapeH = h;
BlackAndWhiteBorder
The blackLinePosition is used in the version of this border that's partially black
private Image createTargetImage(Component c, int w, int h, boolean fast) {
Image target = Image.createImage(w, h, 0);
int shapeX = 0;
int shapeY = 0;
int shapeW = w;
int shapeH = h;
Graphics tg = target.getGraphics();
tg.setAntiAliased(true);
int shadowSpreadL = Display.getInstance().convertToPixels(shadowSpread);
shapeW -= shadowSpreadL;
shapeH -= shadowSpreadL;
shapeX += Math.round(((float)shadowSpreadL) * 0.9);
shapeY += Math.round(((float)shadowSpreadL) * 0.9);
for(int iter = shadowSpreadL - 1 ; iter >= 0 ; iter--) {
tg.translate(iter, iter);
fillShape(tg, 0, shadowOpacity / shadowSpreadL, w-(iter*2),h - (iter * 2));
tg.translate(-iter, -iter);
}
if(Display.getInstance().isGaussianBlurSupported() && !fast) {
Image blured = Display.getInstance().gaussianBlurImage(target,shadowBlur/2);
target = Image.createImage(w, h, 0);
tg = target.getGraphics();
tg.drawImage(blured, 0, 0);
BlackAndWhiteBorder
Here we create the border image that we will cache for the given component. Since a shadow is set on the border and that can take some processing power. To speed
this up we have two versions of the method fast and slow. We call the fast one and invoke the slow one asynchronously to update the border
private Image createTargetImage(Component c, int w, int h, boolean fast) {
Image target = Image.createImage(w, h, 0);
int shapeX = 0;
int shapeY = 0;
int shapeW = w;
int shapeH = h;
Graphics tg = target.getGraphics();
tg.setAntiAliased(true);
int shadowSpreadL = Display.getInstance().convertToPixels(shadowSpread);
shapeW -= shadowSpreadL;
shapeH -= shadowSpreadL;
shapeX += Math.round(((float)shadowSpreadL) * 0.9);
shapeY += Math.round(((float)shadowSpreadL) * 0.9);
for(int iter = shadowSpreadL - 1 ; iter >= 0 ; iter--) {
tg.translate(iter, iter);
fillShape(tg, 0, shadowOpacity / shadowSpreadL, w-(iter*2),h - (iter * 2));
tg.translate(-iter, -iter);
}
if(Display.getInstance().isGaussianBlurSupported() && !fast) {
Image blured = Display.getInstance().gaussianBlurImage(target,shadowBlur/2);
target = Image.createImage(w, h, 0);
tg = target.getGraphics();
tg.drawImage(blured, 0, 0);
BlackAndWhiteBorder
We do a shadow effect by drawing a gradient with varying alpha degrees then blurring that out
tg.drawImage(blured, 0, 0);
tg.setAntiAliased(true);
}
tg.translate(shapeX, shapeY);
c.getStyle().setBorder(Border.createEmpty());
GeneralPath gp = createShape(shapeW, shapeH);
tg.setClip(gp);
c.getStyle().getBgPainter().paint(tg, new Rectangle(0, 0, w, h));
c.getStyle().setBorder(this);
return target;
}
public void paintBorderBackground(Graphics g, final Component c) {
final int w = c.getWidth();
final int h = c.getHeight();
int x = c.getX();
int y = c.getY();
if(w > 0 && h > 0) {
Image background = (Image)c.getClientProperty(CACHE_KEY);
if(background!=null && background.getWidth()==w && background.getHeight()==h){
g.drawImage(background, x, y);
return;
}
BlackAndWhiteBorder
If we have a cached version of the border image we will just use that as the background of the component assuming the size of the component didn't change
int y = c.getY();
if(w > 0 && h > 0) {
Image background = (Image)c.getClientProperty(CACHE_KEY);
if(background!=null && background.getWidth()==w && background.getHeight()==h){
g.drawImage(background, x, y);
return;
}
} else {
return;
}
Image target = createTargetImage(c, w, h, true);
g.drawImage(target, x, y);
c.putClientProperty(CACHE_KEY, target);
Display.getInstance().callSeriallyOnIdle(new Runnable() {
public void run() {
if(w == c.getWidth() && h == c.getHeight()) {
Image target = createTargetImage(c, w, h, false);
c.putClientProperty(CACHE_KEY, target);
c.repaint();
}
}
BlackAndWhiteBorder
Otherwise we create that image and update it later with the slower version that includes the gradient shadow effect
c.putClientProperty(CACHE_KEY, target);
c.repaint();
}
}
});
}
private GeneralPath createShape(int shapeW, int shapeH) {
GeneralPath gp = new GeneralPath();
float radius = Display.getInstance().convertToPixels(cornerRadius);
float x = 0;
float y = 0;
float widthF = shapeW;
float heightF = shapeH;
gp.moveTo(x + radius, y);
if(blackLinePosition > -1) {
gp.lineTo(x + widthF, y);
} else {
gp.lineTo(x + widthF - radius, y);
gp.quadTo(x + widthF, y, x + widthF, y + radius);
}
gp.lineTo(x + widthF, y + heightF - radius);
gp.quadTo(x + widthF, y + heightF, x + widthF - radius, y + heightF);
if(blackLinePosition > -1) {
BlackAndWhiteBorder
We create the shape of the component. If it's the one with the black line we place the corner in the top right otherwise we place it in the bottom left
gp.quadTo(x + widthF, y + heightF, x + widthF - radius, y + heightF);
if(blackLinePosition > -1) {
gp.lineTo(x + radius, y + heightF);
gp.quadTo(x, y + heightF, x, y + heightF - radius);
} else {
gp.lineTo(x, y + heightF);
}
gp.lineTo(x, y + radius);
gp.quadTo(x, y, x + radius, y);
gp.closePath();
return gp;
}
public int getMinimumHeight() {
return convertToPixels(shadowSpread) + convertToPixels(cornerRadius) * 2;
}
public int getMinimumWidth() {
return convertToPixels(shadowSpread) + convertToPixels(cornerRadius) * 2;
}
private void fillShape(Graphics g, int color, int opacity, int width, int height) {
g.setColor(0xffffff);
g.setAlpha(255);
GeneralPath gp = createShape(width, height);
if(blackLinePosition > -1) {
BlackAndWhiteBorder
We can now fill out the shape as part of the image creation code if we have a black line we do the fill operation twice with different clip sizes to create that effect

More Related Content

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

Leaving Flatland: getting started with WebGL
Leaving Flatland: getting started with WebGLLeaving Flatland: getting started with WebGL
Leaving Flatland: getting started with WebGLgerbille
 
Maps - Part 3 - Transcript.pdf
Maps - Part 3 - Transcript.pdfMaps - Part 3 - Transcript.pdf
Maps - Part 3 - Transcript.pdfShaiAlmog1
 
Trident International Graphics Workshop 2014 5/5
Trident International Graphics Workshop 2014 5/5Trident International Graphics Workshop 2014 5/5
Trident International Graphics Workshop 2014 5/5Takao Wada
 
C Graphics Functions
C Graphics FunctionsC Graphics Functions
C Graphics FunctionsSHAKOOR AB
 
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.pdfShaiAlmog1
 
Trident International Graphics Workshop 2014 1/5
Trident International Graphics Workshop 2014 1/5Trident International Graphics Workshop 2014 1/5
Trident International Graphics Workshop 2014 1/5Takao Wada
 
openFrameworks 007 - graphics
openFrameworks 007 - graphicsopenFrameworks 007 - graphics
openFrameworks 007 - graphicsroxlu
 
Creating an Uber Clone - Part VII - Transcript.pdf
Creating an Uber Clone - Part VII - Transcript.pdfCreating an Uber Clone - Part VII - Transcript.pdf
Creating an Uber Clone - Part VII - Transcript.pdfShaiAlmog1
 
Animations - Part 3.pdf
Animations - Part 3.pdfAnimations - Part 3.pdf
Animations - Part 3.pdfShaiAlmog1
 
Yahoo Open Source - The Tour & Mystery of AppDevKit (MOPCON 2016)
Yahoo Open Source - The Tour & Mystery of AppDevKit (MOPCON 2016)Yahoo Open Source - The Tour & Mystery of AppDevKit (MOPCON 2016)
Yahoo Open Source - The Tour & Mystery of AppDevKit (MOPCON 2016)anistar sung
 
203 Is It Real or Is It Virtual? Augmented Reality on the iPhone
203 Is It Real or Is It Virtual? Augmented Reality on the iPhone203 Is It Real or Is It Virtual? Augmented Reality on the iPhone
203 Is It Real or Is It Virtual? Augmented Reality on the iPhonejonmarimba
 
Webgl para JavaScripters
Webgl para JavaScriptersWebgl para JavaScripters
Webgl para JavaScriptersgerbille
 
Kotlin Mullets
Kotlin MulletsKotlin Mullets
Kotlin MulletsJames Ward
 
Computer graphics
Computer graphicsComputer graphics
Computer graphicsamitsarda3
 

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

Introduction to graphics programming in c
Introduction to graphics programming in cIntroduction to graphics programming in c
Introduction to graphics programming in c
 
Leaving Flatland: getting started with WebGL
Leaving Flatland: getting started with WebGLLeaving Flatland: getting started with WebGL
Leaving Flatland: getting started with WebGL
 
Maps - Part 3 - Transcript.pdf
Maps - Part 3 - Transcript.pdfMaps - Part 3 - Transcript.pdf
Maps - Part 3 - Transcript.pdf
 
Graphics in C++
Graphics in C++Graphics in C++
Graphics in C++
 
Applications
ApplicationsApplications
Applications
 
Trident International Graphics Workshop 2014 5/5
Trident International Graphics Workshop 2014 5/5Trident International Graphics Workshop 2014 5/5
Trident International Graphics Workshop 2014 5/5
 
C Graphics Functions
C Graphics FunctionsC Graphics Functions
C Graphics Functions
 
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
 
Trident International Graphics Workshop 2014 1/5
Trident International Graphics Workshop 2014 1/5Trident International Graphics Workshop 2014 1/5
Trident International Graphics Workshop 2014 1/5
 
Games 3 dl4-example
Games 3 dl4-exampleGames 3 dl4-example
Games 3 dl4-example
 
openFrameworks 007 - graphics
openFrameworks 007 - graphicsopenFrameworks 007 - graphics
openFrameworks 007 - graphics
 
Creating an Uber Clone - Part VII - Transcript.pdf
Creating an Uber Clone - Part VII - Transcript.pdfCreating an Uber Clone - Part VII - Transcript.pdf
Creating an Uber Clone - Part VII - Transcript.pdf
 
7. chapter vi
7. chapter vi7. chapter vi
7. chapter vi
 
Animations - Part 3.pdf
Animations - Part 3.pdfAnimations - Part 3.pdf
Animations - Part 3.pdf
 
Yahoo Open Source - The Tour & Mystery of AppDevKit (MOPCON 2016)
Yahoo Open Source - The Tour & Mystery of AppDevKit (MOPCON 2016)Yahoo Open Source - The Tour & Mystery of AppDevKit (MOPCON 2016)
Yahoo Open Source - The Tour & Mystery of AppDevKit (MOPCON 2016)
 
203 Is It Real or Is It Virtual? Augmented Reality on the iPhone
203 Is It Real or Is It Virtual? Augmented Reality on the iPhone203 Is It Real or Is It Virtual? Augmented Reality on the iPhone
203 Is It Real or Is It Virtual? Augmented Reality on the iPhone
 
Webgl para JavaScripters
Webgl para JavaScriptersWebgl para JavaScripters
Webgl para JavaScripters
 
OpenGL L06-Performance
OpenGL L06-PerformanceOpenGL L06-Performance
OpenGL L06-Performance
 
Kotlin Mullets
Kotlin MulletsKotlin Mullets
Kotlin Mullets
 
Computer graphics
Computer graphicsComputer graphics
Computer graphics
 

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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
create-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfcreate-netflix-clone-01-introduction.pdf
create-netflix-clone-01-introduction.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
create-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfcreate-netflix-clone-03-server.pdf
create-netflix-clone-03-server.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
create-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfcreate-netflix-clone-02-server.pdf
create-netflix-clone-02-server.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 

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 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
 

Recently uploaded

Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsPrecisely
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraDeakin University
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDGMarianaLemus7
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Neo4j
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 

Recently uploaded (20)

Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptxVulnerability_Management_GRC_by Sohang Sengupta.pptx
Vulnerability_Management_GRC_by Sohang Sengupta.pptx
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power Systems
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning era
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDG
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 

Creating an Uber Clone - Part XXII - Transcript.pdf

  • 1. Creating an Uber Clone - Part XXII With that out of the way search should work but how does it display the result? For that we need to add additional features to the MapForm that address these capabilities. Before we go into that lets check out what that means
  • 2. Routes © Codename One 2017 all rights reserved The ride booking UI plots the path of the ride on the map and includes two tags one pointing at your current location and one on the destination. The first tag is divided to a "time indication" and name. The latter only contains the name. Notice that the elements have a rounded rectangle shape with a pointy end on one side to point at the position within the path.
  • 3. private Component createNavigationTag(String location, int durationMinutes) { Label locationLabel = new Label(location, "NavigationLabel"); if(durationMinutes > 0) { Label duration = new Label("" + durationMinutes, "NavigationMinuteLabel"); Label min = new Label("MIN", "NavigationMinuteDescLabel"); Container west = BoxLayout.encloseY(duration, min); Container result = BorderLayout.centerEastWest(locationLabel, null, west); result.getUnselectedStyle().setBorder(BlackAndWhiteBorder.create(). blackLinePosition(west.getPreferredW())); return result; } locationLabel.getUnselectedStyle().setBorder( BlackAndWhiteBorder.create()); return locationLabel; } addMapListener Lets start with creating these tags. The tag code itself is trivial it's just a Label or a Container with some details. Nothing special. Except for one important detail, the BlackAndWhiteBorder. In order to implement the unique shape of the tag I created a new Border class. Notice I used the preferred width of the west component to determine the black section. This is done in the blackLinePosition method. Before we go any further I’d just like to make one point clear: I Would have Used a 9-piece Border. If this were a real application I would have just cut a 9-piece border and moved on. However, since the point is teaching I chose to do this the "hard way"
  • 4. NavigationLabel © Codename One 2017 all rights reserved Before we get into the BlackAndWhiteBorder there are a few UIID's we need to define. The NavigationLabel UIID is a the black on white label that appears in the tag.
  • 5. NavigationLabel © Codename One 2017 all rights reserved The only unique thing about it is the relatively small amount of padding so the tag doesn’t take up too much space
  • 6. NavigationLabel © Codename One 2017 all rights reserved The margin is predictably zero
  • 7. NavigationLabel © Codename One 2017 all rights reserved And the font is slightly smaller than usual
  • 8. NavigationMinuteLabel © Codename One 2017 all rights reserved The NavigationMinuteLabel UIID is the white on black minute value.
  • 9. NavigationMinuteLabel © Codename One 2017 all rights reserved It’s center aligned
  • 10. NavigationMinuteLabel © Codename One 2017 all rights reserved It has 0 padding below to keep the text and number close together but has similar paddings on the other sides to match the NavigationLabel
  • 11. NavigationMinuteLabel © Codename One 2017 all rights reserved It has zero margin
  • 12. NavigationMinuteLabel © Codename One 2017 all rights reserved and it has a smaller font size than usual although not a tiny font
  • 13. NavigationMinuteDescLabel © Codename One 2017 all rights reserved The NavigationMinuteDescLabel UIID is used for the text below that. The text with the word “MIN”. It derives from NavigationMinuteLabel
  • 14. NavigationMinuteDescLabel © Codename One 2017 all rights reserved And has an even smaller font than that…
  • 15. public class BlackAndWhiteBorder extends Border { private static final String CACHE_KEY = "cn1$$-bwcache"; private final float shadowBlur = 10; private final float shadowSpread; private final int shadowOpacity = 110; private final float cornerRadius = 1f; private int blackLinePosition = -1; BlackAndWhiteBorder() { shadowSpread = Display.getInstance().convertToPixels(0.2f); } public static BlackAndWhiteBorder create() { return new BlackAndWhiteBorder(); } public BlackAndWhiteBorder blackLinePosition(int blackLinePosition) { this.blackLinePosition = blackLinePosition; return this; } private Image createTargetImage(Component c, int w, int h, boolean fast) { Image target = Image.createImage(w, h, 0); int shapeX = 0; int shapeY = 0; int shapeW = w; int shapeH = h; BlackAndWhiteBorder Now that these are out of the way let's take a look at the border. Notice we can just subclass the Border class just like we can implement painters etc. This provides a similar path for customization but is sometimes more flexible. Most of this code is based on the builtin RoundRectBorder class. Drawing this type of border is pretty expensive so we draw onto an image and place that image in cache within the component using putClientProperty we use this value as the key
  • 16. public class BlackAndWhiteBorder extends Border { private static final String CACHE_KEY = "cn1$$-bwcache"; private final float shadowBlur = 10; private final float shadowSpread; private final int shadowOpacity = 110; private final float cornerRadius = 1f; private int blackLinePosition = -1; BlackAndWhiteBorder() { shadowSpread = Display.getInstance().convertToPixels(0.2f); } public static BlackAndWhiteBorder create() { return new BlackAndWhiteBorder(); } public BlackAndWhiteBorder blackLinePosition(int blackLinePosition) { this.blackLinePosition = blackLinePosition; return this; } private Image createTargetImage(Component c, int w, int h, boolean fast) { Image target = Image.createImage(w, h, 0); int shapeX = 0; int shapeY = 0; int shapeW = w; int shapeH = h; BlackAndWhiteBorder The blackLinePosition is used in the version of this border that's partially black
  • 17. private Image createTargetImage(Component c, int w, int h, boolean fast) { Image target = Image.createImage(w, h, 0); int shapeX = 0; int shapeY = 0; int shapeW = w; int shapeH = h; Graphics tg = target.getGraphics(); tg.setAntiAliased(true); int shadowSpreadL = Display.getInstance().convertToPixels(shadowSpread); shapeW -= shadowSpreadL; shapeH -= shadowSpreadL; shapeX += Math.round(((float)shadowSpreadL) * 0.9); shapeY += Math.round(((float)shadowSpreadL) * 0.9); for(int iter = shadowSpreadL - 1 ; iter >= 0 ; iter--) { tg.translate(iter, iter); fillShape(tg, 0, shadowOpacity / shadowSpreadL, w-(iter*2),h - (iter * 2)); tg.translate(-iter, -iter); } if(Display.getInstance().isGaussianBlurSupported() && !fast) { Image blured = Display.getInstance().gaussianBlurImage(target,shadowBlur/2); target = Image.createImage(w, h, 0); tg = target.getGraphics(); tg.drawImage(blured, 0, 0); BlackAndWhiteBorder Here we create the border image that we will cache for the given component. Since a shadow is set on the border and that can take some processing power. To speed this up we have two versions of the method fast and slow. We call the fast one and invoke the slow one asynchronously to update the border
  • 18. private Image createTargetImage(Component c, int w, int h, boolean fast) { Image target = Image.createImage(w, h, 0); int shapeX = 0; int shapeY = 0; int shapeW = w; int shapeH = h; Graphics tg = target.getGraphics(); tg.setAntiAliased(true); int shadowSpreadL = Display.getInstance().convertToPixels(shadowSpread); shapeW -= shadowSpreadL; shapeH -= shadowSpreadL; shapeX += Math.round(((float)shadowSpreadL) * 0.9); shapeY += Math.round(((float)shadowSpreadL) * 0.9); for(int iter = shadowSpreadL - 1 ; iter >= 0 ; iter--) { tg.translate(iter, iter); fillShape(tg, 0, shadowOpacity / shadowSpreadL, w-(iter*2),h - (iter * 2)); tg.translate(-iter, -iter); } if(Display.getInstance().isGaussianBlurSupported() && !fast) { Image blured = Display.getInstance().gaussianBlurImage(target,shadowBlur/2); target = Image.createImage(w, h, 0); tg = target.getGraphics(); tg.drawImage(blured, 0, 0); BlackAndWhiteBorder We do a shadow effect by drawing a gradient with varying alpha degrees then blurring that out
  • 19. tg.drawImage(blured, 0, 0); tg.setAntiAliased(true); } tg.translate(shapeX, shapeY); c.getStyle().setBorder(Border.createEmpty()); GeneralPath gp = createShape(shapeW, shapeH); tg.setClip(gp); c.getStyle().getBgPainter().paint(tg, new Rectangle(0, 0, w, h)); c.getStyle().setBorder(this); return target; } public void paintBorderBackground(Graphics g, final Component c) { final int w = c.getWidth(); final int h = c.getHeight(); int x = c.getX(); int y = c.getY(); if(w > 0 && h > 0) { Image background = (Image)c.getClientProperty(CACHE_KEY); if(background!=null && background.getWidth()==w && background.getHeight()==h){ g.drawImage(background, x, y); return; } BlackAndWhiteBorder If we have a cached version of the border image we will just use that as the background of the component assuming the size of the component didn't change
  • 20. int y = c.getY(); if(w > 0 && h > 0) { Image background = (Image)c.getClientProperty(CACHE_KEY); if(background!=null && background.getWidth()==w && background.getHeight()==h){ g.drawImage(background, x, y); return; } } else { return; } Image target = createTargetImage(c, w, h, true); g.drawImage(target, x, y); c.putClientProperty(CACHE_KEY, target); Display.getInstance().callSeriallyOnIdle(new Runnable() { public void run() { if(w == c.getWidth() && h == c.getHeight()) { Image target = createTargetImage(c, w, h, false); c.putClientProperty(CACHE_KEY, target); c.repaint(); } } BlackAndWhiteBorder Otherwise we create that image and update it later with the slower version that includes the gradient shadow effect
  • 21. c.putClientProperty(CACHE_KEY, target); c.repaint(); } } }); } private GeneralPath createShape(int shapeW, int shapeH) { GeneralPath gp = new GeneralPath(); float radius = Display.getInstance().convertToPixels(cornerRadius); float x = 0; float y = 0; float widthF = shapeW; float heightF = shapeH; gp.moveTo(x + radius, y); if(blackLinePosition > -1) { gp.lineTo(x + widthF, y); } else { gp.lineTo(x + widthF - radius, y); gp.quadTo(x + widthF, y, x + widthF, y + radius); } gp.lineTo(x + widthF, y + heightF - radius); gp.quadTo(x + widthF, y + heightF, x + widthF - radius, y + heightF); if(blackLinePosition > -1) { BlackAndWhiteBorder We create the shape of the component. If it's the one with the black line we place the corner in the top right otherwise we place it in the bottom left
  • 22. gp.quadTo(x + widthF, y + heightF, x + widthF - radius, y + heightF); if(blackLinePosition > -1) { gp.lineTo(x + radius, y + heightF); gp.quadTo(x, y + heightF, x, y + heightF - radius); } else { gp.lineTo(x, y + heightF); } gp.lineTo(x, y + radius); gp.quadTo(x, y, x + radius, y); gp.closePath(); return gp; } public int getMinimumHeight() { return convertToPixels(shadowSpread) + convertToPixels(cornerRadius) * 2; } public int getMinimumWidth() { return convertToPixels(shadowSpread) + convertToPixels(cornerRadius) * 2; } private void fillShape(Graphics g, int color, int opacity, int width, int height) { g.setColor(0xffffff); g.setAlpha(255); GeneralPath gp = createShape(width, height); if(blackLinePosition > -1) { BlackAndWhiteBorder We can now fill out the shape as part of the image creation code if we have a black line we do the fill operation twice with different clip sizes to create that effect