Progress Bar in Blackberry from right to left

Progress Bar in Blackberry from right to left,blackberry,java-me,right-to-left,Blackberry,Java Me,Right To Left,I am developing an application which requires me to create a progress bar moving from right to left. I tried using GaugeField by filling startVal as 100 and then on decrementing it but I couldn't achieve it. Is there any way in BlackBerry say paint() method or drawRect() using timer where we can fill it from right to left?

I am developing an application which requires me to create a progress bar moving from right to left.

I tried using

GaugeField
by filling startVal as 100 and then on decrementing it but I couldn't achieve it.

Is there any way in BlackBerry say

paint()
method or
drawRect()
using timer where we can fill it from right to left?


#1

Check following code for an implementation of Custom GaugeField.

Output

Implementation of CustomGaugeField

class CustomGaugeField extends GaugeField {
    // Default constructor, need improvement
    public CustomGaugeField() {
        super("", 0, 100, 0, GaugeField.PERCENT);
    }

    // Colors
    private static final int BG_COLOR = 0xd6d7d6;
    private static final int BAR_COLOR = 0x63cb52;
    private static final int FONT_COLOR = 0x5a55c6;

    protected void paint(Graphics graphics) {
        int xProgress = (int) ((getWidth() / 100.0) * getValue());
        int xProgressInv = getWidth() - xProgress;

        // draw background
        graphics.setBackgroundColor(BG_COLOR);
        graphics.clear();

        // draw progress bar
        graphics.setColor(BAR_COLOR);
        graphics.fillRect(xProgressInv, 0, xProgress, getHeight());

        // draw progress indicator text
        String text = getValue() + "%";
        Font font = graphics.getFont();
        int xText = (getWidth() - font.getAdvance(text)) / 2;
        int yText = (getHeight() - font.getHeight()) / 2;
        graphics.setColor(FONT_COLOR);
        graphics.drawText(text, xText, yText);
    }
}


How to use

class MyScreen extends MainScreen {

    public MyScreen() {
        setTitle("Custom GaugeField Demo");
        GaugeField gField;
        for (int i = 0; i < 6; i++) {
            gField = new CustomGaugeField();
            gField.setMargin(10, 10, 10, 10);
            add(gField);
        }
        startProgressTimer();
    }

    private void startProgressTimer() {
        TimerTask ttask = new TimerTask() {
            public void run() {
                Field f;
                for (int i = 0; i < getFieldCount(); i++) {
                    f = getField(i);
                    if (f instanceof CustomGaugeField) {
                        final CustomGaugeField gField = (CustomGaugeField) f;
                        final int increment = (i + 1) * 2;
                        UiApplication.getUiApplication().invokeLater(
                            new Runnable() {
                                public void run() {
                                    gField.setValue((gField.getValue() + increment) % 101);
                                }
                            }
                        );
                    }
                }

            }
        };

        Timer ttimer = new Timer();
        ttimer.schedule(ttask, 1000, 300);
    }
}

#2

Here is what I recommend you do. Download the BlackBerry Advanced UI Samples ... select the Download as Zip button.

Take a look at some screenshots of what the samples have here. The one you need to use is the Bitmap Gauge Field:

enter image description here

What you can do is modify the BitmapGaugeField class that they have in the sample folder, under Advanced UI -> src/com/samples/toolkit/ui/component

In BitmapGaugeField.java, you will only need to change the drawHorizontalPill() method:

private void drawHorizontalPill( Graphics g, Bitmap baseImage, Bitmap centerTile, int clipLeft, int clipRight, int width )
{
    int yPosition = ( _height - baseImage.getHeight() ) >> 1;
    width = Math.max( width, clipLeft + clipRight );

    // ORIGINAL IMPLEMENTATION COMMENTED OUT HERE:
    // Left
    //g.drawBitmap( 0, yPosition, clipLeft, baseImage.getHeight(), baseImage, 0, 0);
    // Middle
    //g.tileRop( _rop, clipLeft, yPosition, Math.max( 0, width - clipLeft - clipRight ), centerTile.getHeight(), centerTile, 0, 0);
    // Right
    //g.drawBitmap( width - clipRight, yPosition, clipRight, baseImage.getHeight(), baseImage, baseImage.getWidth() - clipRight, 0);

    int offset = _width - width;
    // Left
    g.drawBitmap( 0 + offset, yPosition, clipLeft, baseImage.getHeight(), baseImage, 0, 0);

    // Middle
    g.tileRop( _rop, clipLeft + offset, yPosition, Math.max( 0, width - clipLeft - clipRight ), centerTile.getHeight(), centerTile, 0, 0);

    // Right
    g.drawBitmap( width - clipRight + offset, yPosition, clipRight, baseImage.getHeight(), baseImage, baseImage.getWidth() - clipRight, 0);
}

The way you use this class is to pass in values for the background, and foreground (fill) stretchable bitmaps, the range of values, initial value, and some clipping margins.

