SlideShare a Scribd company logo
1 of 28
Download to read offline
Creating a Facebook Clone - Part XV
The one last form we’ll work on in the mockup stage is the “New Post” Form
© Codename One 2017 all rights reserved
Right now I'll only support simple variations of the new post. I'll deal with image & video posting later. We will discuss some builtin styles and use HTML to display
formatted posts. This could allow for logic that implements things such as hashtags etc. in a future implementation.
public class NewPostForm extends Form {
private static final String[] POST_STYLES = {
"Label", "PostStyleHearts", "PostStyleHands", "PostStyleBlack",
"PostStyleRed", "PostStylePurple" };
public NewPostForm() {
super("Create Post", new BorderLayout());
Form current = getCurrentForm();
getToolbar().setBackCommand("Cancel",
Toolbar.BackCommandPolicy.
WHEN_USES_TITLE_OTHERWISE_ARROW,
e -> current.showBack());
getToolbar().addMaterialCommandToRightBar("",
FontImage.MATERIAL_DONE, e -> {});
User me = ServerAPI.me();
Container userSettings = BorderLayout.west(
new Label(me.getAvatar(6.5f), "HalfPaddedContainer"));
Button friends = new Button("Friends", "FriendCombo");
FontImage.setMaterialIcon(friends, FontImage.MATERIAL_PEOPLE);
userSettings.add(CENTER,
BoxLayout.encloseY(
new Label(me.fullName(), "MultiLine1"),
FlowLayout.encloseIn(friends)));
NewPostForm
Unlike the tabs we had until now the new post is a separate Form
public class NewPostForm extends Form {
private static final String[] POST_STYLES = {
"Label", "PostStyleHearts", "PostStyleHands", "PostStyleBlack",
"PostStyleRed", "PostStylePurple" };
public NewPostForm() {
super("Create Post", new BorderLayout());
Form current = getCurrentForm();
getToolbar().setBackCommand("Cancel",
Toolbar.BackCommandPolicy.
WHEN_USES_TITLE_OTHERWISE_ARROW,
e -> current.showBack());
getToolbar().addMaterialCommandToRightBar("",
FontImage.MATERIAL_DONE, e -> {});
User me = ServerAPI.me();
Container userSettings = BorderLayout.west(
new Label(me.getAvatar(6.5f), "HalfPaddedContainer"));
Button friends = new Button("Friends", "FriendCombo");
FontImage.setMaterialIcon(friends, FontImage.MATERIAL_PEOPLE);
userSettings.add(CENTER,
BoxLayout.encloseY(
new Label(me.fullName(), "MultiLine1"),
FlowLayout.encloseIn(friends)));
NewPostForm
The new post form includes styles that can be applied to the editing such as colors, background images etc.
public class NewPostForm extends Form {
private static final String[] POST_STYLES = {
"Label", "PostStyleHearts", "PostStyleHands", "PostStyleBlack",
"PostStyleRed", "PostStylePurple" };
public NewPostForm() {
super("Create Post", new BorderLayout());
Form current = getCurrentForm();
getToolbar().setBackCommand("Cancel",
Toolbar.BackCommandPolicy.
WHEN_USES_TITLE_OTHERWISE_ARROW,
e -> current.showBack());
getToolbar().addMaterialCommandToRightBar("",
FontImage.MATERIAL_DONE, e -> {});
User me = ServerAPI.me();
Container userSettings = BorderLayout.west(
new Label(me.getAvatar(6.5f), "HalfPaddedContainer"));
Button friends = new Button("Friends", "FriendCombo");
FontImage.setMaterialIcon(friends, FontImage.MATERIAL_PEOPLE);
userSettings.add(CENTER,
BoxLayout.encloseY(
new Label(me.fullName(), "MultiLine1"),
FlowLayout.encloseIn(friends)));
NewPostForm
The Form itself uses a BorderLayout to position a title area on the top and the rest of the UI over the entire screen
public class NewPostForm extends Form {
private static final String[] POST_STYLES = {
"Label", "PostStyleHearts", "PostStyleHands", "PostStyleBlack",
"PostStyleRed", "PostStylePurple" };
public NewPostForm() {
super("Create Post", new BorderLayout());
Form current = getCurrentForm();
getToolbar().setBackCommand("Cancel",
Toolbar.BackCommandPolicy.
WHEN_USES_TITLE_OTHERWISE_ARROW,
e -> current.showBack());
getToolbar().addMaterialCommandToRightBar("",
FontImage.MATERIAL_DONE, e -> {});
User me = ServerAPI.me();
Container userSettings = BorderLayout.west(
new Label(me.getAvatar(6.5f), "HalfPaddedContainer"));
Button friends = new Button("Friends", "FriendCombo");
FontImage.setMaterialIcon(friends, FontImage.MATERIAL_PEOPLE);
userSettings.add(CENTER,
BoxLayout.encloseY(
new Label(me.fullName(), "MultiLine1"),
FlowLayout.encloseIn(friends)));
NewPostForm
We save the current form before showing so we can go back to it
public class NewPostForm extends Form {
private static final String[] POST_STYLES = {
"Label", "PostStyleHearts", "PostStyleHands", "PostStyleBlack",
"PostStyleRed", "PostStylePurple" };
public NewPostForm() {
super("Create Post", new BorderLayout());
Form current = getCurrentForm();
getToolbar().setBackCommand("Cancel",
Toolbar.BackCommandPolicy.
WHEN_USES_TITLE_OTHERWISE_ARROW,
e -> current.showBack());
getToolbar().addMaterialCommandToRightBar("",
FontImage.MATERIAL_DONE, e -> {});
User me = ServerAPI.me();
Container userSettings = BorderLayout.west(
new Label(me.getAvatar(6.5f), "HalfPaddedContainer"));
Button friends = new Button("Friends", "FriendCombo");
FontImage.setMaterialIcon(friends, FontImage.MATERIAL_PEOPLE);
userSettings.add(CENTER,
BoxLayout.encloseY(
new Label(me.fullName(), "MultiLine1"),
FlowLayout.encloseIn(friends)));
NewPostForm
The avatar of the user goes on the left side of the title area followed by a button that should let us pick the right visibility mode for the post
WHEN_USES_TITLE_OTHERWISE_ARROW,
e -> current.showBack());
getToolbar().addMaterialCommandToRightBar("",
FontImage.MATERIAL_DONE, e -> {});
User me = ServerAPI.me();
Container userSettings = BorderLayout.west(
new Label(me.getAvatar(6.5f), "HalfPaddedContainer"));
Button friends = new Button("Friends", "FriendCombo");
FontImage.setMaterialIcon(friends, FontImage.MATERIAL_PEOPLE);
userSettings.add(CENTER,
BoxLayout.encloseY(
new Label(me.fullName(), "MultiLine1"),
FlowLayout.encloseIn(friends)));
add(NORTH, userSettings);
TextArea post = new TextArea(3, 80);
post.setUIID("Label");
post.setGrowByContent(false);
Container postStyles = createPostStyles(post);
add(CENTER, LayeredLayout.encloseIn(
BorderLayout.north(post), BorderLayout.south(postStyles)));
setEditOnShow(post);
}
private Container createPostStyles(TextArea post) {
Container postStyles = new Container(BoxLayout.x());
postStyles.setScrollableX(true);
NewPostForm
The text of the post is just a standard TextArea with 3 rows and 80 columns. These are just hints for the preferred size of the component
WHEN_USES_TITLE_OTHERWISE_ARROW,
e -> current.showBack());
getToolbar().addMaterialCommandToRightBar("",
FontImage.MATERIAL_DONE, e -> {});
User me = ServerAPI.me();
Container userSettings = BorderLayout.west(
new Label(me.getAvatar(6.5f), "HalfPaddedContainer"));
Button friends = new Button("Friends", "FriendCombo");
FontImage.setMaterialIcon(friends, FontImage.MATERIAL_PEOPLE);
userSettings.add(CENTER,
BoxLayout.encloseY(
new Label(me.fullName(), "MultiLine1"),
FlowLayout.encloseIn(friends)));
add(NORTH, userSettings);
TextArea post = new TextArea(3, 80);
post.setUIID("Label");
post.setGrowByContent(false);
Container postStyles = createPostStyles(post);
add(CENTER, LayeredLayout.encloseIn(
BorderLayout.north(post), BorderLayout.south(postStyles)));
setEditOnShow(post);
}
private Container createPostStyles(TextArea post) {
Container postStyles = new Container(BoxLayout.x());
postStyles.setScrollableX(true);
NewPostForm
If we input more than 3 rows the UI shouldn't grow, it might go on top of the the post styles container and it would be hard to differentiate a tap there from a text edit
gesture
BorderLayout.north(post), BorderLayout.south(postStyles)));
setEditOnShow(post);
}
private Container createPostStyles(TextArea post) {
Container postStyles = new Container(BoxLayout.x());
postStyles.setScrollableX(true);
int size = convertToPixels(8);
ButtonGroup bg = new ButtonGroup();
for(String s : POST_STYLES) {
Button postStyleButton = RadioButton.createToggle("", bg);
postStyleButton.setShowEvenIfBlank(true);
postStyleButton.setUIID(s);
Style stl = postStyleButton.getAllStyles();
stl.setBorder(RoundRectBorder.create());
stl.setPadding(3, 3, 3, 3);
stl.setMarginUnit(Style.UNIT_TYPE_DIPS);
stl.setMargin(1, 1, 1, 1);
int strokeColor = 0xffffff;
if(s.equals("Label")) {
stl.setBgTransparency(255);
stl.setBgColor(0xffffff);
strokeColor = 0;
}
postStyleButton.getPressedStyle().setBorder(RoundRectBorder.
create().strokeColor(strokeColor).
NewPostForm
This method creates the bar at the bottom of the screen, 

When we click an entry in the bar the look changes and the post gets a new style
BorderLayout.north(post), BorderLayout.south(postStyles)));
setEditOnShow(post);
}
private Container createPostStyles(TextArea post) {
Container postStyles = new Container(BoxLayout.x());
postStyles.setScrollableX(true);
int size = convertToPixels(8);
ButtonGroup bg = new ButtonGroup();
for(String s : POST_STYLES) {
Button postStyleButton = RadioButton.createToggle("", bg);
postStyleButton.setShowEvenIfBlank(true);
postStyleButton.setUIID(s);
Style stl = postStyleButton.getAllStyles();
stl.setBorder(RoundRectBorder.create());
stl.setPadding(3, 3, 3, 3);
stl.setMarginUnit(Style.UNIT_TYPE_DIPS);
stl.setMargin(1, 1, 1, 1);
int strokeColor = 0xffffff;
if(s.equals("Label")) {
stl.setBgTransparency(255);
stl.setBgColor(0xffffff);
strokeColor = 0;
}
postStyleButton.getPressedStyle().setBorder(RoundRectBorder.
create().strokeColor(strokeColor).
NewPostForm
The bar on the bottom of the form is an X axis box layout that's scrollable on the X axis
BorderLayout.north(post), BorderLayout.south(postStyles)));
setEditOnShow(post);
}
private Container createPostStyles(TextArea post) {
Container postStyles = new Container(BoxLayout.x());
postStyles.setScrollableX(true);
int size = convertToPixels(8);
ButtonGroup bg = new ButtonGroup();
for(String s : POST_STYLES) {
Button postStyleButton = RadioButton.createToggle("", bg);
postStyleButton.setShowEvenIfBlank(true);
postStyleButton.setUIID(s);
Style stl = postStyleButton.getAllStyles();
stl.setBorder(RoundRectBorder.create());
stl.setPadding(3, 3, 3, 3);
stl.setMarginUnit(Style.UNIT_TYPE_DIPS);
stl.setMargin(1, 1, 1, 1);
int strokeColor = 0xffffff;
if(s.equals("Label")) {
stl.setBgTransparency(255);
stl.setBgColor(0xffffff);
strokeColor = 0;
}
postStyleButton.getPressedStyle().setBorder(RoundRectBorder.
create().strokeColor(strokeColor).
NewPostForm
Every icon is 8 millimeter in size
private Container createPostStyles(TextArea post) {
Container postStyles = new Container(BoxLayout.x());
postStyles.setScrollableX(true);
int size = convertToPixels(8);
ButtonGroup bg = new ButtonGroup();
for(String s : POST_STYLES) {
Button postStyleButton = RadioButton.createToggle("", bg);
postStyleButton.setShowEvenIfBlank(true);
postStyleButton.setUIID(s);
Style stl = postStyleButton.getAllStyles();
stl.setBorder(RoundRectBorder.create());
stl.setPadding(3, 3, 3, 3);
stl.setMarginUnit(Style.UNIT_TYPE_DIPS);
stl.setMargin(1, 1, 1, 1);
int strokeColor = 0xffffff;
if(s.equals("Label")) {
stl.setBgTransparency(255);
stl.setBgColor(0xffffff);
strokeColor = 0;
}
postStyleButton.getPressedStyle().setBorder(RoundRectBorder.
create().strokeColor(strokeColor).
strokeOpacity(255).
stroke(0.5f, true));
postStyleButton.addActionListener(e -> changeStyle(post, s));
NewPostForm
We loop over the style types, the first style is "Label" which means an unstyled regular post
private Container createPostStyles(TextArea post) {
Container postStyles = new Container(BoxLayout.x());
postStyles.setScrollableX(true);
int size = convertToPixels(8);
ButtonGroup bg = new ButtonGroup();
for(String s : POST_STYLES) {
Button postStyleButton = RadioButton.createToggle("", bg);
postStyleButton.setShowEvenIfBlank(true);
postStyleButton.setUIID(s);
Style stl = postStyleButton.getAllStyles();
stl.setBorder(RoundRectBorder.create());
stl.setPadding(3, 3, 3, 3);
stl.setMarginUnit(Style.UNIT_TYPE_DIPS);
stl.setMargin(1, 1, 1, 1);
int strokeColor = 0xffffff;
if(s.equals("Label")) {
stl.setBgTransparency(255);
stl.setBgColor(0xffffff);
strokeColor = 0;
}
postStyleButton.getPressedStyle().setBorder(RoundRectBorder.
create().strokeColor(strokeColor).
strokeOpacity(255).
stroke(0.5f, true));
postStyleButton.addActionListener(e -> changeStyle(post, s));
NewPostForm
We create a radio toggle button for every style and set the style to the button
private Container createPostStyles(TextArea post) {
Container postStyles = new Container(BoxLayout.x());
postStyles.setScrollableX(true);
int size = convertToPixels(8);
ButtonGroup bg = new ButtonGroup();
for(String s : POST_STYLES) {
Button postStyleButton = RadioButton.createToggle("", bg);
postStyleButton.setShowEvenIfBlank(true);
postStyleButton.setUIID(s);
Style stl = postStyleButton.getAllStyles();
stl.setBorder(RoundRectBorder.create());
stl.setPadding(3, 3, 3, 3);
stl.setMarginUnit(Style.UNIT_TYPE_DIPS);
stl.setMargin(1, 1, 1, 1);
int strokeColor = 0xffffff;
if(s.equals("Label")) {
stl.setBgTransparency(255);
stl.setBgColor(0xffffff);
strokeColor = 0;
}
postStyleButton.getPressedStyle().setBorder(RoundRectBorder.
create().strokeColor(strokeColor).
strokeOpacity(255).
stroke(0.5f, true));
postStyleButton.addActionListener(e -> changeStyle(post, s));
NewPostForm
For the round corners we use the RoundRectBorder class and apply it manually as the style is designed for the entire entry
private Container createPostStyles(TextArea post) {
Container postStyles = new Container(BoxLayout.x());
postStyles.setScrollableX(true);
int size = convertToPixels(8);
ButtonGroup bg = new ButtonGroup();
for(String s : POST_STYLES) {
Button postStyleButton = RadioButton.createToggle("", bg);
postStyleButton.setShowEvenIfBlank(true);
postStyleButton.setUIID(s);
Style stl = postStyleButton.getAllStyles();
stl.setBorder(RoundRectBorder.create());
stl.setPadding(3, 3, 3, 3);
stl.setMarginUnit(Style.UNIT_TYPE_DIPS);
stl.setMargin(1, 1, 1, 1);
int strokeColor = 0xffffff;
if(s.equals("Label")) {
stl.setBgTransparency(255);
stl.setBgColor(0xffffff);
strokeColor = 0;
}
postStyleButton.getPressedStyle().setBorder(RoundRectBorder.
create().strokeColor(strokeColor).
strokeOpacity(255).
stroke(0.5f, true));
postStyleButton.addActionListener(e -> changeStyle(post, s));
NewPostForm
The first entry is a special case because text fields are sometimes transparent and so are labels
Button postStyleButton = RadioButton.createToggle("", bg);
postStyleButton.setShowEvenIfBlank(true);
postStyleButton.setUIID(s);
Style stl = postStyleButton.getAllStyles();
stl.setBorder(RoundRectBorder.create());
stl.setPadding(3, 3, 3, 3);
stl.setMarginUnit(Style.UNIT_TYPE_DIPS);
stl.setMargin(1, 1, 1, 1);
int strokeColor = 0xffffff;
if(s.equals("Label")) {
stl.setBgTransparency(255);
stl.setBgColor(0xffffff);
strokeColor = 0;
}
postStyleButton.getPressedStyle().setBorder(RoundRectBorder.
create().strokeColor(strokeColor).
strokeOpacity(255).
stroke(0.5f, true));
postStyleButton.addActionListener(e -> changeStyle(post, s));
postStyleButton.setPreferredSize(new Dimension(size, size));
postStyles.add(postStyleButton);
}
return postStyles;
}
NewPostForm
This implements the selected line border around an entry notice strokeColor can be black when surrounding the white label entry
Button postStyleButton = RadioButton.createToggle("", bg);
postStyleButton.setShowEvenIfBlank(true);
postStyleButton.setUIID(s);
Style stl = postStyleButton.getAllStyles();
stl.setBorder(RoundRectBorder.create());
stl.setPadding(3, 3, 3, 3);
stl.setMarginUnit(Style.UNIT_TYPE_DIPS);
stl.setMargin(1, 1, 1, 1);
int strokeColor = 0xffffff;
if(s.equals("Label")) {
stl.setBgTransparency(255);
stl.setBgColor(0xffffff);
strokeColor = 0;
}
postStyleButton.getPressedStyle().setBorder(RoundRectBorder.
create().strokeColor(strokeColor).
strokeOpacity(255).
stroke(0.5f, true));
postStyleButton.addActionListener(e -> changeStyle(post, s));
postStyleButton.setPreferredSize(new Dimension(size, size));
postStyles.add(postStyleButton);
}
return postStyles;
}
NewPostForm
When the user clicks one of these radio buttons we invoke the changeStyle method
strokeColor = 0;
}
postStyleButton.getPressedStyle().setBorder(RoundRectBorder.
create().strokeColor(strokeColor).
strokeOpacity(255).
stroke(0.5f, true));
postStyleButton.addActionListener(e -> changeStyle(post, s));
postStyleButton.setPreferredSize(new Dimension(size, size));
postStyles.add(postStyleButton);
}
return postStyles;
}
private void changeStyle(TextArea post, String s) {
if(s.equals("Label")) {
post.setUIID(s);
post.getParent().setUIID("Container");
} else {
post.setUIID("PostStyleText");
post.getParent().setUIID(s);
}
revalidate();
}
}
NewPostForm
This brings us directly to the changeStyle method
strokeColor = 0;
}
postStyleButton.getPressedStyle().setBorder(RoundRectBorder.
create().strokeColor(strokeColor).
strokeOpacity(255).
stroke(0.5f, true));
postStyleButton.addActionListener(e -> changeStyle(post, s));
postStyleButton.setPreferredSize(new Dimension(size, size));
postStyles.add(postStyleButton);
}
return postStyles;
}
private void changeStyle(TextArea post, String s) {
if(s.equals("Label")) {
post.setUIID(s);
post.getParent().setUIID("Container");
} else {
post.setUIID("PostStyleText");
post.getParent().setUIID(s);
}
revalidate();
}
}
NewPostForm
We need a special case for the first entry again as the behavior is slightly different
strokeColor = 0;
}
postStyleButton.getPressedStyle().setBorder(RoundRectBorder.
create().strokeColor(strokeColor).
strokeOpacity(255).
stroke(0.5f, true));
postStyleButton.addActionListener(e -> changeStyle(post, s));
postStyleButton.setPreferredSize(new Dimension(size, size));
postStyles.add(postStyleButton);
}
return postStyles;
}
private void changeStyle(TextArea post, String s) {
if(s.equals("Label")) {
post.setUIID(s);
post.getParent().setUIID("Container");
} else {
post.setUIID("PostStyleText");
post.getParent().setUIID(s);
}
revalidate();
}
}
NewPostForm
Separate UIID's are needed for the text area and the foreground
}
if(p.comments.size() > 0) {
stats.add(EAST, new Label(p.comments.size() + " comments",
"SmallLabel"));
}
return stats;
}
private Container createPostBar() {
Button avatar = new Button(ServerAPI.me().getAvatar(6.5f), "Label");
Button writePost = new Button("What's on your mind?",
"NewPostButton");
Button gallery = new Button("Photo", "GalleryButton");
FontImage.setMaterialIcon(gallery,
FontImage.MATERIAL_PHOTO_LIBRARY, 2.9f);
gallery.setTextPosition(BOTTOM);
Container c = BorderLayout.
centerEastWest(writePost, gallery, avatar);
c.setUIID("HalfPaddedContainer");
writePost.addActionListener(e -> new NewPostForm().show());
return c;
}
}
NewsfeedContainer
Before we go into the CSS we need one more thing to get this working. We need the following line in the NewsfeedContainer class in the createPostBar() method.
FriendCombo {
padding: 2mm;
margin: 1mm;
border-radius: 1mm;
border-width: 1px;
border-color: gray;
background: transparent;
color: gray;
font-family: "native:MainLight";
font-size: 2.6mm;
}
PostStyleBase {
background-color: black;
color: white;
padding: 3mm;
text-align: center;
font-family: "native:MainRegular";
font-size: 4.5mm;
}
PostStyleHearts {
cn1-derive: PostStyleBase;
background-image: url(images/hearts.jpg);
theme.css
There is quite a bit of CSS listed here, lets start with the simple stuff. The FriendCombo. This is the gray round rect border that's applied to the visibility button. This
button determines if something is seen only by friends or is public
FriendCombo {
padding: 2mm;
margin: 1mm;
border-radius: 1mm;
border-width: 1px;
border-color: gray;
background: transparent;
color: gray;
font-family: "native:MainLight";
font-size: 2.6mm;
}
PostStyleBase {
background-color: black;
color: white;
padding: 3mm;
text-align: center;
font-family: "native:MainRegular";
font-size: 4.5mm;
}
PostStyleHearts {
cn1-derive: PostStyleBase;
background-image: url(images/hearts.jpg);
theme.css
This is the base UIID for every one of the UIID's listed in the array it isn't mentioned in the code but it's used in the CSS itself
color: white;
padding: 3mm;
text-align: center;
font-family: "native:MainRegular";
font-size: 4.5mm;
}
PostStyleHearts {
cn1-derive: PostStyleBase;
background-image: url(images/hearts.jpg);
cn1-source-dpi: 0;
cn1-background-type: cn1-image-scaled-fill;
}
PostStyleHands {
cn1-derive: PostStyleBase;
background-image: url(images/hands.jpg);
cn1-source-dpi: 0;
cn1-background-type: cn1-image-scaled-fit;
background: #243761;
}
PostStyleBlack {
cn1-derive: PostStyleBase;
}
PostStyleRed {
cn1-derive: PostStyleBase;
background: red;
}
theme.css
Next we have the CSS definitions of the text styles. For this code we'll need hearts.jpg & hands.jpg that represent two of the designs.

Notice that all the styles here derive from PostStyleBase. I fill the hearts pattern into place even though it might make sense to tile it in some cases.
background-image: url(images/hearts.jpg);
cn1-source-dpi: 0;
cn1-background-type: cn1-image-scaled-fill;
}
PostStyleHands {
cn1-derive: PostStyleBase;
background-image: url(images/hands.jpg);
cn1-source-dpi: 0;
cn1-background-type: cn1-image-scaled-fit;
background: #243761;
}
PostStyleBlack {
cn1-derive: PostStyleBase;
}
PostStyleRed {
cn1-derive: PostStyleBase;
background: red;
}
PostStylePurple {
cn1-derive: PostStyleBase;
background: #c600ff;
}
PostStyleText {
background: transparent;
color: white;
padding: 1.5mm;
theme.css
I scale to fit the hands entry, I'm not sure if it's the best way as even in the native app the hands disappear in some cases
cn1-derive: PostStyleBase;
background-image: url(images/hands.jpg);
cn1-source-dpi: 0;
cn1-background-type: cn1-image-scaled-fit;
background: #243761;
}
PostStyleBlack {
cn1-derive: PostStyleBase;
}
PostStyleRed {
cn1-derive: PostStyleBase;
background: red;
}
PostStylePurple {
cn1-derive: PostStyleBase;
background: #c600ff;
}
PostStyleText {
background: transparent;
color: white;
padding: 1.5mm;
text-align: center;
font-family: "native:MainRegular";
font-size: 3.5mm;
}
theme.css
The rest of the styles are pretty trivial and should be easy to understand
cn1-derive: PostStyleBase;
background-image: url(images/hands.jpg);
cn1-source-dpi: 0;
cn1-background-type: cn1-image-scaled-fit;
background: #243761;
}
PostStyleBlack {
cn1-derive: PostStyleBase;
}
PostStyleRed {
cn1-derive: PostStyleBase;
background: red;
}
PostStylePurple {
cn1-derive: PostStyleBase;
background: #c600ff;
}
PostStyleText {
background: transparent;
color: white;
padding: 1.5mm;
text-align: center;
font-family: "native:MainRegular";
font-size: 3.5mm;
}
theme.css
This is the style of the foreground text when another style is applied to the background. With that we are done. You should have a working mockup with a signup wizard
and the core functionality we will work on.

