SlideShare a Scribd company logo
1 of 21
Download to read offline
How do I?
In this short video Iā€™ll review the basics of creating a list of items in Codename One. But there is a catch, Codename One has a List class and we wonā€™t be using it. The list
class is designed for a very elaborate type of list that isnā€™t as useful for common day devices. Unless you have a very extreme and specific use case you probably
shouldnā€™t use it as it is slower & harder to use than the alternative!
Create a List Of Items
In this short video Iā€™ll review the basics of creating a list of items in Codename One. But there is a catch, Codename One has a List class and we wonā€™t be using it. The list
class is designed for a very elaborate type of list that isnā€™t as useful for common day devices. Unless you have a very extreme and specific use case you probably
shouldnā€™t use it as it is slower & harder to use than the alternative!
List?
āœ¦Donā€™t use com.codename1.ui.List!
āœ¦Use box layout Y and components
āœ¦Use InfiniteScrollAdapter or
InfiniteContainer for larger sets
Ā© Codename One 2017 all rights reserved
In this short video Iā€™ll review the basics of creating a list of items in Codename One. But there is a catch, Codename One has a List class and we wonā€™t be using it. The list
class is designed for a very elaborate type of list that isnā€™t as useful for common day devices. Unless you have a very extreme and specific use case you probably
shouldnā€™t use it as it is slower & harder to use than the alternative!

Instead weā€™ll use the box layout on the Y axis and add components to it. Iā€™ll focus on multi-button as this is a very common component for this type of use but you can
add any custom component you want.

In larger sets we can use infinite container or infinite scroll adapter. This allows us to fetch elements dynamically and avoid the overhead of creating hundreds or
thousands of components at once.
Form hi = new Form("Basic List", new BorderLayout());
Container list = new Container(BoxLayout.y());
list.setScrollableY(true);
for(int iter = 0 ; iter < 1000 ; iter++) {
MultiButton mb = new MultiButton("List entry " + iter);
mb.setTextLine2("Further details....");
list.add(mb);
}
hi.add(CENTER, list);
hi.show();
Hello List
Lets start with a hello world for a box layout list. This is pretty standard Codename One code, lets go over the diļ¬€erent pieces.

First we create the list container, notice we set it to scroll on the Y axis. This allows us to scroll through the list which is crucial. Notice that by default a Form is already
scrollable on the Y axis but Iā€™ve set the layout to border layout which implicitly disables scrolling. Itā€™s important that scrolling shouldnā€™t ā€œnestā€ as itā€™s impossible to pick the
right scrollbar with a touch interface.
Form hi = new Form("Basic List", new BorderLayout());
Container list = new Container(BoxLayout.y());
list.setScrollableY(true);
for(int iter = 0 ; iter < 1000 ; iter++) {
MultiButton mb = new MultiButton("List entry " + iter);
mb.setTextLine2("Further details....");
list.add(mb);
}
hi.add(CENTER, list);
hi.show();
Hello List
In this case I just added a thousand entries to the list one by one. The list is relatively simple with no actual functionality other than counting the entries
Form hi = new Form("Basic List", new BorderLayout());
Container list = new Container(BoxLayout.y());
list.setScrollableY(true);
for(int iter = 0 ; iter < 1000 ; iter++) {
MultiButton mb = new MultiButton("List entry " + iter);
mb.setTextLine2("Further details....");
list.add(mb);
}
hi.add(CENTER, list);
hi.show();
Hello List
Notice I place the list in the CENTER of the border layout. This is crucial as center in the border layout stretches the container to fit the screen exactly.

This is the resulting list that can be scrolled up and down by swiping.
Form hi = new Form("Infinite List", new BorderLayout());
Container list = new InfiniteContainer() {
@Override
public Component[] fetchComponents(int index, int amount) {
Component[] more = new Component[amount];
for(int iter = 0 ; iter < amount ; iter++) {
MultiButton mb = new MultiButton("List entry " + (index + iter));
mb.setTextLine2("Further details....");
more[iter] = mb;
}
return more;
}
};
hi.add(CENTER, list);
hi.show();
Infinite List
Thatā€™s all good and well but in the real world we need lists to be more dynamic than that. We need to fetch data in batches. Thatā€™s why we have the infinite container
class which allows us to fetch components as the user scrolls through the list. This is the exact same code from before but it creates the list entries in batches instead of
as a single block.

The fetchComponents method is invoked with an index in the list and the amount of elements to return. It then creates and returns those elements. This implicitly adds
the elements as we scroll and implements the pull to refresh functionality.
public Component[] fetchComponents(int index, int amount) {
Component[] more = new Component[amount];
for(int iter = 0 ; iter < amount ; iter++) {
int offset = index + iter;
MultiButton mb = new MultiButton("List entry " + offset);
mb.setTextLine2("Further details....");
FontImage.setMaterialIcon(mb, FontImage.MATERIAL_PERSON);
mb.addActionListener(ee ->
ToastBar.showMessage("Clicked: " + offset,
FontImage.MATERIAL_PERSON));
more[iter] = mb;
}
return more;
}
Events/Icons
This might be obvious but just in case you donā€™t know you can set an icon for every entry and just add an action listener to get events for a specific entry in the list. This
is very convenient.