public BitmapGaugeField( 
   Bitmap background,             /** bitmap to draw for gauge background */
   Bitmap progress,               /** bitmap to draw for gauge foreground */
   int numValues,                 /** this is the discrete range, not including 0 */
   int initialValue,
   int leadingBackgroundClip,
   int trailingBackgroundClip,
   int leadingProgressClip,
   int trailingProgressClip,
   boolean horizontal )          /** it looks like you could even do vertical! */

An example, if you want this gauge to go from 0 to 100, and have an initial value of 30 (this code goes in a Manager class):

    Bitmap gaugeBack3 = Bitmap.getBitmapResource( "gauge_back_3.png" );
    Bitmap gaugeProgress3 = Bitmap.getBitmapResource( "gauge_progress_3.png" );
    BitmapGaugeField bitGauge3 = new BitmapGaugeField( gaugeBack3, gaugeProgress3, 
        100, 30, 
        14, 14, 14, 14, 
        true );
    bitGauge3.setPadding(15,5,15,5);
    add(bitGauge3);    

    bitGauge3.setValue(80);   // change the initial value from 30 to 80

You'll find in the project some PNG images, like gauge_back_3.png and gauge_progress_3.png. If you don't like the colors or shapes, you can swap those images out for ones you draw yourself (in Photoshop, or another drawing program).

Good luck!


#3

Check following code for an implementation of Custom GaugeField.

Output

Implementation of CustomGaugeField

class CustomGaugeField extends GaugeField {
    // Default constructor, need improvement
    public CustomGaugeField() {
        super("", 0, 100, 0, GaugeField.PERCENT);
    }

    // Colors
    private static final int BG_COLOR = 0xd6d7d6;
    private static final int BAR_COLOR = 0x63cb52;
    private static final int FONT_COLOR = 0x5a55c6;

    protected void paint(Graphics graphics) {
        int xProgress = (int) ((getWidth() / 100.0) * getValue());
        int xProgressInv = getWidth() - xProgress;

        // draw background
        graphics.setBackgroundColor(BG_COLOR);
        graphics.clear();

        // draw progress bar
        graphics.setColor(BAR_COLOR);
        graphics.fillRect(xProgressInv, 0, xProgress, getHeight());

        // draw progress indicator text
        String text = getValue() + "%";
        Font font = graphics.getFont();
        int xText = (getWidth() - font.getAdvance(text)) / 2;
        int yText = (getHeight() - font.getHeight()) / 2;
        graphics.setColor(FONT_COLOR);
        graphics.drawText(text, xText, yText);
    }
}


How to use

class MyScreen extends MainScreen {

    public MyScreen() {
        setTitle("Custom GaugeField Demo");
        GaugeField gField;
        for (int i = 0; i < 6; i++) {
            gField = new CustomGaugeField();
            gField.setMargin(10, 10, 10, 10);
            add(gField);
        }
        startProgressTimer();
    }

    private void startProgressTimer() {
        TimerTask ttask = new TimerTask() {
            public void run() {
                Field f;
                for (int i = 0; i < getFieldCount(); i++) {
                    f = getField(i);
                    if (f instanceof CustomGaugeField) {
                        final CustomGaugeField gField = (CustomGaugeField) f;
                        final int increment = (i + 1) * 2;
                        UiApplication.getUiApplication().invokeLater(
                            new Runnable() {
                                public void run() {
                                    gField.setValue((gField.getValue() + increment) % 101);
                                }
                            }
                        );
                    }
                }

            }
        };

        Timer ttimer = new Timer();
        ttimer.schedule(ttask, 1000, 300);
    }
}

#4

Here is what I recommend you do. Download the BlackBerry Advanced UI Samples ... select the Download as Zip button.

Take a look at some screenshots of what the samples have here. The one you need to use is the Bitmap Gauge Field:

enter image description here

What you can do is modify the BitmapGaugeField class that they have in the sample folder, under Advanced UI -> src/com/samples/toolkit/ui/component

In BitmapGaugeField.java, you will only need to change the drawHorizontalPill() method:

private void drawHorizontalPill( Graphics g, Bitmap baseImage, Bitmap centerTile, int clipLeft, int clipRight, int width )
{
    int yPosition = ( _height - baseImage.getHeight() ) >> 1;
    width = Math.max( width, clipLeft + clipRight );

    // ORIGINAL IMPLEMENTATION COMMENTED OUT HERE:
    // Left
    //g.drawBitmap( 0, yPosition, clipLeft, baseImage.getHeight(), baseImage, 0, 0);
    // Middle
    //g.tileRop( _rop, clipLeft, yPosition, Math.max( 0, width - clipLeft - clipRight ), centerTile.getHeight(), centerTile, 0, 0);
    // Right
    //g.drawBitmap( width - clipRight, yPosition, clipRight, baseImage.getHeight(), baseImage, baseImage.getWidth() - clipRight, 0);

    int offset = _width - width;
    // Left
    g.drawBitmap( 0 + offset, yPosition, clipLeft, baseImage.getHeight(), baseImage, 0, 0);

    // Middle
    g.tileRop( _rop, clipLeft + offset, yPosition, Math.max( 0, width - clipLeft - clipRight ), centerTile.getHeight(), centerTile, 0, 0);

    // Right
    g.drawBitmap( width - clipRight + offset, yPosition, clipRight, baseImage.getHeight(), baseImage, baseImage.getWidth() - clipRight, 0);
}