More Related Content

Similar to Creating a Facebook Clone - Part XVI - Transcript.pdf

Creating a Facebook Clone - Part XXVIII - Transcript.pdf
Creating a Facebook Clone - Part XXVIII - Transcript.pdfCreating a Facebook Clone - Part XXVIII - Transcript.pdf
Creating a Facebook Clone - Part XXVIII - Transcript.pdfShaiAlmog1
 
Creating an Uber Clone - Part XXXX - Transcript.pdf
Creating an Uber Clone - Part XXXX - Transcript.pdfCreating an Uber Clone - Part XXXX - Transcript.pdf
Creating an Uber Clone - Part XXXX - Transcript.pdfShaiAlmog1
 
Creating a Facebook Clone - Part VII.pdf
Creating a Facebook Clone - Part VII.pdfCreating a Facebook Clone - Part VII.pdf
Creating a Facebook Clone - Part VII.pdfShaiAlmog1
 
Creating a Facebook Clone - Part XXVIII.pdf
Creating a Facebook Clone - Part XXVIII.pdfCreating a Facebook Clone - Part XXVIII.pdf
Creating a Facebook Clone - Part XXVIII.pdfShaiAlmog1
 
Creating a Facebook Clone - Part XLII.pdf
Creating a Facebook Clone - Part XLII.pdfCreating a Facebook Clone - Part XLII.pdf
Creating a Facebook Clone - Part XLII.pdfShaiAlmog1
 
