UI Framework Reference Implementation

UI Framework Reference Implementation builds on the Hello World app that was built in the UI Framework Building Blocks set-up. These instructions provide a brief description of how to implement the UI Framework components and show some examples for each component. You can refer to the Java docs for UI Framework version 1.0.1, FCAComponents-javadoc.jar to get more details about the UI Framework API.

You can get the UI Framework sample app for use with FCA Framework version 1.0.1 at FCASample.zip or in Downloads in the Reference Implementation Source section. The sample app contains more detailed code examples for an each component and feature.

Page contents:

Prerequisites to getting started.
FCAXlet is required and the entry point for your app.
FCAForm is required, the top level UI component, all app forms extend from it.
FCAList is a component that shows items in a vertically scrolling list.
FCAGrid is a component that shows items a two-dimensional scrolling grid.
FCATabBar is a component that switches between a group of components by clicking on a tab.
FCADialog is the base class for all dialogs.
FCAAlertDialog is a component that shows a simple message dialogs with (optional) buttons.
FCAProgressDialog is a component that shows a dialog showing an animated progress indicator.
FCAKeyboard is a component that shows a dialog that renders a virtual Keyboard.
FCAJumpKeyboard is a component that shows a type of keyboard used for picking a single character.
Hard Scroll Knob events are received by FCAForm.
Installation and Execution of the FCASample App.

