2

I'm working on a blackberry application. I have a header which you can see in the following picture, with low resolution it takes the space more than the width, currently testing on BB Bold 9900 Simulator. So I tried using the following code to prevent UI destruction.

Questions:

  1. Is it the correct code to prevent UI destruction?
  2. If yes then by using this code how can we align the button to right and logo to left.

Which design/UI should I follow to prevent UI destruction in different resolution devices?

ImageButton Login = new ImageButton(configModel.getLoginButton(), FOCUSABLE, "login.png", "plogin.png",0x9cbe95);
HorizontalFieldManager hfm = new HorizontalFieldManager(Field.FIELD_HCENTER);
HorizontalFieldManager kenexaLogoHfm = new HorizontalFieldManager(hfm.FIELD_LEFT);
HorizontalFieldManager loginButtonHfm = new HorizontalFieldManager(hfm.FIELD_RIGHT);

Bitmap logo = Bitmap.getBitmapResource("logo.png");
NullField nullField = new NullField();
BitmapField kenexaLogo = new BitmapField(logo);

kenexaLogoHfm.add(new LabelField("", NON_FOCUSABLE));
kenexaLogoHfm.add(kenexaLogo);
kenexaLogoHfm.add(nullField);

loginButtonHfm.add(Login);

hfm.setPadding(0, 5, 0, 5);
hfm.add(kenexaLogoHfm);
hfm.add(loginButtonHfm)
add(hfm);

enter image description here

Following is the code for ImageButton

public class ImageButton extends Field{

        //Image Button Class 
        private String _label;
        private int _labelHeight;
        private int _labelWidth;
        private Font _font;

        private Bitmap _currentPicture;
        private Bitmap _onPicture;
        private Bitmap _offPicture;
        int color;

        public ImageButton(String text, long style ,String img, String img_hvr, int color){
            super(style);

            _offPicture = Bitmap.getBitmapResource(img);
            _onPicture = Bitmap.getBitmapResource(img_hvr);

            _font = Font.getDefault().derive(Font.BOLD, 7, Ui.UNITS_pt);
            _label = text;


            _labelHeight = _onPicture.getHeight();  
            _labelWidth = _onPicture.getWidth();

            this.color = color;

            _currentPicture = _offPicture;
        }
        public void setImage(String img){

            _offPicture = Bitmap.getBitmapResource(img); 
            _currentPicture = _offPicture;
        }

        /**
         * @return The text on the button
         */
        public void setText(String text){
            _label = text;
        }
            String getText(){
            return _label;
        }

        /**
         * Field implementation.
         * @see net.rim.device.api.ui.Field#getPreferredHeight()
         */
        public int getPreferredHeight(){
            return _labelHeight;
        }
        /**
         * Field implementation.
         * @see net.rim.device.api.ui.Field#getPreferredWidth()
         */
        public int getPreferredWidth(){
            return _labelWidth;
        }

        /**
         * Field implementation.  Changes the picture when focus is gained.
         * @see net.rim.device.api.ui.Field#onFocus(int)
         */
        protected void onFocus(int direction) {

             _currentPicture = _onPicture;
          //  invalidate();
            super.onFocus(direction);
        }

        /**
         * Field implementation.  Changes picture back when focus is lost.
         * @see net.rim.device.api.ui.Field#onUnfocus()
         */
        protected void onUnfocus() {
            _currentPicture = _offPicture;
            invalidate();
            super.onUnfocus();
        }

        /**
         * Field implementation.  
         * @see net.rim.device.api.ui.Field#drawFocus(Graphics, boolean)
         */
//      protected void drawFocus(Graphics graphics, boolean on) {
//          // Do nothing
//      }
        protected void drawFocus(Graphics graphics, boolean on) {
            if (on) {
                     //draw your own custom focus.
                    }
                }
        /**
         * Field implementation.
         * @see net.rim.device.api.ui.Field#layout(int, int)
         */
        protected void layout(int width, int height) {
            setExtent(Math.min( width, getPreferredWidth()),
            Math.min( height, getPreferredHeight()));
        }
        /**
         * Field implementation.
         * @see net.rim.device.api.ui.Field#paint(Graphics)
         */
        protected void paint(Graphics graphics){      
            // First draw the background colour and picture
            graphics.setColor(this.color);
            graphics.fillRect(0, 0, getWidth(), getHeight());
            graphics.drawBitmap(0, 0, getWidth(), getHeight(), _currentPicture, 0, 0);

            // Then draw the text
            graphics.setColor(Color.WHITE);
            graphics.setFont(_font);
            graphics.setFont(graphics.getFont().derive(Font.BOLD)); 
            graphics.drawText(_label, 5,9,
                (int)( getStyle() & DrawStyle.ELLIPSIS | DrawStyle.VALIGN_MASK | DrawStyle.HALIGN_MASK),
                getWidth() - 6 );

        }

