I'm working on a blackberry project and for that I need to create grid layout. I'm working on "Blackberry java sdk".
I'm using this code
public class GridScreen extends UiApplication {
// main method
public static void main(String[] args) {
GridScreen theApp = new GridScreen();
UiApplication.getUiApplication().pushScreen(new GFMScreen());
theApp.enterEventDispatcher();
}
}
// VFM
class GFMScreen extends MainScreen {
public GFMScreen() {
// this doesnt do anything for VCENTER!!
//super(Field.USE_ALL_HEIGHT);
// create a grid field manager, with 2 cols and 0 style param for super class
// style of Manager.FIELD_VCENTER | Field.USE_ALL_HEIGHT doesnt do a thing!
int columns = 2;
final GridFieldManager gfm = new GridFieldManager(columns, 0);
// add some items to the screen
int size = 6;
BitmapField[] fRay = new BitmapField[size];
for (int i = 0; i < size; i++) {
// create an bitmap field that's centered H + V (inside grid space)
fRay[i] = new BitmapField(loadBitmap("images/" + (i + 1) + ".png"),
Field.FIELD_HCENTER | Field.FIELD_VCENTER | Field.FOCUSABLE);
gfm.add(fRay[i]);
}
// set padding on top/bottom
{
// add gfm to screen - this does not center the gfm on the screen... is top aligned no matter what!
add(gfm);
int gfmHeight = 48 * (size / columns);
int borderHeight = (Display.getHeight() - gfmHeight) / 2;
gfm.setBorder(BorderFactory.createSimpleBorder(
new XYEdges(borderHeight, 0, borderHeight, 0),
Border.STYLE_TRANSPARENT));
System.out.println("border=" + borderHeight);
System.out.println("display=" + Display.getHeight());
System.out.println("gfm=" + gfmHeight);
}
}
/** #param res eg "images/icon.png" */
public static Bitmap loadBitmap(String res) {
EncodedImage img = EncodedImage.getEncodedImageResource(res);
return img.getBitmap();
}
}// end class
What is wrong in this code?
Is there any best approch to create grid layout in BlackBerry.
In above code error is "Display.getHeight() is not define".
Hope this code helps:
Bitmap[] images = new Bitmap[6];
for ((int i = 0; i < 6; i++) {
string filename = "images/" + String.valueOf(i + 1) + ".png";
images[i] = Bitmap.getBitmapResource(filename);
}
}
Related
I am customizing Badge in TabbedPage. I have now added the red dot from inheriting UIView. However how can I Add Text inside that Frame. Xamarin iOS
MyTabbedPageRenderer.cs
public static class TabbarExtensions
{
readonly static int tabBarItemTag = 9999;
public static void addItemBadge(this UITabBar tabbar, int index)
{
if (tabbar.Items != null && tabbar.Items.Length == 0) return;
if (index >= tabbar.Items.Length) return;
removeItemBadge(tabbar, index);
var badgeView = new UIView();
badgeView.Tag = tabBarItemTag + index;
badgeView.Layer.CornerRadius = 7;
badgeView.BackgroundColor = UIColor.Red;
var tabFrame = tabbar.Frame;
var percentX = (index + 0.56) / tabbar.Items.Length;
var x = percentX * tabFrame.Width;
var y = tabFrame.Height * 0.05;
badgeView.Frame = new CoreGraphics.CGRect(x, y, 13, 13);
tabbar.AddSubview(badgeView);
//var badgeView = new UILabel();
//badgeView.Tag = tabBarItemTag + index;
//badgeView.BackgroundColor = UIColor.Red;
//var tabFrame = tabbar.Frame;
//var percentX = (index + 0.56) / tabbar.Items.Length;
//var x = percentX * tabFrame.Width;
//var y = tabFrame.Height * 0.05;
//badgeView.Text = "1";
//badgeView.TextAlignment = UITextAlignment.Center;
//badgeView.TextColor = UIColor.White;
//badgeView.Font = UIFont.SystemFontOfSize(10);
//tabbar.AddSubview(badgeView);
}
public static bool removeItemBadge(this UITabBar tabbar, int index)
{
foreach (var subView in tabbar.Subviews)
{
if (subView.Tag == tabBarItemTag + index)
{
subView.RemoveFromSuperview();
return true;
}
}
return false;
}
}
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
MessagingCenter.Subscribe<object, int>(this, "Add", (obj, index) => {
TabBar.addItemBadge(index);
});
MessagingCenter.Subscribe<object, int>(this, "Remove", (obj, index) => {
TabBar.removeItemBadge(index);
});
}
MainView.xaml.cs
protected override void OnAppearing()
{
base.OnAppearing();
MessagingCenter.Send<object, int>(this, "Add", 2);
}
As in my code above I tried with UILabel. However I cannot set CornerRadius for Label
Summarize how I can Add Text inside Frame. Or how can I set CornerRadius for Lable in Xamarin iOS.
Thank you!
Description picture:
If I use UILabel, I cannot set CornerRadius
If I use UIView
For UILabel, you could set the CornerRadius using the following:
badgeView.Layer.CornerRadius = 7;
badgeView.Layer.MasksToBounds = true;//add this line
For more info, you could refer to masksToBounds.
Hope it works for you.
I made a test game in unity that makes it so when I click on a button, it spawns a cylinder created from a factory class. I'm trying to make it so when I create the cylinder, its height shrinks over the next 20 seconds. Some methods I found are difficult to translate into what I'm doing. If you could lead me to the right direction, I'd very much appreciate it.
Here's my code for the cylinder class
public class Cylinder : Shape
{
public Cylinder()
{
GameObject cylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
cylinder.transform.position = new Vector3(3, 0, 0);
cylinder.transform.localScale = new Vector3(1.0f, Random.Range(1, 2)-1*Time.deltaTime, 1.0f);
cylinder.GetComponent<MeshRenderer>().material.color = Random.ColorHSV();
Destroy(cylinder, 30.0f);
}
}
This can be done with the Time.deltaTime and Vector3.Lerp in a coroutine function. Similar to Rotate GameObject over time and Move GameObject over time questions. Modified it a little bit to do just this.
bool isScaling = false;
IEnumerator scaleOverTime(Transform objectToScale, Vector3 toScale, float duration)
{
//Make sure there is only one instance of this function running
if (isScaling)
{
yield break; ///exit if this is still running
}
isScaling = true;
float counter = 0;
//Get the current scale of the object to be moved
Vector3 startScaleSize = objectToScale.localScale;
while (counter < duration)
{
counter += Time.deltaTime;
objectToScale.localScale = Vector3.Lerp(startScaleSize, toScale, counter / duration);
yield return null;
}
isScaling = false;
}
USAGE:
Will scale GameObject within 20 seconds:
StartCoroutine(scaleOverTime(cylinder.transform, new Vector3(0, 0, 90), 20f));
Check out Lerp. A general example of how to use it would be something like this:
float t = 0;
Update()
{
t += Time.deltaTime;
cylinder.localScale = new Vector3(1, Mathf.Lerp(2f, 1f, t/3f), 1); // shrink from 2 to 1 over 3 seconds;
}
You will create a new monobehaviour script and add it to your primitive. Then you wil use "Update" method of monobehaviour (or use coroutine) for change object over time.
Monobehaviour must be look like this:
public class ShrinkBehaviour : MonoBehaviour
{
bool isNeedToShrink;
Config currentConfig;
float startTime;
float totalDistance;
public void StartShrink(Config config)
{
startTime = Time.time;
currentConfig = config;
totalDistance = Vector3.Distance(currentConfig.startSize, currentConfig.destinationSize);
isNeedToShrink = true;
transform.localScale = config.startSize;
}
private void Update()
{
if (isNeedToShrink)
{
var nextSize = GetNextSize(currentConfig);
if (Vector3.Distance(nextSize, currentConfig.destinationSize) <= 0.05f)
{
isNeedToShrink = false;
return;
}
transform.localScale = nextSize;
}
}
Vector3 GetNextSize(Config config)
{
float timeCovered = (Time.time - startTime) / config.duration;
var result = Vector3.Lerp(config.startSize, config.destinationSize, timeCovered);
return result;
}
public struct Config
{
public float duration;
public Vector3 startSize;
public Vector3 destinationSize;
}
}
For using this, you must do next:
public Cylinder()
{
GameObject cylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
var shrink = cylinder.AddComponent<ShrinkBehaviour>();
shrink.StartShrink(new ShrinkBehaviour.Config() { startSize = Vector3.one * 10, destinationSize = Vector3.one * 1, duration = 20f });
cylinder.transform.position = new Vector3(3, 0, 0);
cylinder.GetComponent<MeshRenderer>().material.color = Random.ColorHSV();
Destroy(cylinder, 30.0f);
}
You must remember, monobehaviour-script must be in separate file, and must have name similar to monobehaviour-class name. For example, ShrinkBehaviour.cs;
I've built a list and inserted labels in each cell. For now the text that is too long simply disappear. I'd like to wrap the text so it is entirely visible inside each cell.
Can you please help?
update: issue solved
For those who need an answer, I used LWUIT's HTMLComponent inside a container. The HTMLComponent allows you to use HTML code. That would allow you to format your list the way you want it to be.
Here is more details on the solution.
In Java ME with LWUIT, I used a HTMLComponent to get the precise layout I wanted. The best way for me was to use an HTML Table inside the HTMLComponent. It just behaves like HTML.
String html_code = "";
html_code = "<table width='100%'>";
html_code += "<tr><td><strong>"+fullname+"</strong></td></tr>";
if (title.length()>0) { html_code += "<tr><td><i>"+title+"</i></td></tr>"; }
if (message.length()>0) { html_code += "<tr><td>"+message+"</td></tr>"; }
if (date.length()>0) { html_code += "<tr><td><i>"+date+"</i></td></tr>"; }
html_code += "</table>";
HTMLComponent html = new HTMLComponent(null);
html.setBodyText(html_code);
Just incase if you are looking for a more "elegant" solution, i found a handy resource online. I am posting here for reference purposes, but HtmlComponent does the job.
import com.sun.lwuit.Font;
/** A class supporting word wrap for MIDP. */
public class WordWrap {
Font font;
int width;
String txt;
int pos;
/**
* Initializes the WordWrap object with the given Font, the text string
* to be wrapped, and the target width.
*
* #param font: The Font to be used to calculate the character widths.
* #param txt: The text string to be wrapped.
* #param width: The line width.
*/
public WordWrap (Font font, String txt, int width) {
this.font = font;
this.txt = txt;
this.width = width;
}
/**
* returns the next line break position. If no text is left, -1 is returned.
*/
public int next () {
int i = pos;
int len = txt.length ();
if (pos >= len) return -1;
int start = pos;
while (true) {
while (i < len && txt.charAt (i) > ' ')
i++;
int w = font.stringWidth (txt.substring (start, i));
if (pos == start) {
if (w > width) {
while (font.stringWidth (txt.substring (start, --i)) > width)
{ }
pos = i;
break;
}
}
if (w <= width) pos = i;
if (w > width || i >= len || txt.charAt(i) == '\n') break;
i++;
}
return pos >= len ? pos : ++pos;
}
}
import com.sun.lwuit.Button;
import com.sun.lwuit.Component;
import com.sun.lwuit.Container;
import com.sun.lwuit.Display;
import com.sun.lwuit.Label;
import com.sun.lwuit.events.ActionListener;
import com.sun.lwuit.events.FocusListener;
import com.sun.lwuit.geom.Dimension;
import com.sun.lwuit.layouts.BoxLayout;
import com.sun.lwuit.plaf.Border;
import com.sun.lwuit.plaf.Style;
/**
*
* #author rubycube
*/
public class WrapList extends Container {
private Button hiddenButton;
private int id;
public WrapList(String text, int containerID) {
id = containerID;
this.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
this.setFocusable(false);
final Style thisContainerStyle = this.getStyle();
Border thisContainerBorder = Border.createRoundBorder(20, 20, 0xcccccc);
thisContainerStyle.setBorder(thisContainerBorder);
hiddenButton = new Button(" ");
hiddenButton.setPreferredSize(new Dimension(1, 1));
Style style = hiddenButton.getStyle();
style.setBgTransparency(0, false);
style.setBorder(Border.createEmpty());
FocusListener hiddenButtonFL = new FocusListener() {
public void focusGained(Component cmp) {
WrapList parentContainer = ((WrapList) (cmp.getParent()));
Border parentContainerBorder = Border.createRoundBorder(20, 20, 0xff6600);
Style parentContainerStyle = parentContainer.getStyle();
parentContainerStyle.setBorder(parentContainerBorder);
parentContainerStyle.setBgColor(0xff9900);
parentContainerStyle.setBgTransparency(50);
parentContainer.repaint();
}
public void focusLost(Component cmp) {
WrapList parentContainer = ((WrapList) (cmp.getParent()));
Border parentContainerBorder = Border.createRoundBorder(20, 20, 0xcccccc);
Style parentContainerStyle = parentContainer.getStyle();
parentContainerStyle.setBorder(parentContainerBorder);
parentContainerStyle.setBgTransparency(0);
parentContainer.repaint();
}
};
hiddenButton.addFocusListener(hiddenButtonFL);
Label l = new Label(text);
l.setSelectedStyle(thisContainerStyle);
//l.setUnselectedStyle(thisContainerStyle);
WordWrap ww = new WordWrap(l.getStyle().getFont(), text, (Display.getInstance().getDisplayWidth() - 10));
int si = 0;
int ei = 0;
while (true) {
int np = ww.next();
if (np == -1) {
break;
} else {
si = ei;
ei = np;
}
String lineText = text.substring(si, ei);
Label line = new Label(lineText);
line.setEndsWith3Points(false);
this.addComponent(line);
}
this.addComponent(hiddenButton);
}
public void addActionListener(ActionListener actionlistener) {
hiddenButton.addActionListener(actionlistener);
}
/**
* #return the id
*/
public int getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(int id) {
this.id = id;
}
}
Trying to make a simple number clicker control for BlackBerry 6/7, like this:
At heart it's just a text field and two buttons, with a Manager to space them out.
I know about the unsupported add-on TableManager, but it doesn't support column scans. And, the notion of using deeply-nested Managers I find... disturbing.
And, this will come up multiple times, so I wanted a simple, reusable component.
So, I built a simple Manager to contain these three components, even allowing you to provide your own textfield or buttons for stylistic reasons. The code is attached below. Obviously fancier than it needs to be but the work is all done in sublayout.
What actually happens is that the upper right of each of the 3 components appears in the correct place, but the 3 components are "shrink wrapped" to the minimum size needed to display their contents, ignoring the requested USE_ALL_WIDTH and USE_ALL_HEIGHT. This is probably a minor goofup, but how can I make these components actually USE ALL WIDTH and USE ALL HEIGHT? I have tried several variations on USE_ALL_* but not found the winning one yet. Of course any other improvements would also be welcome.
Thanks.
package layout;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.XYEdges;
import net.rim.device.api.ui.component.ButtonField;
import net.rim.device.api.ui.component.EditField;
/**
* XXX BROKEN DO NOT USE YET - layout fail, components get shrink-wrapped.
*
* NumberClicker Makes a layout with three components, like this:
* <pre>
* +-------------------+ +-------------------+
* | | | + |
* | 3 | |-------------------|
* | | |-------------------|
* | | | - |
* |-------------------| |-------------------|
* </pre>
* Note that by default, the buttons are set to increment and decrement the number in the textfield!
* #author Ian Darwin
*/
public class NumberClicker extends Manager {
private static final long SUBCOMPONENT_STYLE = Field.USE_ALL_HEIGHT | Field.USE_ALL_WIDTH;
private static final long MANAGER_STYLE = Field.FIELD_HCENTER | Field.FIELD_VCENTER;
final XYEdges MARGINS = new XYEdges(10,10,10,10);
EditField number = new EditField(SUBCOMPONENT_STYLE);
ButtonField plus = new ButtonField("+", SUBCOMPONENT_STYLE);
ButtonField minus = new ButtonField("-", SUBCOMPONENT_STYLE);
public NumberClicker() {
this(MANAGER_STYLE);
}
public NumberClicker(long style)
{
this(null, null, null, style);
}
/** Constructor allows you to provide your own three fields */
public NumberClicker(EditField number, ButtonField plus, ButtonField minus) {
this(number, plus, minus, MANAGER_STYLE);
}
/** Constructor allows you to provide your own three fields ANd override style.
* If any of the fields is null, the default value is used.
*/
public NumberClicker(EditField number, ButtonField plus, ButtonField minus, long style) {
super(style);
if (number != null) {
this.number = number;
} else {
this.number.setMargin(MARGINS); // set margins on our default, constructed above.
}
setValue(1);
add(this.number); // Nulls allowed, so must be careful to use "this." throughout this method.
if (plus != null) {
this.plus = plus;
} else {
this.plus.setMargin(MARGINS);
}
add(this.plus);
if (minus != null) {
this.minus = minus;
} else {
this.minus.setMargin(MARGINS);
}
add(this.minus);
this.plus.setRunnable(new Runnable() {
public void run() {
increment();
}
});
this.minus.setRunnable(new Runnable() {
public void run() {
decrement();
}
});
}
public void increment() {
number.setText(Integer.toString(Integer.parseInt(number.getText().trim()) + 1));
}
public void decrement() {
number.setText(Integer.toString(Integer.parseInt(number.getText().trim()) - 1));
}
/** Return the integer value of the clicker. Do not call if you are re-using this as a three-component layout manager! */
public int getValue() {
return Integer.parseInt(number.getText().trim());
}
public void setValue(int value) {
number.setText(Integer.toString(value));
}
/**
* Compute sizes and positions of subfields.
*
* Required by Manager
*/
public void sublayout(int width, int height) {
int layoutWidth = width;
int layoutHeight = Math.min(height, Display.getHeight()); // no scrolling here
System.err.println("Display:" + Display.getWidth() + "x" + Display.getHeight());
int halfX = layoutWidth / 2;
int halfY = layoutHeight / 2;
System.err.println("sublayout:" + width + "," + height + "; " + halfX + "," + halfY);
int numberWidth = halfX - number.getMarginLeft() - number.getMarginRight();
int numberHeight = layoutHeight - number.getMarginTop() - number.getMarginBottom();
layoutChild(number, numberWidth, numberHeight);
setPositionChild(number, 0 + number.getMarginLeft(), 0 + number.getMarginTop());
System.err.println(number + " " + numberWidth + "," + numberHeight + " " +number.getMarginLeft());
int plusWidth = halfX - plus.getMarginLeft() - plus.getMarginRight();
int plusHeight = halfY - plus.getMarginTop() - plus.getMarginBottom();
layoutChild(plus, plusWidth, plusHeight);
setPositionChild( plus, halfX + plus.getMarginLeft(), plus.getMarginTop());
int minusWidth = halfX - minus.getMarginLeft() - minus.getMarginRight();
int minusHeight = halfY - minus.getMarginTop() - minus.getMarginBottom();
layoutChild(minus, minusWidth, minusHeight);
// Use plus.getMarginHeight() for better alignment.
setPositionChild( minus, halfX + plus.getMarginLeft(), halfY + minus.getMarginTop() );
//setVirtualExtent(layoutWidth, height);
setExtent(layoutWidth, height);
}
public EditField getNumberField() {
return number;
}
public void setNumberField(EditField number) {
this.number = number;
}
public ButtonField getPlusField() {
return plus;
}
public void setPlusField(ButtonField plus) {
this.plus = plus;
}
public Field getMinusField() {
return minus;
}
public void setMinusField(ButtonField minus) {
this.minus = minus;
}
}
The closest thing to what you are trying to achieve is
Few notes:
EditField always use USE_ALL_WIDTH. It doesn't matter if you requested it or not. Therefore, if you want to limit its width you have override its layout() method. In my code snippet, its width is limited by the maximum chars allowed for this field's value (see CustomEditField).
ButtonField ignores USE_ALL_WIDTH and USE_ALL_HEIGHT. Its extent depends only on the text within the button. In order to achieve the effect of USE_ALL_WIDTH, you have to add horizontal padding to it.
Unfortunately, the padding trick won't work if you want to achieve the USE_ALL_HEIGHT effect. When you add vertical padding to a button, at some stage it will repeat its background vertically. If it is required, you will have to write a custom button field for it.
Also check BlackBerry's advanced UI components at this page.
Here is the code:
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.FontMetrics;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.XYEdges;
import net.rim.device.api.ui.component.ButtonField;
import net.rim.device.api.ui.component.EditField;
import net.rim.device.api.ui.decor.Border;
import net.rim.device.api.ui.decor.BorderFactory;
import net.rim.device.api.ui.text.NumericTextFilter;
public class NumberClicker extends Manager {
private class CustomEditField extends EditField {
public int getPreferredWidth() {
FontMetrics fontMetrics = new FontMetrics();
getFont().getMetrics(fontMetrics);
return getMaxSize()*fontMetrics.getMaxCharWidth();
};
public int getPreferredHeight() {
// forcing the field to be single lined
return getFont().getHeight();
}
protected void layout(int width, int height) {
super.layout(
Math.min(width, getPreferredWidth()),
Math.min(height, getPreferredHeight())
);
}
}
final XYEdges MARGINS = new XYEdges(2,2,2,2);
EditField _number;
Manager _numberManager;
ButtonField _plus;
ButtonField _minus;
public NumberClicker() {
super(0);
Font font = getFont();
font = font.derive(Font.BOLD, font.getHeight() + 10);
_number = new CustomEditField();
_number.setFilter(new NumericTextFilter());
_number.setMaxSize(1);
_number.setFont(font);
setValue(1);
_numberManager = new Manager(0) {
protected void sublayout(int width, int height) {
layoutChild(_number, width, height);
setPositionChild(_number,
Math.max(0, (width - _number.getWidth())/2),
Math.max(0, (height - _number.getHeight())/2)
);
setExtent(width, height);
}
};
_numberManager.setBorder(BorderFactory.createRoundedBorder(new XYEdges()));
_numberManager.setMargin(MARGINS);
_numberManager.add(_number);
add(_numberManager);
_plus = new ButtonField("+", 0);
_plus.setMargin(MARGINS);
add(_plus);
_minus = new ButtonField("-");
_minus.setMargin(MARGINS);
add(_minus);
_plus.setRunnable(new Runnable() {
public void run() {
increment();
}
});
_minus.setRunnable(new Runnable() {
public void run() {
decrement();
}
});
}
private void increment() {
synchronized (UiApplication.getEventLock()) { //probably not needed here. overkill.
_number.setText(Integer.toString(Integer.parseInt(_number.getText().trim()) + 1));
}
}
private void decrement() {
if (Integer.parseInt(_number.getText()) <= 0) {
return;
}
synchronized (UiApplication.getEventLock()) { //probably not needed here. overkill.
_number.setText(Integer.toString(Integer.parseInt(_number.getText().trim()) - 1));
}
}
public void setValue(int value) {
if (value < 0) {
return;
}
synchronized (UiApplication.getEventLock()) { // MUST. can be called from non UI thread.
_number.setText(Integer.toString(value));
}
}
/**
* Compute sizes and positions of subfields.
*/
public void sublayout(int width, int height) {
int heightUsed = 0;
int halfX = width / 2;
Border border = _plus.getBorder();
int plusWidth = halfX - _plus.getMarginLeft() - _plus.getMarginRight();
int plusHeight = height - _plus.getMarginTop() - _plus.getMarginBottom();
// calculate horizontal padding so the button will look like USE_ALL_WIDTH
int plusHPadding = (Math.max(0, plusWidth - _plus.getPreferredWidth() - border.getLeft() - border.getRight()))/2;
_plus.setPadding(0, plusHPadding, 0, plusHPadding);
layoutChild(_plus, plusWidth, plusHeight);
setPositionChild( _plus, halfX + _plus.getMarginLeft(), _plus.getMarginTop());
heightUsed += _plus.getHeight() + _plus.getMarginTop() + _plus.getMarginBottom();
border = _minus.getBorder();
int minusWidth = halfX - _minus.getMarginLeft() - _minus.getMarginRight();
int minusHeight = height - _plus.getHeight() - _minus.getMarginTop() - _minus.getMarginBottom();
// calculate horizontal padding so the button will look like USE_ALL_WIDTH
int minusHPadding = (Math.max(0, minusWidth - _minus.getPreferredWidth() - border.getLeft() - border.getRight()))/2;
_minus.setPadding(0, minusHPadding, 0, minusHPadding);
layoutChild(_minus, minusWidth, minusHeight);
setPositionChild( _minus, halfX + _plus.getMarginLeft(), heightUsed + _minus.getMarginTop());
heightUsed += _minus.getHeight() + _minus.getMarginTop() + _minus.getMarginBottom();
int numberWidth = halfX - _numberManager.getMarginLeft() - _numberManager.getMarginRight();
int numberHeight = heightUsed - _numberManager.getMarginTop() - _numberManager.getMarginBottom();
layoutChild(_numberManager, numberWidth, numberHeight);
setPositionChild(_numberManager, _numberManager.getMarginLeft(), _numberManager.getMarginTop());
setExtent(width, heightUsed);
}
}
Is there any way to create a Tab Menu in j2me?
I found a code but I am unable to understand it
In this code there is Tab Menu created which is in Canvas class and then Tab menu is created which is totally done in Canvas or painted. The only part I found difficult to grasp was the void go() method and then
When I try to draw anything above and below this code using paint method, it doesn't work - what's the problem?
Below is the code
// Tab Menu CANVAS class
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
public class TabMenuCanvas extends Canvas
{
TabMenu menu = null;
public TabMenuCanvas()
{
menu = new TabMenu(
new String[]{"Home", "News", "Community", "Your files", "Credits", "Events", "Blog", "Upload", "Forum Nokia"},
getWidth() - 20
);
}
protected void keyPressed(int key)
{
int gameAction = getGameAction(key);
if(gameAction == Canvas.RIGHT)
{
menu.goRight();
repaint();
}
else if(gameAction == Canvas.LEFT)
{
menu.goLeft();
repaint();
}
}
protected void paint(Graphics g)
{
g.translate(10, 30);
menu.paint(g);
g.translate(- 10, - 30);
}
}
// Tab Menu Class
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
public class TabMenu
{
int background = 0xffffff;
int bgColor = 0xcccccc;
int bgFocusedColor = 0x0000ff;
int foreColor = 0x000000;
int foreFocusedColor = 0xffffff;
int cornerRadius = 6;
int padding = 2;
int margin = 2;
Font font = Font.getDefaultFont();
int scrollStep = 20;
int selectedTab = 0; //selected tab index
int[] tabsWidth = null; //width of single tabs
int[] tabsLeft = null; //left X coordinate of single tabs
int tabHeight = 0; //height of tabs (equal for all tabs)
String[] tabs = null; //tab labels
int menuWidth = 0; //total menu width
int viewportWidth = 0; //visible viewport width
int viewportX = 0; //current viewport X coordinate
public TabMenu(String[] tabs, int width)
{
this.tabs = tabs;
this.viewportWidth = width;
initialize();
}
void initialize()
{
tabHeight = font.getHeight() + cornerRadius + 2 * padding; //[ same for all tabs]
menuWidth = 0;
tabsWidth = new int[tabs.length];
tabsLeft = new int[tabs.length];
for(int i = 0; i < tabsWidth.length; i++)
{
tabsWidth[i] = font.stringWidth(tabs[i]) + 2 * padding + 2 * cornerRadius;
tabsLeft[i] = menuWidth;
menuWidth += tabsWidth[i];
if(i > 0)
{
menuWidth += margin;
}
}
}
public void goRight()
{
go(+1);
}
public void goLeft()
{
go(-1);
}
private void go(int delta)
{
int newTab = Math.max(0, Math.min(tabs.length - 1, selectedTab + delta));
boolean scroll = true;
if(newTab != selectedTab && isTabVisible(newTab))
{
selectedTab = newTab;
if( (delta > 0 && tabsLeft[selectedTab] + tabsWidth[selectedTab] > viewportX + viewportWidth) ||
(delta < 0 && tabsLeft[selectedTab] < viewportX))
{
scroll = true;
}
else
{
scroll = false;
}
}
if(scroll)
{
viewportX = Math.max(0, Math.min(menuWidth - viewportWidth, viewportX + delta * scrollStep));
}
}
private boolean isTabVisible(int tabIndex)
{
return tabsLeft[tabIndex] < viewportX + viewportWidth &&
tabsLeft[tabIndex] + tabsWidth[tabIndex] >= viewportX;
}
public void paint(Graphics g)
{
int currentX = - viewportX;
g.setClip(0, 0, viewportWidth, tabHeight);
g.setColor(background);
g.fillRect(0, 0, viewportWidth, tabHeight);
for(int i = 0; i < tabs.length; i++)
{
g.setColor(i == selectedTab ? bgFocusedColor : bgColor);
g.fillRoundRect(currentX, 0, tabsWidth[i], tabHeight + cornerRadius, 2 * cornerRadius, 2 * cornerRadius);
g.setColor(i == selectedTab ? foreFocusedColor : foreColor);
g.drawString(tabs[i], currentX + cornerRadius + padding, cornerRadius + padding, Graphics.LEFT | Graphics.TOP);
currentX += tabsWidth[i] + margin;
}
}
}
When I try to draw anything above and below this code using paint method, it doesn't work
what of the paint methods you use to draw above and below? Pay attention that there are two methods named that way - first is in TabMenuCanvas, second is in TabMenu (second method is invoked from TabMenuCanvas#repaint).
whatever you would try to draw in TabMenuCanvas#paint will most likely be overwritten by setClip and fillRect when TabMenu#paint is invoked following repaint request
The only place where one can expect to be able to draw something visible seems to be in TabMenu#paint method, inside the clip area that is set there.
You can use GUI Libraries for J2ME,for example Lightweight User Interface Toolkit (LWUIT),Flemil have "tab menu".You can see list of GUI Libraries here.