Initial UI Mockup - Part 3 - Transcript.pdf
Initial UI Mockup - Part 3 - Transcript.pdfInitial UI Mockup - Part 3 - Transcript.pdf
Initial UI Mockup - Part 3 - Transcript.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 
Initial UI Mockup - Part 3.pdf
Initial UI Mockup - Part 3.pdfInitial UI Mockup - Part 3.pdf
Initial UI Mockup - Part 3.pdfShaiAlmog1
 
Creating a Facebook Clone - Part XXXV - Transcript.pdf
Creating a Facebook Clone - Part XXXV - Transcript.pdfCreating a Facebook Clone - Part XXXV - Transcript.pdf
Creating a Facebook Clone - Part XXXV - Transcript.pdfShaiAlmog1
 
Creating a Facebook Clone - Part XII.pdf
Creating a Facebook Clone - Part XII.pdfCreating a Facebook Clone - Part XII.pdf
Creating a Facebook Clone - Part XII.pdfShaiAlmog1
 
C#_hw9_S17.docModify AnimatedBall on Chapter 13. Instead of dr.docx
C#_hw9_S17.docModify AnimatedBall on Chapter 13. Instead of dr.docxC#_hw9_S17.docModify AnimatedBall on Chapter 13. Instead of dr.docx
C#_hw9_S17.docModify AnimatedBall on Chapter 13. Instead of dr.docxRAHUL126667
 