        /**
         * Overridden so that the Event Dispatch thread can catch this event
         * instead of having it be caught here..
         * @see net.rim.device.api.ui.Field#navigationClick(int, int)
         */
        protected boolean navigationClick(int status, int time){
            fieldChangeNotify(1);
            return true;
        } 
}
Ahmad Shahwaiz
  • 1,432
  • 1
  • 17
  • 35
  • you want the login button on the right side of screen ? – Rince Thomas May 14 '13 at 09:11
  • yes and logo to the left, by using this code(horizontal managers). Will it not effect in other resolution devices? – Ahmad Shahwaiz May 14 '13 at 09:31
  • use justification field manager. – Rince Thomas May 14 '13 at 09:45
  • It takes only 2 fields, I have other headers having 3,4,5 items in the header. Waiting for the generic solution. – Ahmad Shahwaiz May 14 '13 at 09:46
  • @AhmadShahwaiz you mentioned how the UI should look only when there is 2 fields (Q2 - how can we align the button to right and logo to left). But didn't mention how the UI should look when there will be more fields. You may need to extend `net.rim.device.api.ui.Manager`, and implement `protected final void layout(int width, int height)` to layout all of it's child fields according to your need. – Rupak May 14 '13 at 21:47

1 Answers1

2

I would recommend getting rid of a couple of unnecessary HorizontalFieldManager objects, and just using this code:

  HorizontalFieldManager hfm = new HorizontalFieldManager(Field.USE_ALL_WIDTH);
  VerticalFieldManager vfm = new VerticalFieldManager(Field.USE_ALL_WIDTH);

  Bitmap logo = Bitmap.getBitmapResource("logo.png");
  BitmapField kenexaLogo = new BitmapField(logo, Field.FIELD_LEFT);
  
  hfm.add(new NullField());  // to take focus from login button
  hfm.add(kenexaLogo);
  vfm.add(new ButtonField("Login", Field.FIELD_RIGHT));
  hfm.add(vfm);
  
  hfm.setPadding(0, 5, 0, 5);
  add(hfm);

Note: I had to create a new ButtonField, because you didn't show how your login button was created (in the original question), and it's important, here.

The problem is that a HorizontalFieldManager tries to be efficient with the space it uses. So, if you only add two real fields (the logo, and the button), and those are not enough to fill the width, it's not going to put the button on the right.

You need to add a VerticalFieldManager to your HoriztonalFieldManager, tell it to use all available width, and then pass it the button, which has been created with the FIELD_RIGHT flag. Those flags for fields tell their parent containers where to lay them out. The VerticalFieldManager will respect FIELD_RIGHT and put the login button at the right, as you wish.

More

I might also suggest that instead of hard coding a 5 pixel right and left padding, you set a padding constant that's a given percentage of screen width:

int pad = Display.getWidth() / 100;
hfm.setPadding(0, pad, 0, pad);

but, that's a separate issue.

Another thing I find useful when trying to debug layout problems like this is to set a different background color on each manager or field in my layout. That helps you see and understand what's happening. Just use this:

hfm.setBackground(BackgroundFactory.createSolidBackground(Color.RED));  // TODO: remove!
Community
  • 1
  • 1
Nate
  • 31,017
  • 13
  • 83
  • 207
  • superb! I have added the image button class which I was using and just had to pass the Field.Field_RIGHT and it worked like a charm. But now there is another issue occurring related to it. The whole VFM is now an click Event of the Login button. In the VFM where ever I click it fires the LoginButton Click Event. How to stop this? Its a major issue now. – Ahmad Shahwaiz May 15 '13 at 07:47
  • And if you could tell more about giving the percentages of the screen width? Because I have many setMargins in my Code. Also if there are 3 or 4 items in the header who to handle them, may be giving the percentages to the setMargin ? – Ahmad Shahwaiz May 15 '13 at 07:55
  • 1
    First about your second question: in the **More** section of my answer, I talk about this. If you build an app for many different screen sizes, you might not want to set the padding to 5 pixels on all of them. 5 pixels of padding on a 360 px wide screen looks different than 5 pixels of padding on a 640 px wide screen. So, the example code I show calculates a padding constant (`pad`), that is equal to 1% of the screen's width, rounded down. So, it will give padding of 3px on a 360px wide screen, and 6 px on a 640px wide screen. The class that holds your header fields does this. – Nate May 15 '13 at 08:08
  • I appreciate and I understood, for the loginButton I'm using FieldChangeListener loginListener = new FieldChangeListener() { public void fieldChanged(Field field, int context) { //Dialog.alert("Clicked FIred"); }} Login.setChangeListener(loginListener); Does it have to change to something else like buttonListener specific to the button not the VFM Field? – Ahmad Shahwaiz May 15 '13 at 08:10
  • On your first question, I think that's a problem with the way you have implemented your `ImageButton` class. That's really a separate question, and isn't related to the problem of aligning the button to the screen's right. Also, since you didn't post that as part of the original question, I would really recommend making a completely new question, where you post your `ImageButton` class, and explain the problem with clicks, when it's contained by a `VerticalFieldManager`. If you ask in the next 30 minutes, I can try to answer it. – Nate May 15 '13 at 08:11