Prerequisites

  1. Your PC is ready to develop apps, see Set-Up to Develop Apps for the VP4R.
  2. You have the Kona emulator and/or CAN simulator. The CAN simulator is not needed to get the reference app to run, however it is worth noting that instructions are available at Kona Emulator and Sensor Simulator. Or you can just download the emulator at EmulatedKona4.1.0.zip (also available at Downloads in the Emulator & Simulator section.
  3. The UI Framework Building Block is installed and the Hello World app runs.

Top

FCAXlet

FCAXlet is the application’s entry point, sets up form handling, does all of the core resource and theme loading. FCAXlet also provides APIs or hooks for you to create your splash screen, declare your first FCAForm to be shown, identify the app resource and theme, supports on load and locale changes, as well as handles display differences for connected apps.

  1. Create your apps splash screen.
    public Component createSplashScreen() {
    		final String splashImageFile = SystemInfo.getInstance().getDeviceType() == DeviceType.HU_12
    				? "/res/splash.12.png" : "/res/splash.8.png";
    		Label bgImageLabel = null;
    		try (InputStream is = getClass().getResourceAsStream(splashImageFile)) {
    			final Image splashImage = Image.createImage(is);
    			// Construct a new label with the background image
    			bgImageLabel = new Label(splashImage);
    			// Set the label style
    			final Style style = bgImageLabel.getStyle();
    			style.setBgColor(0);
    			style.setBgTransparency(0);
    			style.setAlignment(Component.CENTER);
    			bgImageLabel.setVerticalAlignment(Component.CENTER);
    		} catch (final IOException e) {
    			logger.e(e.getMessage(), e);
    		}
    		return bgImageLabel;
    	}
    							
  2. Declare your first FCAForm to be shown.
    @Override
    	public Class< ? extends FCAForm> getMainFormClass() {
    		return MainForm.class;
    	}						
    							
  3. Identify the app resource, theme and locale.
    @Override
    	public String getResourceFilePath(final VehicleBrand vehicleBrand) {
    		// regardless vehicle brand sample app uses only one resource bundle
    		return "/fcasample.res";
    	}
    	
    	@Override
    	public String getThemeName(final VehicleBrand vehicleBrand) {
    		// regardless vehicle brand sample app uses only one theme
    		return "theme";
    	}
    	
    	@Override
    	public String l10n() {
    		return "localize";
    	}
    							
  4. Supports on load and locale changes.
    @Override
    	public void onLoad() throws Exception {
    		// TODO Auto-generated method stub
    	}
    	
    	@Override
    	public void onLocaleChange(final Locale arg0) {
    		// TODO Auto-generated method stub
    	}
    							
  5. Handles display differences for connected apps.
    @Override
    	public boolean isConnectedApp() {
    		return true;
    	}
    							

Top

FCAForm

Top level UI component. This Component extends Form and contains a special FCABreadcrumbBar component. All client app forms shall extend from it.

Provides lifecycle callbacks such as:

  • public void onCreate(Bundle params) - called on the form instance initial creation. Bundle object may contain data passed from FCAForm’s launcher.
  • public void onHide() - called when the form is hiding.
    NOTE: callbacks onShow() and onShowCompleted() from superclass com.codename1.ui.Form can be used as the opposites to onHide().
  • public void onSaveInstanceState(Bundle outState) - called before a form may be killed so that when it comes back some time in the future it can restore its state.
  • public void onRestoreInstanceState(Bundle savedInstanceState) - called after onCreate() when the form is being re-initialized from a previously saved state, given here in savedInstanceState.
  • public void onDestroy() - called when the form is destroying.

 

Additional callbacks:

  • public void onFormResult(Bundle result) - called when a next form returned the result data via call to public void finish(Bundle result).
  • protected void onBackPressed() - called when the form has detected the user's press of the back key. The default implementation simply closes the current form, but you can override this to do whatever you need.
  • public void onNewFormParams(Bundle params) - called if client uses the CLEAR_TOP flag in FormIntent when calling showForm(FormIntent, Bundle params). In such a case onCreate(Bundle params) will not be called for this form if it already exists in back stack.

 

It’s possible to setup a custom title component instead of simple label:

Container titleContainer = new Container(new CenteredBoxLayout(CenteredBoxLayout.X_AXIS));
	
	Label label1 = new Label("Custom");
	label1.getUnselectedStyle().setFgColor(Color.CYAN.getRGB());
	titleContainer.addComponent(label1);
	
	Label label2 = new Label(" Title");
	label2.getUnselectedStyle().setFgColor(Color.RED.getRGB());
	titleContainer.addComponent(label2);
	
	setTitleComponent(titleContainer);
						

 

Top

FCAList

A component that shows items in a vertically scrolling list. The items come from the FCAListArrayAdapter associated with this view.

The general use looks like:

FCAList list = new FCAList<>();
	FCAListArrayAdapter listAdapter = new FCAListArrayAdapter<>();
	// add some list items
	for (int i = 0; i < 10; i++) {
		listAdapter.add("Item #" + i);
	}
	list.setListAdapter(listAdapter);			
					

The code snippet above constructs a FCAList populated with 10 items and displays as:

Top

FCAGrid

A view that shows items a two-dimensional scrolling grid. The items in the grid come from the FCAGridArrayAdapter associated with this view.

The principles of use are nearly the same as for FCAList:

FCAGrid grid = new FCAGrid<>(/*minRows*/3, /*cols*/4);
	FCAGridArrayAdapter gridAdapter = new FCAGridArrayAdapter() {
		@Override
		protected void fillItemContainer(Container itemContainer, int position, boolean selected) {
			itemContainer.setLayout(new BorderLayout());
	
			Border border = Border.createLineBorder(2, Color.CYAN.getRGB());
			itemContainer.getUnselectedStyle().setBorder(border);
			itemContainer.getUnselectedStyle().setMargin(5, 5, 5, 5);
			itemContainer.setPreferredH(110);
	
			Label nameLabel = new Label(getItem(position));
			nameLabel.getUnselectedStyle().setAlignment(CENTER);
			itemContainer.addComponent(BorderLayout.CENTER, nameLabel);
		}
	};
	for (int i = 0; i < 42; i++) {
		gridAdapter.add("Item #" + i);
	}
	grid.setGridAdapter(gridAdapter);
					

The code snippet above constructs a FCAGrid and displays as:

You can react to an item click events via attached listener:

grid.setOnItemClickListener(new FCAArrayAdapter.OnItemClickListener() {
		@Override
		public void onItemClick(int arg0) {
			//do something
		}
	});
					

As well as FCAList, FCAGrid has built-in ability to show a given placeholder when FCAGridArrayAdapter does not provide any data:

FCAGrid grid = new FCAGrid<>(/* minRows */3, /* cols */4);
	FCAGridArrayAdapter gridAdapter = new FCAGridArrayAdapter();
	
	Label noDataLabel = new Label();
	noDataLabel.getUnselectedStyle().setAlignment(CENTER);
	noDataLabel.getUnselectedStyle().setMargin(TOP, 200);
	noDataLabel.getUnselectedStyle().setMargin(LEFT, 430);
	noDataLabel.setText("No data");
	grid.setEmptyComponent(noDataLabel);
	
	grid.setGridAdapter(gridAdapter);
					

The code snippet above constructs a FCAGrid and displays as:

Top

FCATabBar

A component that lets the user switch between a group of components by clicking on a tab with a given title and/or icon. FCATabBar provides tabbed button bar with corresponding callbacks but does not contain a tab content by itself.

A typical use of FCATabBar:

@Override
	protected void onCreate(Bundle params) {
		super.onCreate(params);
	
		setTitle("HelloForm");
		setLayout(new BorderLayout());
	
		Container contentContainer = new Container(new BorderLayout());
		Label label = new Label("Content for tab 1");
		label.getUnselectedStyle().setAlignment(CENTER);
		contentContainer.addComponent(BorderLayout.CENTER, label);
		addComponent(BorderLayout.CENTER, contentContainer);
	
		List tabButtonList = new ArrayList<>();
		for (int i = 0; i < 4; i++) {
			FCATabButton tabButton = new FCATabButton("Tab " + (i + 1));
			tabButton.setPreferredSize(new Dimension(245, 70));
			tabButtonList.add(tabButton);
		}
	
		FCATabBar tabBar = new FCATabBar(tabButtonList);
		tabBar.setOnTabSelectionListener(new FCATabBar.OnTabSelectionListener() {
	
			@Override
			public void onTabSelected(int tabIndex) {
				contentContainer.removeAll();
				Label label = new Label("Content for tab " + (tabIndex + 1));
				label.getUnselectedStyle().setAlignment(CENTER);
				contentContainer.addComponent(BorderLayout.CENTER, label);
				contentContainer.repaint();
			}
		});
	
		addComponent(BorderLayout.NORTH, tabBar);
	}
					

The code snippet above constructs a FCATabBar and displays as:

Top

FCADialog

FCADialog is the base class for all dialogs. Two crucial methods: getContentContainer() which return a container for all main content area, and getButtonContainer() which returns a container for placing dialog buttons.

Usage example:

 FCADialog dialog = new FCADialog();
	
	Container centerContainer = new Container(new FlowLayout(CENTER));
	dialog.getContentContainer().setLayout(new BorderLayout());
	dialog.getContentContainer().addComponent(BorderLayout.CENTER, centerContainer);
	centerContainer.addComponent(new Label("Message"));
	
	DialogButton button1 = new DialogButton("Button 1");
	button1.addActionListener(new ActionListener() {
	
		@Override
		public void actionPerformed(ActionEvent evt) {
			dialog.dispose();
		}
	});
	dialog.getButtonContainer().addComponent(button1);
	
	DialogButton button2 = new DialogButton("Button 2");
	button2.addActionListener(new ActionListener() {
	
		@Override
		public void actionPerformed(ActionEvent evt) {
			dialog.dispose();
		}
	});
	dialog.getButtonContainer().addComponent(button2);
	
	dialog.show();
					

The code snippet above constructs a FCADialog on the 8.4 display as:

The code snippet above constructs a FCADialog on the 12 inch display as:

Top

FCAAlertDialog

A subclass of FCADialog aimed to show quickly setup simple message dialogs with (optional) buttons.

Sample usage:

Button button = new Button("Show dialog");
	button.addActionListener(new ActionListener() {
	
		@Override
		public void actionPerformed(ActionEvent evt) {
			OnButtonClickListener buttonClickListener = new OnButtonClickListener() {
	
				@Override
				public void onClick(int id) {
					// do an action
				}
			};
	
			FCAAlertDialog alertDialog = new FCAAlertDialog.Builder()
					.setTitle("SAMPLE: Dialog Box with 1 Button")
					.setMessage("A sample AlertDialog\nwith one button.")
					.addButton("Button 1", 0, buttonClickListener)
					.create();
	
			alertDialog.show();
		}
	});
	
	addComponent(button);
					

The code snippet above constructs an alert dialog (popup) and displays as:

Top

FCAProgressDialog

A dialog showing an animated progress indicator and an optional text message.

Sample usage:

OnCancelListener onCancelListener = new OnCancelListener() {
		@Override
		public void onCancel() {
			// cancel a task
		}
	};
	
	FCAProgressDialog progressDialog = new FCAProgressDialog(
			"Please wait",
			"Cancel",
			onCancelListener);
	progressDialog.show();
					

The code snippet above constructs a progress dialog on the 8.4 inch display:

The code snippet above constructs a progress dialog on the 12 inch display:

Top

FCAKeyboard

A dialog that renders a virtual Keyboard. It handles rendering of keys and detecting key presses.

FCAKeyboard is set as default virtual keyboard on the start of FCAXlet so you don’t need to handle input requests for each input field - it’s handled internally by Codename One.

Just add the TextField component as shown below and click on it:

Label textFieldLabel = new Label("Touch the text field to show Keyboard");
	addComponent(textFieldLabel);
	
	FCAEditField editField = new FCAEditField();
	addComponent(editField);
					

The code snippet above constructs an input field that when clicked displays a keyboard, (8.4 inch display):

The code snippet above constructs an input field that when clicked displays a keyboard, (12 inch display):

Text typed in the keyboard will appear in the FCAEditField once the Enter button on the keyboard is clicked.

It’s possible to limit the keyboard by phone number input or password using a constraint.

editField.setConstraint(TextArea.PHONENUMBER);
					

The numeric keyboard shown below was built using the phone number constraint, (8.4 inch display).

The numeric keyboard shown below was built using the phone number constraint, (12 inch display).

Top

FCAJumpKeyboard

This type of keyboard used for picking a single character. For example - for jumping to some part of sorted list (e.g. contacts list or A-Z index).

Simplified example:

private void showJumpKeyboard() {
		Set filter = createListFilter();
		KeySelectionListener keySelectionListener = new KeySelectionListener() {
	
			@Override
			public void onKeySelected(String selectedSymbol) {
				handleJumpKeyboardInput(selectedSymbol);
			}
		};
		FCAJumpKeyboard jumpKeyboard = FCAJumpKeyboardManager.getInstance().createKeyboard(keySelectionListener, filter);
		jumpKeyboard.show();
	}
	
	private void handleJumpKeyboardInput(String selectedSymbol) {
		// found position of an item starting with selected character
		for (int i = 0; i < listAdapter.getCount(); i++) {
			String item = listAdapter.getItem(i);
			if (item.trim().toUpperCase().startsWith(selectedSymbol)) {
				// scroll to item
				list.setSelectedItem(i, true);
				return;
			}
		}
	}
	
	private Set createListFilter() {
		// iterate through the list and collect all unique first characters
		Set filter = new HashSet<>();
	
		for (int i = 0; i < listAdapter.getCount(); i++) {
			String item = listAdapter.getItem(i);
			String firstCharUppercase = String.valueOf(item.charAt(0));
			filter.add(firstCharUppercase);
		}
	
		return filter;
	}
					

The ABC jump form shows a list with an ABC button to display the keyboard, (8.4 inch display).

Clicking the ABC button will display the ABC jump keyboard, (8.4 inch display). The only selectable keyboard keys are the ones that have an entry in the list.

The ABC jump form and ABC jump keyboard, (12 inch display).

Top

Hard Scroll Knob

FCAForm registers itself to receive a hardware knob events while being on screen, thus it out of the box reacts to hardware back button presses.

Also, you can listen for knob events via FCAKnobListener registered at FCAForm.setKnobListener FCAKnobListener knobListener). For example - set the FCAList as the listener so it will receive scroll knob events.

In order to pass the hover state between different hoverable components use the FCAHoverOrderMediator:

  • public void requestHover(FCAHoverableContainer requestor) method will be called when some hoverable wants to get a hover state as a result of non-knob event (e.g. touch). Typical realization is - clear the hover state on previously hovered component and pass it to another (requestor).
  • public boolean yieldHover(FCAHoverableContainer requestor, Direction direction) method will be called when a hovered component wants to pass it's hovered state to another component (as a result of over-scrolling the list for example).

Top

Installation and Execution

The FCA sample app was created to give you a working example of an app that has used all of the currently available components.

  1. Download the FCA Sample App source FCASample.zip (also available at Downloads in the Reference Implementation Source section.
  2. Create an Eclipse project for the FCA Sample App source.
  3. For a clean compile add the UI Framework and Kona jars to the build path as shown.
  4. Create a new run configuration.
  5. Set the Xlet extension directory to where you stored the UI Framework jar.
  6. Download and unzip Emulator_Fonts.zip.
  7. Set the font properties to the location you unzipped the Emulator fonts.
  8. Set the verbosity level to 5. You can change this later.
  9. Select the borderless theme.
  10. Run the sample app. You should see the splash screen then the main form.

Top

Updated: 01/02/2018