Initial UI Mockup - Part 2.pdf
Initial UI Mockup - Part 2.pdfInitial UI Mockup - Part 2.pdf
Initial UI Mockup - Part 2.pdfShaiAlmog1
 
Creating a Facebook Clone - Part XLII - Transcript.pdf
Creating a Facebook Clone - Part XLII - Transcript.pdfCreating a Facebook Clone - Part XLII - Transcript.pdf
Creating a Facebook Clone - Part XLII - Transcript.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 Facebook Clone - Part XXX.pdf
Creating a Facebook Clone - Part XXX.pdfCreating a Facebook Clone - Part XXX.pdf
Creating a Facebook Clone - Part XXX.pdfShaiAlmog1
 
Extracting ui Design - part 6 - transcript.pdf
Extracting ui Design - part 6 - transcript.pdfExtracting ui Design - part 6 - transcript.pdf
Extracting ui Design - part 6 - transcript.pdfShaiAlmog1
 
Object Oriented Programming Session 4 part 2 Slides .pptx
Object Oriented Programming Session 4 part 2 Slides .pptxObject Oriented Programming Session 4 part 2 Slides .pptx
Object Oriented Programming Session 4 part 2 Slides .pptxr209777z
 
Creating an Uber Clone - Part V.pdf
Creating an Uber Clone - Part V.pdfCreating an Uber Clone - Part V.pdf
Creating an Uber Clone - Part V.pdfShaiAlmog1
 
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.pdfShaiAlmog1
 