The way you use this class is to pass in values for the background, and foreground (fill) stretchable bitmaps, the range of values, initial value, and some clipping margins.

public BitmapGaugeField( 
   Bitmap background,             /** bitmap to draw for gauge background */
   Bitmap progress,               /** bitmap to draw for gauge foreground */
   int numValues,                 /** this is the discrete range, not including 0 */
   int initialValue,
   int leadingBackgroundClip,
   int trailingBackgroundClip,
   int leadingProgressClip,
   int trailingProgressClip,
   boolean horizontal )          /** it looks like you could even do vertical! */

An example, if you want this gauge to go from 0 to 100, and have an initial value of 30 (this code goes in a Manager class):

    Bitmap gaugeBack3 = Bitmap.getBitmapResource( "gauge_back_3.png" );
    Bitmap gaugeProgress3 = Bitmap.getBitmapResource( "gauge_progress_3.png" );
    BitmapGaugeField bitGauge3 = new BitmapGaugeField( gaugeBack3, gaugeProgress3, 
        100, 30, 
        14, 14, 14, 14, 
        true );
    bitGauge3.setPadding(15,5,15,5);
    add(bitGauge3);    

    bitGauge3.setValue(80);   // change the initial value from 30 to 80

You'll find in the project some PNG images, like gauge_back_3.png and gauge_progress_3.png. If you don't like the colors or shapes, you can swap those images out for ones you draw yourself (in Photoshop, or another drawing program).

Good luck!


#5

are there accesible methods set(apply)ComponentOrientation ???

#6

Does your progress bar still have 100% on the right, and 0% on the left, and you simply want to take the progress from 100%, down to 0% as time passes? Or, do you want 0% to actually be on the right, so that the gauge fills from right to left? Those are two different things.

#7

its not specific about the percentages.....its about the direction....doesnt matter where 0% is placed....all i want is the filling to take place in opposite direction

#8

Its screen is based on Canvas or LCDUI (Form, List...) ?

#9

You can use GaugeField as you said by setting progress value as (100 - progressValue) always. And if you need full control over the appearance (color) you need to override the paint() method of GaugeField.

#10

You are a life saviour Rupak :) thanks a ton. This works for me :)

#11

what if i want to run the timer only once and stop it? where do i need to make the change

#12

There is no need to use any Timer, it was used for demonstration only. For real world scenario, you need to use setValue(progressPercentage) depending on the progress of the work you started. For example, if you start download a file from server, and if the file size is 10 MB, then after downloading 3 MB you can set the value of the progress to 30. When 8.5 MB downloaded, set the value to '85' and when all downloading finished set the value to 100.

#13

On my demo code, I updated the value of the progress in a scheduled interval. And when the value exceeds 100, it starts setting the progress values again. But you need to stop when the progress value is equals to 100.

#14

yes that exactly wat i want to do. even il be using the timer and want to run as long as an audio runs in the background, when the song completes,i want the bar to stop to....but here its repeating

#15

are there accesible methods set(apply)ComponentOrientation ???

#16

Does your progress bar still have 100% on the right, and 0% on the left, and you simply want to take the progress from 100%, down to 0% as time passes? Or, do you want 0% to actually be on the right, so that the gauge fills from right to left? Those are two different things.

#17

its not specific about the percentages.....its about the direction....doesnt matter where 0% is placed....all i want is the filling to take place in opposite direction

#18

Its screen is based on Canvas or LCDUI (Form, List...) ?

#19

You can use GaugeField as you said by setting progress value as (100 - progressValue) always. And if you need full control over the appearance (color) you need to override the paint() method of GaugeField.

#20

You are a life saviour Rupak :) thanks a ton. This works for me :)

#21

what if i want to run the timer only once and stop it? where do i need to make the change

#22

There is no need to use any Timer, it was used for demonstration only. For real world scenario, you need to use setValue(progressPercentage) depending on the progress of the work you started. For example, if you start download a file from server, and if the file size is 10 MB, then after downloading 3 MB you can set the value of the progress to 30. When 8.5 MB downloaded, set the value to '85' and when all downloading finished set the value to 100.

#23

On my demo code, I updated the value of the progress in a scheduled interval. And when the value exceeds 100, it starts setting the progress values again. But you need to stop when the progress value is equals to 100.

#24

yes that exactly wat i want to do. even il be using the timer and want to run as long as an audio runs in the background, when the song completes,i want the bar to stop to....but here its repeating