This is relatively simple in terms of design, you can check out some of the more elaborate design of a list we have in the kitchen sink demo.
Form hi = new Form("Contacts List", new BorderLayout());
final FontImage placeholderImage = FontImage.createMaterial(FontImage.MATERIAL_PERSON, "Label", 6);
Container list = new InfiniteContainer() {
private Contact[] contacts;
public Component[] fetchComponents(int index, int amount) {
if(index == 0) // for pull for refresh by fetching the contacts over again
contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false);
if(index + amount > contacts.length) {
amount = contacts.length - index;
if(amount <= 0) { // we reached the end of the infinite contacts
return null;
}
}
Component[] more = new Component[amount];
for(int iter = 0 ; iter < amount ; iter++) {
int offset = index + iter;
MultiButton mb = new MultiButton(contacts[offset].getDisplayName());
String contactId = contacts[iter].getId();
mb.setIcon(placeholderImage);
Display.getInstance().callSeriallyOnIdle(() -> {
Contact cnt=Display.getInstance().getContactById(contactId,false,true,false,false,false);
Image i = cnt.getPhoto();
if(i != null) mb.setIcon(i.fill(placeholderImage.getWidth(), placeholderImage.getHeight()));
});
more[iter] = mb;
}
Contacts List
Up until now we did simple demos, this is a screenshot of a contacts list from my device using this sort of API and it was generated with this code. Notice I blurred a few
entries since these are my actual phone contacts and Iā€™d like to keep their privacyā€¦ This is done with the code here, letā€™s go over it.
Form hi = new Form("Contacts List", new BorderLayout());
final FontImage placeholderImage = FontImage.createMaterial(FontImage.MATERIAL_PERSON, "Label", 6);
Container list = new InfiniteContainer() {
private Contact[] contacts;
public Component[] fetchComponents(int index, int amount) {
if(index == 0) // for pull for refresh by fetching the contacts over again
contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false);
if(index + amount > contacts.length) {
amount = contacts.length - index;
if(amount <= 0) { // we reached the end of the infinite contacts
return null;
}
}
Component[] more = new Component[amount];
for(int iter = 0 ; iter < amount ; iter++) {
int offset = index + iter;
MultiButton mb = new MultiButton(contacts[offset].getDisplayName());
String contactId = contacts[iter].getId();
mb.setIcon(placeholderImage);
Display.getInstance().callSeriallyOnIdle(() -> {
Contact cnt=Display.getInstance().getContactById(contactId,false,true,false,false,false);
Image i = cnt.getPhoto();
if(i != null) mb.setIcon(i.fill(placeholderImage.getWidth(), placeholderImage.getHeight()));
});
more[iter] = mb;
}
Contacts List
First we need a placeholder image for the common case where a contact doesnā€™t have a profile picture or when we are still loading the profile picture.
Form hi = new Form("Contacts List", new BorderLayout());
final FontImage placeholderImage = FontImage.createMaterial(FontImage.MATERIAL_PERSON, "Label", 6);
Container list = new InfiniteContainer() {
private Contact[] contacts;
public Component[] fetchComponents(int index, int amount) {
if(index == 0) // for pull for refresh by fetching the contacts over again
contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false);
if(index + amount > contacts.length) {
amount = contacts.length - index;
if(amount <= 0) { // we reached the end of the infinite contacts
return null;
}
}
Component[] more = new Component[amount];
for(int iter = 0 ; iter < amount ; iter++) {
int offset = index + iter;
MultiButton mb = new MultiButton(contacts[offset].getDisplayName());
String contactId = contacts[iter].getId();
mb.setIcon(placeholderImage);
Display.getInstance().callSeriallyOnIdle(() -> {
Contact cnt=Display.getInstance().getContactById(contactId,false,true,false,false,false);
Image i = cnt.getPhoto();
if(i != null) mb.setIcon(i.fill(placeholderImage.getWidth(), placeholderImage.getHeight()));
});
more[iter] = mb;
}
Contacts List
When we are in the first element which will happen when the form loads or after a ā€œpull to refreshā€ I load the contacts. Notice I could have used if contacts equals null but
that would have done nothing in the case of pull to refresh as contacts would have been initialized already. By checking against zero I implicitly support the pull to refresh
behavior which just calls the fetch method over again.

The contacts API can be a bit slow sometimes which is why you shouldnā€™t fetch ā€œeverythingā€ with one request. Thatā€™s why the method accepts all of these boolean values
to indicate what we need from the contact itself. Setting all of these to true will slow you down significantly so you should generally load just what you need which in this
case is contacts with a phone number and full name.
Form hi = new Form("Contacts List", new BorderLayout());
final FontImage placeholderImage = FontImage.createMaterial(FontImage.MATERIAL_PERSON, "Label", 6);
Container list = new InfiniteContainer() {
private Contact[] contacts;
public Component[] fetchComponents(int index, int amount) {
if(index == 0) // for pull for refresh by fetching the contacts over again
contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false);
if(index + amount > contacts.length) {
amount = contacts.length - index;
if(amount <= 0) { // we reached the end of the infinite contacts
return null;
}
}
Component[] more = new Component[amount];
for(int iter = 0 ; iter < amount ; iter++) {
int offset = index + iter;
MultiButton mb = new MultiButton(contacts[offset].getDisplayName());
String contactId = contacts[iter].getId();
mb.setIcon(placeholderImage);
Display.getInstance().callSeriallyOnIdle(() -> {
Contact cnt=Display.getInstance().getContactById(contactId,false,true,false,false,false);
Image i = cnt.getPhoto();
if(i != null) mb.setIcon(i.fill(placeholderImage.getWidth(), placeholderImage.getHeight()));
});
more[iter] = mb;
}
Contacts List
The infinite container has no idea how many elements we might have. So we need to check if the amount of elements requested exceeds the total and if the index is out
of bounds. If the former is true we need to reduce the amount and return a smaller array. If the latter is true we need to return null which will stop future calls to fetch
components unless pull to refresh is triggered again.
Form hi = new Form("Contacts List", new BorderLayout());
final FontImage placeholderImage = FontImage.createMaterial(FontImage.MATERIAL_PERSON, "Label", 6);
Container list = new InfiniteContainer() {
private Contact[] contacts;
public Component[] fetchComponents(int index, int amount) {
if(index == 0) // for pull for refresh by fetching the contacts over again
contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false);
if(index + amount > contacts.length) {
amount = contacts.length - index;
if(amount <= 0) { // we reached the end of the infinite contacts
return null;
}
}
Component[] more = new Component[amount];
for(int iter = 0 ; iter < amount ; iter++) {
int offset = index + iter;
MultiButton mb = new MultiButton(contacts[offset].getDisplayName());
String contactId = contacts[iter].getId();
mb.setIcon(placeholderImage);
Display.getInstance().callSeriallyOnIdle(() -> {
Contact cnt=Display.getInstance().getContactById(contactId,false,true,false,false,false);
Image i = cnt.getPhoto();
if(i != null) mb.setIcon(i.fill(placeholderImage.getWidth(), placeholderImage.getHeight()));
});
more[iter] = mb;
}
Contacts List
The rest is pretty close to the code we had before where we loop and create multi buttons but in this case we just fill them up with the content details and the placeholder
image.
Form hi = new Form("Contacts List", new BorderLayout());
final FontImage placeholderImage = FontImage.createMaterial(FontImage.MATERIAL_PERSON, "Label", 6);
Container list = new InfiniteContainer() {
private Contact[] contacts;
public Component[] fetchComponents(int index, int amount) {
if(index == 0) // for pull for refresh by fetching the contacts over again
contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false);
if(index + amount > contacts.length) {
amount = contacts.length - index;
if(amount <= 0) { // we reached the end of the infinite contacts
return null;
}
}
Component[] more = new Component[amount];
for(int iter = 0 ; iter < amount ; iter++) {
int offset = index + iter;
MultiButton mb = new MultiButton(contacts[offset].getDisplayName());
String contactId = contacts[iter].getId();
mb.setIcon(placeholderImage);
Display.getInstance().callSeriallyOnIdle(() -> {
Contact cnt=Display.getInstance().getContactById(contactId,false,true,false,false,false);
Image i = cnt.getPhoto();
if(i != null) mb.setIcon(i.fill(placeholderImage.getWidth(), placeholderImage.getHeight()));
});
more[iter] = mb;
}
Contacts List
However, you might recall we didnā€™t fetch the image for the contact and that might be pretty expensive to loadā€¦ So the trick is to call this method on a button by button
case where we fetch ONLY the image but we donā€™t just invoke that as it would kill performance.

For this we use the new callSeriallyOnIdle() method. This method works like callSerially by performing the code in the next event dispatch thread cycle. However, in this
case the code will only occur when the phone is idle and there are no other urgent events.
Form hi = new Form("Contacts List", new BorderLayout());
final FontImage placeholderImage = FontImage.createMaterial(FontImage.MATERIAL_PERSON, "Label", 6);
Container list = new InfiniteContainer() {
private Contact[] contacts;
public Component[] fetchComponents(int index, int amount) {
if(index == 0) // for pull for refresh by fetching the contacts over again
contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false);
if(index + amount > contacts.length) {
amount = contacts.length - index;
if(amount <= 0) { // we reached the end of the infinite contacts
return null;
}
}
Component[] more = new Component[amount];
for(int iter = 0 ; iter < amount ; iter++) {
int offset = index + iter;
MultiButton mb = new MultiButton(contacts[offset].getDisplayName());
String contactId = contacts[iter].getId();
mb.setIcon(placeholderImage);
Display.getInstance().callSeriallyOnIdle(() -> {
Contact cnt=Display.getInstance().getContactById(contactId,false,true,false,false,false);
Image i = cnt.getPhoto();
if(i != null) mb.setIcon(i.fill(placeholderImage.getWidth(), placeholderImage.getHeight()));
});
more[iter] = mb;
}
Contacts List
So if we are in idle state we can just ask for the contacts image using the specific API then fill up the UI. Since this is an infinite list this will only be invoked for the
ā€œamountā€ number of entries per cycle and that means it should be reasonably eļ¬ƒcient.
Component[] more = new Component[amount];
for(int iter = 0 ; iter < amount ; iter++) {
int offset = index + iter;
MultiButton mb = new MultiButton(contacts[offset].getDisplayName());
String contactId = contacts[iter].getId();
mb.setIcon(placeholderImage);
Display.getInstance().callSeriallyOnIdle(() -> {
Contact cnt=Display.getInstance().getContactById(contactId,true,true,false,false,false);
Image i = cnt.getPhoto();
if(i != null) mb.setIcon(i.fill(placeholderImage.getWidth(), placeholderImage.getHeight()));
});
more[iter] = mb;
}
return more;
}
};
hi.add(CENTER, list);
hi.show();
Contacts List
Moving to the next page we can see that not much is left, we just return the array and add the list to the center.

I didnā€™t spend much time on refinement and some of the nicer eļ¬€ects you can achieve but you can check out the kitchen sink demo where the contacts section features
a swipe UI with many special eļ¬€ects such as generated icons per letter.
String searchString;
public void start() {
if(current != null){
current.show();
return;
}
Form hi = new Form("Contacts List", new BorderLayout());
final FontImage placeholderImage = FontImage.createMaterial(
FontImage.MATERIAL_PERSON, "Label", 6);
InfiniteContainer list = new InfiniteContainer() {
private Contact[] contacts;
public Component[] fetchComponents(int index, int amount) {
if(index == 0) {
contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false);
if(searchString != null && searchString.length() > 0) {
ArrayList<Contact> cts = new ArrayList<>();
searchString = searchString.toLowerCase();
for(Contact c : contacts) {
if(c.getDisplayName().toLowerCase().indexOf(searchString) > -1) {
cts.add(c);
}
}
contacts = new Contact[cts.size()];
cts.toArray(contacts);
}
}
if(index + amount > contacts.length) {
amount = contacts.length - index;
if(amount <= 0) { // we reached the end of the infinite contacts
return null;
}
}
Component[] more = new Component[amount];
for(int iter = 0 ; iter < amount ; iter++) {
int offset = index + iter;
MultiButton mb = new MultiButton(contacts[offset].getDisplayName());
String contactId = contacts[iter].getId();
mb.setIcon(placeholderImage);
Display.getInstance().callSeriallyOnIdle(() -> {
Contact cnt=Display.getInstance().getContactById(contactId,true,true,false,false,false);
Image i = cnt.getPhoto();
if(i != null) mb.setIcon(i.fill(placeholderImage.getWidth(), placeholderImage.getHeight()));
});
more[iter] = mb;
}
return more;
}
};
hi.getToolbar().addSearchCommand(e -> {
searchString = (String)e.getSource();
list.refresh();
});
hi.add(CENTER, list);
hi.show();
Search
Adding search to the infinite list is pretty easy
String searchString;
public void start() {
if(current != null){
current.show();
return;
}
Form hi = new Form("Contacts List", new BorderLayout());
final FontImage placeholderImage = FontImage.createMaterial(
FontImage.MATERIAL_PERSON, "Label", 6);
InfiniteContainer list = new InfiniteContainer() {
private Contact[] contacts;
public Component[] fetchComponents(int index, int amount) {
if(index == 0) {
contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false);
if(searchString != null && searchString.length() > 0) {
ArrayList<Contact> cts = new ArrayList<>();
searchString = searchString.toLowerCase();
for(Contact c : contacts) {
if(c.getDisplayName().toLowerCase().indexOf(searchString) > -1) {
cts.add(c);
}
}
contacts = new Contact[cts.size()];
cts.toArray(contacts);
}
}
Search
We need a search string variable that is both modifiable and accessible in the inner class so I added a member to the parent class.
String searchString;
public void start() {
if(current != null){
current.show();
return;
}
Form hi = new Form("Contacts List", new BorderLayout());
final FontImage placeholderImage = FontImage.createMaterial(
FontImage.MATERIAL_PERSON, "Label", 6);
InfiniteContainer list = new InfiniteContainer() {
private Contact[] contacts;
public Component[] fetchComponents(int index, int amount) {
if(index == 0) {
contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false);
if(searchString != null && searchString.length() > 0) {
ArrayList<Contact> cts = new ArrayList<>();
searchString = searchString.toLowerCase();
for(Contact c : contacts) {
if(c.getDisplayName().toLowerCase().indexOf(searchString) > -1) {
cts.add(c);
}
}
contacts = new Contact[cts.size()];
cts.toArray(contacts);
}
}
Search
The rest of the code is identical, I just filter the basic contacts entry. A change in search will refresh the list and invoke fetch components for index zero. If in this case I
have a search filter I can loop over the contacts and filter them into a new array list. I can then create a new smaller contacts array that matches the search.
hi.getToolbar().addSearchCommand(e -> {
searchString = (String)e.getSource();
list.refresh();
});
hi.add(CENTER, list);
hi.show();
}
Search
The search string can be bound to the variable using the toolbar search API thatā€™s builtin. The call to refresh has a similar eļ¬€ect to pull to refresh. It allows me to filter the
list dynamically and eļ¬ƒciently.
Thank You!
Thanks for watching, I hope you found this helpful

More Related Content

Similar to How do I - Create a List of Items - Transcript.pdf

Java căn bįŗ£n - Chapter10
Java căn bįŗ£n - Chapter10Java căn bįŗ£n - Chapter10
Java căn bįŗ£n - Chapter10Vince Vo
Ā 
UIKonf App & Data Driven Design @swift.berlin
UIKonf App & Data Driven Design @swift.berlinUIKonf App & Data Driven Design @swift.berlin
UIKonf App & Data Driven Design @swift.berlinMaxim Zaks
Ā 
Implement the ListArray ADT-Implement the following operations.pdf
Implement the ListArray ADT-Implement the following operations.pdfImplement the ListArray ADT-Implement the following operations.pdf
Implement the ListArray ADT-Implement the following operations.pdfpetercoiffeur18
Ā 
Documentation For Tab Setup
Documentation For Tab SetupDocumentation For Tab Setup
Documentation For Tab Setupvkeeton
Ā 
All you need to know about JavaScript Functions
All you need to know about JavaScript FunctionsAll you need to know about JavaScript Functions
All you need to know about JavaScript FunctionsOluwaleke Fakorede
Ā 
2. Section 2. Implementing functionality in the PersonEntry. (1.5 ma.pdf
2. Section 2. Implementing functionality in the PersonEntry. (1.5 ma.pdf2. Section 2. Implementing functionality in the PersonEntry. (1.5 ma.pdf
2. Section 2. Implementing functionality in the PersonEntry. (1.5 ma.pdfallwayscollection
Ā 
Need done for Date Structures please! 4-18 LAB- Sorted number list imp.pdf
Need done for Date Structures please! 4-18 LAB- Sorted number list imp.pdfNeed done for Date Structures please! 4-18 LAB- Sorted number list imp.pdf
Need done for Date Structures please! 4-18 LAB- Sorted number list imp.pdfinfo114
Ā 
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
Ā 
dynamicList.ppt
dynamicList.pptdynamicList.ppt
dynamicList.pptssuser0be977
Ā 
Write a program to find the number of comparisons using the binary se.docx
 Write a program to find the number of comparisons using the binary se.docx Write a program to find the number of comparisons using the binary se.docx
Write a program to find the number of comparisons using the binary se.docxajoy21
Ā 
ź°•ģ˜ģžė£Œ7
ź°•ģ˜ģžė£Œ7ź°•ģ˜ģžė£Œ7
ź°•ģ˜ģžė£Œ7Young Wook Kim
Ā 
Presentation
PresentationPresentation
Presentationmanogallery
Ā 
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
Ā 
Creating a Facebook Clone - Part XXXIII - Transcript.pdf
Creating a Facebook Clone - Part XXXIII - Transcript.pdfCreating a Facebook Clone - Part XXXIII - Transcript.pdf
Creating a Facebook Clone - Part XXXIII - Transcript.pdfShaiAlmog1
Ā 
Given the following codepackage data1;import java.util.;p.pdf
Given the following codepackage data1;import java.util.;p.pdfGiven the following codepackage data1;import java.util.;p.pdf
Given the following codepackage data1;import java.util.;p.pdfillyasraja7
Ā 
A Skeptics guide to functional style javascript
A Skeptics guide to functional style javascriptA Skeptics guide to functional style javascript
A Skeptics guide to functional style javascriptjonathanfmills
Ā 

Similar to How do I - Create a List of Items - Transcript.pdf (20)

Java căn bįŗ£n - Chapter10
Java căn bįŗ£n - Chapter10Java căn bįŗ£n - Chapter10
Java căn bįŗ£n - Chapter10
Ā 
Lab 13
Lab 13Lab 13
Lab 13
Ā 
UIKonf App & Data Driven Design @swift.berlin
UIKonf App & Data Driven Design @swift.berlinUIKonf App & Data Driven Design @swift.berlin
UIKonf App & Data Driven Design @swift.berlin
Ā 
Implement the ListArray ADT-Implement the following operations.pdf
Implement the ListArray ADT-Implement the following operations.pdfImplement the ListArray ADT-Implement the following operations.pdf
Implement the ListArray ADT-Implement the following operations.pdf
Ā 
Documentation For Tab Setup
Documentation For Tab SetupDocumentation For Tab Setup
Documentation For Tab Setup
Ā 
All you need to know about JavaScript Functions
All you need to know about JavaScript FunctionsAll you need to know about JavaScript Functions
All you need to know about JavaScript Functions
Ā 
2. Section 2. Implementing functionality in the PersonEntry. (1.5 ma.pdf
2. Section 2. Implementing functionality in the PersonEntry. (1.5 ma.pdf2. Section 2. Implementing functionality in the PersonEntry. (1.5 ma.pdf
2. Section 2. Implementing functionality in the PersonEntry. (1.5 ma.pdf
Ā 
Programming Assignment Help
Programming Assignment HelpProgramming Assignment Help
Programming Assignment Help
Ā 
Need done for Date Structures please! 4-18 LAB- Sorted number list imp.pdf
Need done for Date Structures please! 4-18 LAB- Sorted number list imp.pdfNeed done for Date Structures please! 4-18 LAB- Sorted number list imp.pdf
Need done for Date Structures please! 4-18 LAB- Sorted number list imp.pdf
Ā 
python.pdf
python.pdfpython.pdf
python.pdf
Ā 
Statistics.cpp
Statistics.cppStatistics.cpp
Statistics.cpp
Ā 
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
Ā 
dynamicList.ppt
dynamicList.pptdynamicList.ppt
dynamicList.ppt
Ā 
Write a program to find the number of comparisons using the binary se.docx
 Write a program to find the number of comparisons using the binary se.docx Write a program to find the number of comparisons using the binary se.docx
Write a program to find the number of comparisons using the binary se.docx
Ā 
ź°•ģ˜ģžė£Œ7
ź°•ģ˜ģžė£Œ7ź°•ģ˜ģžė£Œ7
ź°•ģ˜ģžė£Œ7
Ā 
Presentation
PresentationPresentation
Presentation
Ā 
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
Ā 
Creating a Facebook Clone - Part XXXIII - Transcript.pdf
Creating a Facebook Clone - Part XXXIII - Transcript.pdfCreating a Facebook Clone - Part XXXIII - Transcript.pdf
Creating a Facebook Clone - Part XXXIII - Transcript.pdf
Ā 
Given the following codepackage data1;import java.util.;p.pdf
Given the following codepackage data1;import java.util.;p.pdfGiven the following codepackage data1;import java.util.;p.pdf
Given the following codepackage data1;import java.util.;p.pdf
Ā 
A Skeptics guide to functional style javascript
A Skeptics guide to functional style javascriptA Skeptics guide to functional style javascript
A Skeptics guide to functional style javascript
Ā 

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

Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
Ā 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
Ā 
Finology Group ā€“ Insurtech Innovation Award 2024
Finology Group ā€“ Insurtech Innovation Award 2024Finology Group ā€“ Insurtech Innovation Award 2024
Finology Group ā€“ Insurtech Innovation Award 2024The Digital Insurer
Ā 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
Ā 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel AraĆŗjo
Ā 
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
Ā 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
Ā 
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
Ā 
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
Ā 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
Ā 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
Ā 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
Ā 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
Ā 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
Ā 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
Ā 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
Ā 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
Ā 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
Ā 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
Ā 

Recently uploaded (20)

+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...
Ā 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
Ā 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
Ā 
Finology Group ā€“ Insurtech Innovation Award 2024
Finology Group ā€“ Insurtech Innovation Award 2024Finology Group ā€“ Insurtech Innovation Award 2024
Finology Group ā€“ Insurtech Innovation Award 2024
Ā 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
Ā 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Ā 
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
Ā 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
Ā 
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
Ā 
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
Ā 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
Ā 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
Ā 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
Ā 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
Ā 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Ā 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
Ā 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Ā 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
Ā 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
Ā 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
Ā 

How do I - Create a List of Items - Transcript.pdf

  • 1. How do I? In this short video Iā€™ll review the basics of creating a list of items in Codename One. But there is a catch, Codename One has a List class and we wonā€™t be using it. The list class is designed for a very elaborate type of list that isnā€™t as useful for common day devices. Unless you have a very extreme and specific use case you probably shouldnā€™t use it as it is slower & harder to use than the alternative!
  • 2. Create a List Of Items In this short video Iā€™ll review the basics of creating a list of items in Codename One. But there is a catch, Codename One has a List class and we wonā€™t be using it. The list class is designed for a very elaborate type of list that isnā€™t as useful for common day devices. Unless you have a very extreme and specific use case you probably shouldnā€™t use it as it is slower & harder to use than the alternative!
  • 3. List? āœ¦Donā€™t use com.codename1.ui.List! āœ¦Use box layout Y and components āœ¦Use InfiniteScrollAdapter or InfiniteContainer for larger sets Ā© Codename One 2017 all rights reserved In this short video Iā€™ll review the basics of creating a list of items in Codename One. But there is a catch, Codename One has a List class and we wonā€™t be using it. The list class is designed for a very elaborate type of list that isnā€™t as useful for common day devices. Unless you have a very extreme and specific use case you probably shouldnā€™t use it as it is slower & harder to use than the alternative! Instead weā€™ll use the box layout on the Y axis and add components to it. Iā€™ll focus on multi-button as this is a very common component for this type of use but you can add any custom component you want. In larger sets we can use infinite container or infinite scroll adapter. This allows us to fetch elements dynamically and avoid the overhead of creating hundreds or thousands of components at once.
  • 4. Form hi = new Form("Basic List", new BorderLayout()); Container list = new Container(BoxLayout.y()); list.setScrollableY(true); for(int iter = 0 ; iter < 1000 ; iter++) { MultiButton mb = new MultiButton("List entry " + iter); mb.setTextLine2("Further details...."); list.add(mb); } hi.add(CENTER, list); hi.show(); Hello List Lets start with a hello world for a box layout list. This is pretty standard Codename One code, lets go over the diļ¬€erent pieces. First we create the list container, notice we set it to scroll on the Y axis. This allows us to scroll through the list which is crucial. Notice that by default a Form is already scrollable on the Y axis but Iā€™ve set the layout to border layout which implicitly disables scrolling. Itā€™s important that scrolling shouldnā€™t ā€œnestā€ as itā€™s impossible to pick the right scrollbar with a touch interface.
  • 5. Form hi = new Form("Basic List", new BorderLayout()); Container list = new Container(BoxLayout.y()); list.setScrollableY(true); for(int iter = 0 ; iter < 1000 ; iter++) { MultiButton mb = new MultiButton("List entry " + iter); mb.setTextLine2("Further details...."); list.add(mb); } hi.add(CENTER, list); hi.show(); Hello List In this case I just added a thousand entries to the list one by one. The list is relatively simple with no actual functionality other than counting the entries
  • 6. Form hi = new Form("Basic List", new BorderLayout()); Container list = new Container(BoxLayout.y()); list.setScrollableY(true); for(int iter = 0 ; iter < 1000 ; iter++) { MultiButton mb = new MultiButton("List entry " + iter); mb.setTextLine2("Further details...."); list.add(mb); } hi.add(CENTER, list); hi.show(); Hello List Notice I place the list in the CENTER of the border layout. This is crucial as center in the border layout stretches the container to fit the screen exactly. This is the resulting list that can be scrolled up and down by swiping.
  • 7. Form hi = new Form("Infinite List", new BorderLayout()); Container list = new InfiniteContainer() { @Override public Component[] fetchComponents(int index, int amount) { Component[] more = new Component[amount]; for(int iter = 0 ; iter < amount ; iter++) { MultiButton mb = new MultiButton("List entry " + (index + iter)); mb.setTextLine2("Further details...."); more[iter] = mb; } return more; } }; hi.add(CENTER, list); hi.show(); Infinite List Thatā€™s all good and well but in the real world we need lists to be more dynamic than that. We need to fetch data in batches. Thatā€™s why we have the infinite container class which allows us to fetch components as the user scrolls through the list. This is the exact same code from before but it creates the list entries in batches instead of as a single block. The fetchComponents method is invoked with an index in the list and the amount of elements to return. It then creates and returns those elements. This implicitly adds the elements as we scroll and implements the pull to refresh functionality.
  • 8. public Component[] fetchComponents(int index, int amount) { Component[] more = new Component[amount]; for(int iter = 0 ; iter < amount ; iter++) { int offset = index + iter; MultiButton mb = new MultiButton("List entry " + offset); mb.setTextLine2("Further details...."); FontImage.setMaterialIcon(mb, FontImage.MATERIAL_PERSON); mb.addActionListener(ee -> ToastBar.showMessage("Clicked: " + offset, FontImage.MATERIAL_PERSON)); more[iter] = mb; } return more; } Events/Icons This might be obvious but just in case you donā€™t know you can set an icon for every entry and just add an action listener to get events for a specific entry in the list. This is very convenient. This is relatively simple in terms of design, you can check out some of the more elaborate design of a list we have in the kitchen sink demo.
  • 9. Form hi = new Form("Contacts List", new BorderLayout()); final FontImage placeholderImage = FontImage.createMaterial(FontImage.MATERIAL_PERSON, "Label", 6); Container list = new InfiniteContainer() { private Contact[] contacts; public Component[] fetchComponents(int index, int amount) { if(index == 0) // for pull for refresh by fetching the contacts over again contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false); if(index + amount > contacts.length) { amount = contacts.length - index; if(amount <= 0) { // we reached the end of the infinite contacts return null; } } Component[] more = new Component[amount]; for(int iter = 0 ; iter < amount ; iter++) { int offset = index + iter; MultiButton mb = new MultiButton(contacts[offset].getDisplayName()); String contactId = contacts[iter].getId(); mb.setIcon(placeholderImage); Display.getInstance().callSeriallyOnIdle(() -> { Contact cnt=Display.getInstance().getContactById(contactId,false,true,false,false,false); Image i = cnt.getPhoto(); if(i != null) mb.setIcon(i.fill(placeholderImage.getWidth(), placeholderImage.getHeight())); }); more[iter] = mb; } Contacts List Up until now we did simple demos, this is a screenshot of a contacts list from my device using this sort of API and it was generated with this code. Notice I blurred a few entries since these are my actual phone contacts and Iā€™d like to keep their privacyā€¦ This is done with the code here, letā€™s go over it.
  • 10. Form hi = new Form("Contacts List", new BorderLayout()); final FontImage placeholderImage = FontImage.createMaterial(FontImage.MATERIAL_PERSON, "Label", 6); Container list = new InfiniteContainer() { private Contact[] contacts; public Component[] fetchComponents(int index, int amount) { if(index == 0) // for pull for refresh by fetching the contacts over again contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false); if(index + amount > contacts.length) { amount = contacts.length - index; if(amount <= 0) { // we reached the end of the infinite contacts return null; } } Component[] more = new Component[amount]; for(int iter = 0 ; iter < amount ; iter++) { int offset = index + iter; MultiButton mb = new MultiButton(contacts[offset].getDisplayName()); String contactId = contacts[iter].getId(); mb.setIcon(placeholderImage); Display.getInstance().callSeriallyOnIdle(() -> { Contact cnt=Display.getInstance().getContactById(contactId,false,true,false,false,false); Image i = cnt.getPhoto(); if(i != null) mb.setIcon(i.fill(placeholderImage.getWidth(), placeholderImage.getHeight())); }); more[iter] = mb; } Contacts List First we need a placeholder image for the common case where a contact doesnā€™t have a profile picture or when we are still loading the profile picture.
  • 11. Form hi = new Form("Contacts List", new BorderLayout()); final FontImage placeholderImage = FontImage.createMaterial(FontImage.MATERIAL_PERSON, "Label", 6); Container list = new InfiniteContainer() { private Contact[] contacts; public Component[] fetchComponents(int index, int amount) { if(index == 0) // for pull for refresh by fetching the contacts over again contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false); if(index + amount > contacts.length) { amount = contacts.length - index; if(amount <= 0) { // we reached the end of the infinite contacts return null; } } Component[] more = new Component[amount]; for(int iter = 0 ; iter < amount ; iter++) { int offset = index + iter; MultiButton mb = new MultiButton(contacts[offset].getDisplayName()); String contactId = contacts[iter].getId(); mb.setIcon(placeholderImage); Display.getInstance().callSeriallyOnIdle(() -> { Contact cnt=Display.getInstance().getContactById(contactId,false,true,false,false,false); Image i = cnt.getPhoto(); if(i != null) mb.setIcon(i.fill(placeholderImage.getWidth(), placeholderImage.getHeight())); }); more[iter] = mb; } Contacts List When we are in the first element which will happen when the form loads or after a ā€œpull to refreshā€ I load the contacts. Notice I could have used if contacts equals null but that would have done nothing in the case of pull to refresh as contacts would have been initialized already. By checking against zero I implicitly support the pull to refresh behavior which just calls the fetch method over again. The contacts API can be a bit slow sometimes which is why you shouldnā€™t fetch ā€œeverythingā€ with one request. Thatā€™s why the method accepts all of these boolean values to indicate what we need from the contact itself. Setting all of these to true will slow you down significantly so you should generally load just what you need which in this case is contacts with a phone number and full name.
  • 12. Form hi = new Form("Contacts List", new BorderLayout()); final FontImage placeholderImage = FontImage.createMaterial(FontImage.MATERIAL_PERSON, "Label", 6); Container list = new InfiniteContainer() { private Contact[] contacts; public Component[] fetchComponents(int index, int amount) { if(index == 0) // for pull for refresh by fetching the contacts over again contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false); if(index + amount > contacts.length) { amount = contacts.length - index; if(amount <= 0) { // we reached the end of the infinite contacts return null; } } Component[] more = new Component[amount]; for(int iter = 0 ; iter < amount ; iter++) { int offset = index + iter; MultiButton mb = new MultiButton(contacts[offset].getDisplayName()); String contactId = contacts[iter].getId(); mb.setIcon(placeholderImage); Display.getInstance().callSeriallyOnIdle(() -> { Contact cnt=Display.getInstance().getContactById(contactId,false,true,false,false,false); Image i = cnt.getPhoto(); if(i != null) mb.setIcon(i.fill(placeholderImage.getWidth(), placeholderImage.getHeight())); }); more[iter] = mb; } Contacts List The infinite container has no idea how many elements we might have. So we need to check if the amount of elements requested exceeds the total and if the index is out of bounds. If the former is true we need to reduce the amount and return a smaller array. If the latter is true we need to return null which will stop future calls to fetch components unless pull to refresh is triggered again.
  • 13. Form hi = new Form("Contacts List", new BorderLayout()); final FontImage placeholderImage = FontImage.createMaterial(FontImage.MATERIAL_PERSON, "Label", 6); Container list = new InfiniteContainer() { private Contact[] contacts; public Component[] fetchComponents(int index, int amount) { if(index == 0) // for pull for refresh by fetching the contacts over again contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false); if(index + amount > contacts.length) { amount = contacts.length - index; if(amount <= 0) { // we reached the end of the infinite contacts return null; } } Component[] more = new Component[amount]; for(int iter = 0 ; iter < amount ; iter++) { int offset = index + iter; MultiButton mb = new MultiButton(contacts[offset].getDisplayName()); String contactId = contacts[iter].getId(); mb.setIcon(placeholderImage); Display.getInstance().callSeriallyOnIdle(() -> { Contact cnt=Display.getInstance().getContactById(contactId,false,true,false,false,false); Image i = cnt.getPhoto(); if(i != null) mb.setIcon(i.fill(placeholderImage.getWidth(), placeholderImage.getHeight())); }); more[iter] = mb; } Contacts List The rest is pretty close to the code we had before where we loop and create multi buttons but in this case we just fill them up with the content details and the placeholder image.
  • 14. Form hi = new Form("Contacts List", new BorderLayout()); final FontImage placeholderImage = FontImage.createMaterial(FontImage.MATERIAL_PERSON, "Label", 6); Container list = new InfiniteContainer() { private Contact[] contacts; public Component[] fetchComponents(int index, int amount) { if(index == 0) // for pull for refresh by fetching the contacts over again contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false); if(index + amount > contacts.length) { amount = contacts.length - index; if(amount <= 0) { // we reached the end of the infinite contacts return null; } } Component[] more = new Component[amount]; for(int iter = 0 ; iter < amount ; iter++) { int offset = index + iter; MultiButton mb = new MultiButton(contacts[offset].getDisplayName()); String contactId = contacts[iter].getId(); mb.setIcon(placeholderImage); Display.getInstance().callSeriallyOnIdle(() -> { Contact cnt=Display.getInstance().getContactById(contactId,false,true,false,false,false); Image i = cnt.getPhoto(); if(i != null) mb.setIcon(i.fill(placeholderImage.getWidth(), placeholderImage.getHeight())); }); more[iter] = mb; } Contacts List However, you might recall we didnā€™t fetch the image for the contact and that might be pretty expensive to loadā€¦ So the trick is to call this method on a button by button case where we fetch ONLY the image but we donā€™t just invoke that as it would kill performance. For this we use the new callSeriallyOnIdle() method. This method works like callSerially by performing the code in the next event dispatch thread cycle. However, in this case the code will only occur when the phone is idle and there are no other urgent events.
  • 15. Form hi = new Form("Contacts List", new BorderLayout()); final FontImage placeholderImage = FontImage.createMaterial(FontImage.MATERIAL_PERSON, "Label", 6); Container list = new InfiniteContainer() { private Contact[] contacts; public Component[] fetchComponents(int index, int amount) { if(index == 0) // for pull for refresh by fetching the contacts over again contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false); if(index + amount > contacts.length) { amount = contacts.length - index; if(amount <= 0) { // we reached the end of the infinite contacts return null; } } Component[] more = new Component[amount]; for(int iter = 0 ; iter < amount ; iter++) { int offset = index + iter; MultiButton mb = new MultiButton(contacts[offset].getDisplayName()); String contactId = contacts[iter].getId(); mb.setIcon(placeholderImage); Display.getInstance().callSeriallyOnIdle(() -> { Contact cnt=Display.getInstance().getContactById(contactId,false,true,false,false,false); Image i = cnt.getPhoto(); if(i != null) mb.setIcon(i.fill(placeholderImage.getWidth(), placeholderImage.getHeight())); }); more[iter] = mb; } Contacts List So if we are in idle state we can just ask for the contacts image using the specific API then fill up the UI. Since this is an infinite list this will only be invoked for the ā€œamountā€ number of entries per cycle and that means it should be reasonably eļ¬ƒcient.
  • 16. Component[] more = new Component[amount]; for(int iter = 0 ; iter < amount ; iter++) { int offset = index + iter; MultiButton mb = new MultiButton(contacts[offset].getDisplayName()); String contactId = contacts[iter].getId(); mb.setIcon(placeholderImage); Display.getInstance().callSeriallyOnIdle(() -> { Contact cnt=Display.getInstance().getContactById(contactId,true,true,false,false,false); Image i = cnt.getPhoto(); if(i != null) mb.setIcon(i.fill(placeholderImage.getWidth(), placeholderImage.getHeight())); }); more[iter] = mb; } return more; } }; hi.add(CENTER, list); hi.show(); Contacts List Moving to the next page we can see that not much is left, we just return the array and add the list to the center. I didnā€™t spend much time on refinement and some of the nicer eļ¬€ects you can achieve but you can check out the kitchen sink demo where the contacts section features a swipe UI with many special eļ¬€ects such as generated icons per letter.
  • 17. String searchString; public void start() { if(current != null){ current.show(); return; } Form hi = new Form("Contacts List", new BorderLayout()); final FontImage placeholderImage = FontImage.createMaterial( FontImage.MATERIAL_PERSON, "Label", 6); InfiniteContainer list = new InfiniteContainer() { private Contact[] contacts; public Component[] fetchComponents(int index, int amount) { if(index == 0) { contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false); if(searchString != null && searchString.length() > 0) { ArrayList<Contact> cts = new ArrayList<>(); searchString = searchString.toLowerCase(); for(Contact c : contacts) { if(c.getDisplayName().toLowerCase().indexOf(searchString) > -1) { cts.add(c); } } contacts = new Contact[cts.size()]; cts.toArray(contacts); } } if(index + amount > contacts.length) { amount = contacts.length - index; if(amount <= 0) { // we reached the end of the infinite contacts return null; } } Component[] more = new Component[amount]; for(int iter = 0 ; iter < amount ; iter++) { int offset = index + iter; MultiButton mb = new MultiButton(contacts[offset].getDisplayName()); String contactId = contacts[iter].getId(); mb.setIcon(placeholderImage); Display.getInstance().callSeriallyOnIdle(() -> { Contact cnt=Display.getInstance().getContactById(contactId,true,true,false,false,false); Image i = cnt.getPhoto(); if(i != null) mb.setIcon(i.fill(placeholderImage.getWidth(), placeholderImage.getHeight())); }); more[iter] = mb; } return more; } }; hi.getToolbar().addSearchCommand(e -> { searchString = (String)e.getSource(); list.refresh(); }); hi.add(CENTER, list); hi.show(); Search Adding search to the infinite list is pretty easy
  • 18. String searchString; public void start() { if(current != null){ current.show(); return; } Form hi = new Form("Contacts List", new BorderLayout()); final FontImage placeholderImage = FontImage.createMaterial( FontImage.MATERIAL_PERSON, "Label", 6); InfiniteContainer list = new InfiniteContainer() { private Contact[] contacts; public Component[] fetchComponents(int index, int amount) { if(index == 0) { contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false); if(searchString != null && searchString.length() > 0) { ArrayList<Contact> cts = new ArrayList<>(); searchString = searchString.toLowerCase(); for(Contact c : contacts) { if(c.getDisplayName().toLowerCase().indexOf(searchString) > -1) { cts.add(c); } } contacts = new Contact[cts.size()]; cts.toArray(contacts); } } Search We need a search string variable that is both modifiable and accessible in the inner class so I added a member to the parent class.
  • 19. String searchString; public void start() { if(current != null){ current.show(); return; } Form hi = new Form("Contacts List", new BorderLayout()); final FontImage placeholderImage = FontImage.createMaterial( FontImage.MATERIAL_PERSON, "Label", 6); InfiniteContainer list = new InfiniteContainer() { private Contact[] contacts; public Component[] fetchComponents(int index, int amount) { if(index == 0) { contacts = Display.getInstance().getAllContacts(true, true, false, false, false, false); if(searchString != null && searchString.length() > 0) { ArrayList<Contact> cts = new ArrayList<>(); searchString = searchString.toLowerCase(); for(Contact c : contacts) { if(c.getDisplayName().toLowerCase().indexOf(searchString) > -1) { cts.add(c); } } contacts = new Contact[cts.size()]; cts.toArray(contacts); } } Search The rest of the code is identical, I just filter the basic contacts entry. A change in search will refresh the list and invoke fetch components for index zero. If in this case I have a search filter I can loop over the contacts and filter them into a new array list. I can then create a new smaller contacts array that matches the search.
  • 20. hi.getToolbar().addSearchCommand(e -> { searchString = (String)e.getSource(); list.refresh(); }); hi.add(CENTER, list); hi.show(); } Search The search string can be bound to the variable using the toolbar search API thatā€™s builtin. The call to refresh has a similar eļ¬€ect to pull to refresh. It allows me to filter the list dynamically and eļ¬ƒciently.
  • 21. Thank You! Thanks for watching, I hope you found this helpful