Similar to Creating a Facebook Clone - Part XVI - Transcript.pdf (20)

Creating a Facebook Clone - Part XXVIII - Transcript.pdf
Creating a Facebook Clone - Part XXVIII - Transcript.pdfCreating a Facebook Clone - Part XXVIII - Transcript.pdf
Creating a Facebook Clone - Part XXVIII - Transcript.pdf
 
Creating an Uber Clone - Part XXXX - Transcript.pdf
Creating an Uber Clone - Part XXXX - Transcript.pdfCreating an Uber Clone - Part XXXX - Transcript.pdf
Creating an Uber Clone - Part XXXX - Transcript.pdf
 
Creating a Facebook Clone - Part VII.pdf
Creating a Facebook Clone - Part VII.pdfCreating a Facebook Clone - Part VII.pdf
Creating a Facebook Clone - Part VII.pdf
 
Creating a Facebook Clone - Part XXVIII.pdf
Creating a Facebook Clone - Part XXVIII.pdfCreating a Facebook Clone - Part XXVIII.pdf
Creating a Facebook Clone - Part XXVIII.pdf
 
Creating a Facebook Clone - Part XLII.pdf
Creating a Facebook Clone - Part XLII.pdfCreating a Facebook Clone - Part XLII.pdf
Creating a Facebook Clone - Part XLII.pdf
 
Initial UI Mockup - Part 3 - Transcript.pdf
Initial UI Mockup - Part 3 - Transcript.pdfInitial UI Mockup - Part 3 - Transcript.pdf
Initial UI Mockup - Part 3 - Transcript.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
 
Initial UI Mockup - Part 3.pdf
Initial UI Mockup - Part 3.pdfInitial UI Mockup - Part 3.pdf
Initial UI Mockup - Part 3.pdf
 
Creating a Facebook Clone - Part XXXV - Transcript.pdf
Creating a Facebook Clone - Part XXXV - Transcript.pdfCreating a Facebook Clone - Part XXXV - Transcript.pdf
Creating a Facebook Clone - Part XXXV - Transcript.pdf
 
Creating a Facebook Clone - Part XII.pdf
Creating a Facebook Clone - Part XII.pdfCreating a Facebook Clone - Part XII.pdf
Creating a Facebook Clone - Part XII.pdf
 
C#_hw9_S17.docModify AnimatedBall on Chapter 13. Instead of dr.docx
C#_hw9_S17.docModify AnimatedBall on Chapter 13. Instead of dr.docxC#_hw9_S17.docModify AnimatedBall on Chapter 13. Instead of dr.docx
C#_hw9_S17.docModify AnimatedBall on Chapter 13. Instead of dr.docx
 
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 XLII - Transcript.pdf
Creating a Facebook Clone - Part XLII - Transcript.pdfCreating a Facebook Clone - Part XLII - Transcript.pdf
Creating a Facebook Clone - Part XLII - Transcript.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
 
ch20.pptx
ch20.pptxch20.pptx
ch20.pptx
 
Creating a Facebook Clone - Part XXX.pdf
Creating a Facebook Clone - Part XXX.pdfCreating a Facebook Clone - Part XXX.pdf
Creating a Facebook Clone - Part XXX.pdf
 
Extracting ui Design - part 6 - transcript.pdf
Extracting ui Design - part 6 - transcript.pdfExtracting ui Design - part 6 - transcript.pdf
Extracting ui Design - part 6 - transcript.pdf
 
Object Oriented Programming Session 4 part 2 Slides .pptx
Object Oriented Programming Session 4 part 2 Slides .pptxObject Oriented Programming Session 4 part 2 Slides .pptx
Object Oriented Programming Session 4 part 2 Slides .pptx
 
Creating an Uber Clone - Part V.pdf
Creating an Uber Clone - Part V.pdfCreating an Uber Clone - Part V.pdf
Creating an Uber Clone - Part V.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
 

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

Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsNanddeep Nachan
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Angeliki Cooney
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...apidays
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Victor Rentea
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Zilliz
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistandanishmna97
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdfSandro Moreira
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2
 

Recently uploaded (20)

Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 

Creating a Facebook Clone - Part XVI - Transcript.pdf

  • 1. Creating a Facebook Clone - Part XV The one last form we’ll work on in the mockup stage is the “New Post” Form
  • 2. © Codename One 2017 all rights reserved Right now I'll only support simple variations of the new post. I'll deal with image & video posting later. We will discuss some builtin styles and use HTML to display formatted posts. This could allow for logic that implements things such as hashtags etc. in a future implementation.
  • 3. public class NewPostForm extends Form { private static final String[] POST_STYLES = { "Label", "PostStyleHearts", "PostStyleHands", "PostStyleBlack", "PostStyleRed", "PostStylePurple" }; public NewPostForm() { super("Create Post", new BorderLayout()); Form current = getCurrentForm(); getToolbar().setBackCommand("Cancel", Toolbar.BackCommandPolicy. WHEN_USES_TITLE_OTHERWISE_ARROW, e -> current.showBack()); getToolbar().addMaterialCommandToRightBar("", FontImage.MATERIAL_DONE, e -> {}); User me = ServerAPI.me(); Container userSettings = BorderLayout.west( new Label(me.getAvatar(6.5f), "HalfPaddedContainer")); Button friends = new Button("Friends", "FriendCombo"); FontImage.setMaterialIcon(friends, FontImage.MATERIAL_PEOPLE); userSettings.add(CENTER, BoxLayout.encloseY( new Label(me.fullName(), "MultiLine1"), FlowLayout.encloseIn(friends))); NewPostForm Unlike the tabs we had until now the new post is a separate Form
  • 4. public class NewPostForm extends Form { private static final String[] POST_STYLES = { "Label", "PostStyleHearts", "PostStyleHands", "PostStyleBlack", "PostStyleRed", "PostStylePurple" }; public NewPostForm() { super("Create Post", new BorderLayout()); Form current = getCurrentForm(); getToolbar().setBackCommand("Cancel", Toolbar.BackCommandPolicy. WHEN_USES_TITLE_OTHERWISE_ARROW, e -> current.showBack()); getToolbar().addMaterialCommandToRightBar("", FontImage.MATERIAL_DONE, e -> {}); User me = ServerAPI.me(); Container userSettings = BorderLayout.west( new Label(me.getAvatar(6.5f), "HalfPaddedContainer")); Button friends = new Button("Friends", "FriendCombo"); FontImage.setMaterialIcon(friends, FontImage.MATERIAL_PEOPLE); userSettings.add(CENTER, BoxLayout.encloseY( new Label(me.fullName(), "MultiLine1"), FlowLayout.encloseIn(friends))); NewPostForm The new post form includes styles that can be applied to the editing such as colors, background images etc.
  • 5. public class NewPostForm extends Form { private static final String[] POST_STYLES = { "Label", "PostStyleHearts", "PostStyleHands", "PostStyleBlack", "PostStyleRed", "PostStylePurple" }; public NewPostForm() { super("Create Post", new BorderLayout()); Form current = getCurrentForm(); getToolbar().setBackCommand("Cancel", Toolbar.BackCommandPolicy. WHEN_USES_TITLE_OTHERWISE_ARROW, e -> current.showBack()); getToolbar().addMaterialCommandToRightBar("", FontImage.MATERIAL_DONE, e -> {}); User me = ServerAPI.me(); Container userSettings = BorderLayout.west( new Label(me.getAvatar(6.5f), "HalfPaddedContainer")); Button friends = new Button("Friends", "FriendCombo"); FontImage.setMaterialIcon(friends, FontImage.MATERIAL_PEOPLE); userSettings.add(CENTER, BoxLayout.encloseY( new Label(me.fullName(), "MultiLine1"), FlowLayout.encloseIn(friends))); NewPostForm The Form itself uses a BorderLayout to position a title area on the top and the rest of the UI over the entire screen
  • 6. public class NewPostForm extends Form { private static final String[] POST_STYLES = { "Label", "PostStyleHearts", "PostStyleHands", "PostStyleBlack", "PostStyleRed", "PostStylePurple" }; public NewPostForm() { super("Create Post", new BorderLayout()); Form current = getCurrentForm(); getToolbar().setBackCommand("Cancel", Toolbar.BackCommandPolicy. WHEN_USES_TITLE_OTHERWISE_ARROW, e -> current.showBack()); getToolbar().addMaterialCommandToRightBar("", FontImage.MATERIAL_DONE, e -> {}); User me = ServerAPI.me(); Container userSettings = BorderLayout.west( new Label(me.getAvatar(6.5f), "HalfPaddedContainer")); Button friends = new Button("Friends", "FriendCombo"); FontImage.setMaterialIcon(friends, FontImage.MATERIAL_PEOPLE); userSettings.add(CENTER, BoxLayout.encloseY( new Label(me.fullName(), "MultiLine1"), FlowLayout.encloseIn(friends))); NewPostForm We save the current form before showing so we can go back to it
  • 7. public class NewPostForm extends Form { private static final String[] POST_STYLES = { "Label", "PostStyleHearts", "PostStyleHands", "PostStyleBlack", "PostStyleRed", "PostStylePurple" }; public NewPostForm() { super("Create Post", new BorderLayout()); Form current = getCurrentForm(); getToolbar().setBackCommand("Cancel", Toolbar.BackCommandPolicy. WHEN_USES_TITLE_OTHERWISE_ARROW, e -> current.showBack()); getToolbar().addMaterialCommandToRightBar("", FontImage.MATERIAL_DONE, e -> {}); User me = ServerAPI.me(); Container userSettings = BorderLayout.west( new Label(me.getAvatar(6.5f), "HalfPaddedContainer")); Button friends = new Button("Friends", "FriendCombo"); FontImage.setMaterialIcon(friends, FontImage.MATERIAL_PEOPLE); userSettings.add(CENTER, BoxLayout.encloseY( new Label(me.fullName(), "MultiLine1"), FlowLayout.encloseIn(friends))); NewPostForm The avatar of the user goes on the left side of the title area followed by a button that should let us pick the right visibility mode for the post
  • 8. WHEN_USES_TITLE_OTHERWISE_ARROW, e -> current.showBack()); getToolbar().addMaterialCommandToRightBar("", FontImage.MATERIAL_DONE, e -> {}); User me = ServerAPI.me(); Container userSettings = BorderLayout.west( new Label(me.getAvatar(6.5f), "HalfPaddedContainer")); Button friends = new Button("Friends", "FriendCombo"); FontImage.setMaterialIcon(friends, FontImage.MATERIAL_PEOPLE); userSettings.add(CENTER, BoxLayout.encloseY( new Label(me.fullName(), "MultiLine1"), FlowLayout.encloseIn(friends))); add(NORTH, userSettings); TextArea post = new TextArea(3, 80); post.setUIID("Label"); post.setGrowByContent(false); Container postStyles = createPostStyles(post); add(CENTER, LayeredLayout.encloseIn( BorderLayout.north(post), BorderLayout.south(postStyles))); setEditOnShow(post); } private Container createPostStyles(TextArea post) { Container postStyles = new Container(BoxLayout.x()); postStyles.setScrollableX(true); NewPostForm The text of the post is just a standard TextArea with 3 rows and 80 columns. These are just hints for the preferred size of the component
  • 9. WHEN_USES_TITLE_OTHERWISE_ARROW, e -> current.showBack()); getToolbar().addMaterialCommandToRightBar("", FontImage.MATERIAL_DONE, e -> {}); User me = ServerAPI.me(); Container userSettings = BorderLayout.west( new Label(me.getAvatar(6.5f), "HalfPaddedContainer")); Button friends = new Button("Friends", "FriendCombo"); FontImage.setMaterialIcon(friends, FontImage.MATERIAL_PEOPLE); userSettings.add(CENTER, BoxLayout.encloseY( new Label(me.fullName(), "MultiLine1"), FlowLayout.encloseIn(friends))); add(NORTH, userSettings); TextArea post = new TextArea(3, 80); post.setUIID("Label"); post.setGrowByContent(false); Container postStyles = createPostStyles(post); add(CENTER, LayeredLayout.encloseIn( BorderLayout.north(post), BorderLayout.south(postStyles))); setEditOnShow(post); } private Container createPostStyles(TextArea post) { Container postStyles = new Container(BoxLayout.x()); postStyles.setScrollableX(true); NewPostForm If we input more than 3 rows the UI shouldn't grow, it might go on top of the the post styles container and it would be hard to differentiate a tap there from a text edit gesture
  • 10. BorderLayout.north(post), BorderLayout.south(postStyles))); setEditOnShow(post); } private Container createPostStyles(TextArea post) { Container postStyles = new Container(BoxLayout.x()); postStyles.setScrollableX(true); int size = convertToPixels(8); ButtonGroup bg = new ButtonGroup(); for(String s : POST_STYLES) { Button postStyleButton = RadioButton.createToggle("", bg); postStyleButton.setShowEvenIfBlank(true); postStyleButton.setUIID(s); Style stl = postStyleButton.getAllStyles(); stl.setBorder(RoundRectBorder.create()); stl.setPadding(3, 3, 3, 3); stl.setMarginUnit(Style.UNIT_TYPE_DIPS); stl.setMargin(1, 1, 1, 1); int strokeColor = 0xffffff; if(s.equals("Label")) { stl.setBgTransparency(255); stl.setBgColor(0xffffff); strokeColor = 0; } postStyleButton.getPressedStyle().setBorder(RoundRectBorder. create().strokeColor(strokeColor). NewPostForm This method creates the bar at the bottom of the screen, When we click an entry in the bar the look changes and the post gets a new style
  • 11. BorderLayout.north(post), BorderLayout.south(postStyles))); setEditOnShow(post); } private Container createPostStyles(TextArea post) { Container postStyles = new Container(BoxLayout.x()); postStyles.setScrollableX(true); int size = convertToPixels(8); ButtonGroup bg = new ButtonGroup(); for(String s : POST_STYLES) { Button postStyleButton = RadioButton.createToggle("", bg); postStyleButton.setShowEvenIfBlank(true); postStyleButton.setUIID(s); Style stl = postStyleButton.getAllStyles(); stl.setBorder(RoundRectBorder.create()); stl.setPadding(3, 3, 3, 3); stl.setMarginUnit(Style.UNIT_TYPE_DIPS); stl.setMargin(1, 1, 1, 1); int strokeColor = 0xffffff; if(s.equals("Label")) { stl.setBgTransparency(255); stl.setBgColor(0xffffff); strokeColor = 0; } postStyleButton.getPressedStyle().setBorder(RoundRectBorder. create().strokeColor(strokeColor). NewPostForm The bar on the bottom of the form is an X axis box layout that's scrollable on the X axis
  • 12. BorderLayout.north(post), BorderLayout.south(postStyles))); setEditOnShow(post); } private Container createPostStyles(TextArea post) { Container postStyles = new Container(BoxLayout.x()); postStyles.setScrollableX(true); int size = convertToPixels(8); ButtonGroup bg = new ButtonGroup(); for(String s : POST_STYLES) { Button postStyleButton = RadioButton.createToggle("", bg); postStyleButton.setShowEvenIfBlank(true); postStyleButton.setUIID(s); Style stl = postStyleButton.getAllStyles(); stl.setBorder(RoundRectBorder.create()); stl.setPadding(3, 3, 3, 3); stl.setMarginUnit(Style.UNIT_TYPE_DIPS); stl.setMargin(1, 1, 1, 1); int strokeColor = 0xffffff; if(s.equals("Label")) { stl.setBgTransparency(255); stl.setBgColor(0xffffff); strokeColor = 0; } postStyleButton.getPressedStyle().setBorder(RoundRectBorder. create().strokeColor(strokeColor). NewPostForm Every icon is 8 millimeter in size
  • 13. private Container createPostStyles(TextArea post) { Container postStyles = new Container(BoxLayout.x()); postStyles.setScrollableX(true); int size = convertToPixels(8); ButtonGroup bg = new ButtonGroup(); for(String s : POST_STYLES) { Button postStyleButton = RadioButton.createToggle("", bg); postStyleButton.setShowEvenIfBlank(true); postStyleButton.setUIID(s); Style stl = postStyleButton.getAllStyles(); stl.setBorder(RoundRectBorder.create()); stl.setPadding(3, 3, 3, 3); stl.setMarginUnit(Style.UNIT_TYPE_DIPS); stl.setMargin(1, 1, 1, 1); int strokeColor = 0xffffff; if(s.equals("Label")) { stl.setBgTransparency(255); stl.setBgColor(0xffffff); strokeColor = 0; } postStyleButton.getPressedStyle().setBorder(RoundRectBorder. create().strokeColor(strokeColor). strokeOpacity(255). stroke(0.5f, true)); postStyleButton.addActionListener(e -> changeStyle(post, s)); NewPostForm We loop over the style types, the first style is "Label" which means an unstyled regular post
  • 14. private Container createPostStyles(TextArea post) { Container postStyles = new Container(BoxLayout.x()); postStyles.setScrollableX(true); int size = convertToPixels(8); ButtonGroup bg = new ButtonGroup(); for(String s : POST_STYLES) { Button postStyleButton = RadioButton.createToggle("", bg); postStyleButton.setShowEvenIfBlank(true); postStyleButton.setUIID(s); Style stl = postStyleButton.getAllStyles(); stl.setBorder(RoundRectBorder.create()); stl.setPadding(3, 3, 3, 3); stl.setMarginUnit(Style.UNIT_TYPE_DIPS); stl.setMargin(1, 1, 1, 1); int strokeColor = 0xffffff; if(s.equals("Label")) { stl.setBgTransparency(255); stl.setBgColor(0xffffff); strokeColor = 0; } postStyleButton.getPressedStyle().setBorder(RoundRectBorder. create().strokeColor(strokeColor). strokeOpacity(255). stroke(0.5f, true)); postStyleButton.addActionListener(e -> changeStyle(post, s)); NewPostForm We create a radio toggle button for every style and set the style to the button
  • 15. private Container createPostStyles(TextArea post) { Container postStyles = new Container(BoxLayout.x()); postStyles.setScrollableX(true); int size = convertToPixels(8); ButtonGroup bg = new ButtonGroup(); for(String s : POST_STYLES) { Button postStyleButton = RadioButton.createToggle("", bg); postStyleButton.setShowEvenIfBlank(true); postStyleButton.setUIID(s); Style stl = postStyleButton.getAllStyles(); stl.setBorder(RoundRectBorder.create()); stl.setPadding(3, 3, 3, 3); stl.setMarginUnit(Style.UNIT_TYPE_DIPS); stl.setMargin(1, 1, 1, 1); int strokeColor = 0xffffff; if(s.equals("Label")) { stl.setBgTransparency(255); stl.setBgColor(0xffffff); strokeColor = 0; } postStyleButton.getPressedStyle().setBorder(RoundRectBorder. create().strokeColor(strokeColor). strokeOpacity(255). stroke(0.5f, true)); postStyleButton.addActionListener(e -> changeStyle(post, s)); NewPostForm For the round corners we use the RoundRectBorder class and apply it manually as the style is designed for the entire entry
  • 16. private Container createPostStyles(TextArea post) { Container postStyles = new Container(BoxLayout.x()); postStyles.setScrollableX(true); int size = convertToPixels(8); ButtonGroup bg = new ButtonGroup(); for(String s : POST_STYLES) { Button postStyleButton = RadioButton.createToggle("", bg); postStyleButton.setShowEvenIfBlank(true); postStyleButton.setUIID(s); Style stl = postStyleButton.getAllStyles(); stl.setBorder(RoundRectBorder.create()); stl.setPadding(3, 3, 3, 3); stl.setMarginUnit(Style.UNIT_TYPE_DIPS); stl.setMargin(1, 1, 1, 1); int strokeColor = 0xffffff; if(s.equals("Label")) { stl.setBgTransparency(255); stl.setBgColor(0xffffff); strokeColor = 0; } postStyleButton.getPressedStyle().setBorder(RoundRectBorder. create().strokeColor(strokeColor). strokeOpacity(255). stroke(0.5f, true)); postStyleButton.addActionListener(e -> changeStyle(post, s)); NewPostForm The first entry is a special case because text fields are sometimes transparent and so are labels
  • 17. Button postStyleButton = RadioButton.createToggle("", bg); postStyleButton.setShowEvenIfBlank(true); postStyleButton.setUIID(s); Style stl = postStyleButton.getAllStyles(); stl.setBorder(RoundRectBorder.create()); stl.setPadding(3, 3, 3, 3); stl.setMarginUnit(Style.UNIT_TYPE_DIPS); stl.setMargin(1, 1, 1, 1); int strokeColor = 0xffffff; if(s.equals("Label")) { stl.setBgTransparency(255); stl.setBgColor(0xffffff); strokeColor = 0; } postStyleButton.getPressedStyle().setBorder(RoundRectBorder. create().strokeColor(strokeColor). strokeOpacity(255). stroke(0.5f, true)); postStyleButton.addActionListener(e -> changeStyle(post, s)); postStyleButton.setPreferredSize(new Dimension(size, size)); postStyles.add(postStyleButton); } return postStyles; } NewPostForm This implements the selected line border around an entry notice strokeColor can be black when surrounding the white label entry
  • 18. Button postStyleButton = RadioButton.createToggle("", bg); postStyleButton.setShowEvenIfBlank(true); postStyleButton.setUIID(s); Style stl = postStyleButton.getAllStyles(); stl.setBorder(RoundRectBorder.create()); stl.setPadding(3, 3, 3, 3); stl.setMarginUnit(Style.UNIT_TYPE_DIPS); stl.setMargin(1, 1, 1, 1); int strokeColor = 0xffffff; if(s.equals("Label")) { stl.setBgTransparency(255); stl.setBgColor(0xffffff); strokeColor = 0; } postStyleButton.getPressedStyle().setBorder(RoundRectBorder. create().strokeColor(strokeColor). strokeOpacity(255). stroke(0.5f, true)); postStyleButton.addActionListener(e -> changeStyle(post, s)); postStyleButton.setPreferredSize(new Dimension(size, size)); postStyles.add(postStyleButton); } return postStyles; } NewPostForm When the user clicks one of these radio buttons we invoke the changeStyle method
  • 19. strokeColor = 0; } postStyleButton.getPressedStyle().setBorder(RoundRectBorder. create().strokeColor(strokeColor). strokeOpacity(255). stroke(0.5f, true)); postStyleButton.addActionListener(e -> changeStyle(post, s)); postStyleButton.setPreferredSize(new Dimension(size, size)); postStyles.add(postStyleButton); } return postStyles; } private void changeStyle(TextArea post, String s) { if(s.equals("Label")) { post.setUIID(s); post.getParent().setUIID("Container"); } else { post.setUIID("PostStyleText"); post.getParent().setUIID(s); } revalidate(); } } NewPostForm This brings us directly to the changeStyle method
  • 20. strokeColor = 0; } postStyleButton.getPressedStyle().setBorder(RoundRectBorder. create().strokeColor(strokeColor). strokeOpacity(255). stroke(0.5f, true)); postStyleButton.addActionListener(e -> changeStyle(post, s)); postStyleButton.setPreferredSize(new Dimension(size, size)); postStyles.add(postStyleButton); } return postStyles; } private void changeStyle(TextArea post, String s) { if(s.equals("Label")) { post.setUIID(s); post.getParent().setUIID("Container"); } else { post.setUIID("PostStyleText"); post.getParent().setUIID(s); } revalidate(); } } NewPostForm We need a special case for the first entry again as the behavior is slightly different
  • 21. strokeColor = 0; } postStyleButton.getPressedStyle().setBorder(RoundRectBorder. create().strokeColor(strokeColor). strokeOpacity(255). stroke(0.5f, true)); postStyleButton.addActionListener(e -> changeStyle(post, s)); postStyleButton.setPreferredSize(new Dimension(size, size)); postStyles.add(postStyleButton); } return postStyles; } private void changeStyle(TextArea post, String s) { if(s.equals("Label")) { post.setUIID(s); post.getParent().setUIID("Container"); } else { post.setUIID("PostStyleText"); post.getParent().setUIID(s); } revalidate(); } } NewPostForm Separate UIID's are needed for the text area and the foreground
  • 22. } if(p.comments.size() > 0) { stats.add(EAST, new Label(p.comments.size() + " comments", "SmallLabel")); } return stats; } private Container createPostBar() { Button avatar = new Button(ServerAPI.me().getAvatar(6.5f), "Label"); Button writePost = new Button("What's on your mind?", "NewPostButton"); Button gallery = new Button("Photo", "GalleryButton"); FontImage.setMaterialIcon(gallery, FontImage.MATERIAL_PHOTO_LIBRARY, 2.9f); gallery.setTextPosition(BOTTOM); Container c = BorderLayout. centerEastWest(writePost, gallery, avatar); c.setUIID("HalfPaddedContainer"); writePost.addActionListener(e -> new NewPostForm().show()); return c; } } NewsfeedContainer Before we go into the CSS we need one more thing to get this working. We need the following line in the NewsfeedContainer class in the createPostBar() method.
  • 23. FriendCombo { padding: 2mm; margin: 1mm; border-radius: 1mm; border-width: 1px; border-color: gray; background: transparent; color: gray; font-family: "native:MainLight"; font-size: 2.6mm; } PostStyleBase { background-color: black; color: white; padding: 3mm; text-align: center; font-family: "native:MainRegular"; font-size: 4.5mm; } PostStyleHearts { cn1-derive: PostStyleBase; background-image: url(images/hearts.jpg); theme.css There is quite a bit of CSS listed here, lets start with the simple stuff. The FriendCombo. This is the gray round rect border that's applied to the visibility button. This button determines if something is seen only by friends or is public
  • 24. FriendCombo { padding: 2mm; margin: 1mm; border-radius: 1mm; border-width: 1px; border-color: gray; background: transparent; color: gray; font-family: "native:MainLight"; font-size: 2.6mm; } PostStyleBase { background-color: black; color: white; padding: 3mm; text-align: center; font-family: "native:MainRegular"; font-size: 4.5mm; } PostStyleHearts { cn1-derive: PostStyleBase; background-image: url(images/hearts.jpg); theme.css This is the base UIID for every one of the UIID's listed in the array it isn't mentioned in the code but it's used in the CSS itself
  • 25. color: white; padding: 3mm; text-align: center; font-family: "native:MainRegular"; font-size: 4.5mm; } PostStyleHearts { cn1-derive: PostStyleBase; background-image: url(images/hearts.jpg); cn1-source-dpi: 0; cn1-background-type: cn1-image-scaled-fill; } PostStyleHands { cn1-derive: PostStyleBase; background-image: url(images/hands.jpg); cn1-source-dpi: 0; cn1-background-type: cn1-image-scaled-fit; background: #243761; } PostStyleBlack { cn1-derive: PostStyleBase; } PostStyleRed { cn1-derive: PostStyleBase; background: red; } theme.css Next we have the CSS definitions of the text styles. For this code we'll need hearts.jpg & hands.jpg that represent two of the designs. Notice that all the styles here derive from PostStyleBase. I fill the hearts pattern into place even though it might make sense to tile it in some cases.
  • 26. background-image: url(images/hearts.jpg); cn1-source-dpi: 0; cn1-background-type: cn1-image-scaled-fill; } PostStyleHands { cn1-derive: PostStyleBase; background-image: url(images/hands.jpg); cn1-source-dpi: 0; cn1-background-type: cn1-image-scaled-fit; background: #243761; } PostStyleBlack { cn1-derive: PostStyleBase; } PostStyleRed { cn1-derive: PostStyleBase; background: red; } PostStylePurple { cn1-derive: PostStyleBase; background: #c600ff; } PostStyleText { background: transparent; color: white; padding: 1.5mm; theme.css I scale to fit the hands entry, I'm not sure if it's the best way as even in the native app the hands disappear in some cases
  • 27. cn1-derive: PostStyleBase; background-image: url(images/hands.jpg); cn1-source-dpi: 0; cn1-background-type: cn1-image-scaled-fit; background: #243761; } PostStyleBlack { cn1-derive: PostStyleBase; } PostStyleRed { cn1-derive: PostStyleBase; background: red; } PostStylePurple { cn1-derive: PostStyleBase; background: #c600ff; } PostStyleText { background: transparent; color: white; padding: 1.5mm; text-align: center; font-family: "native:MainRegular"; font-size: 3.5mm; } theme.css The rest of the styles are pretty trivial and should be easy to understand
  • 28. cn1-derive: PostStyleBase; background-image: url(images/hands.jpg); cn1-source-dpi: 0; cn1-background-type: cn1-image-scaled-fit; background: #243761; } PostStyleBlack { cn1-derive: PostStyleBase; } PostStyleRed { cn1-derive: PostStyleBase; background: red; } PostStylePurple { cn1-derive: PostStyleBase; background: #c600ff; } PostStyleText { background: transparent; color: white; padding: 1.5mm; text-align: center; font-family: "native:MainRegular"; font-size: 3.5mm; } theme.css This is the style of the foreground text when another style is applied to the background. With that we are done. You should have a working mockup with a signup wizard and the core functionality we will work on.