Related
I have created a SliderField class in order to show a drag-able slider in my BlackBerry application. The slider is basically used to set interval for location updates (via GPS) in the app. The app is built on OS 5.0 and so no API was found for the SliderField. The problem
I am facing is that I need to increase the integer value in a label as the slider is moved. For instance, if the integer value in a label is 1 and the user moves the slider the value should increase to 5,10,15 etc. I do not know how to link moving the slider to increasing the value in the label field. Can anyone please help? I am adding the SliderField object to the screen as below:
Bitmap sliderBack = Bitmap.getBitmapResource( "progress51.png" );
Bitmap sliderFocus = Bitmap.getBitmapResource( "progress51.png" );
Bitmap sliderThumb = Bitmap.getBitmapResource( "butt.png" );
SliderField theSlider = new SliderField( sliderThumb, sliderBack, sliderFocus,20, 1, 1, 1 );
secondHFM.add(theSlider)
Below is my code for the SliderField class.
public class SliderField extends Field
{
Bitmap _imageThumb;
Bitmap _imageSlider;
Bitmap _imageSliderLeft;
Bitmap _imageSliderCenter;
Bitmap _imageSliderRight;
Bitmap _imageSliderFocus;
Bitmap _imageSliderFocusLeft;
Bitmap _imageSliderFocusCenter;
Bitmap _imageSliderFocusRight;
private int _numStates;
private int _currentState;
private boolean _selected;
private int _xLeftBackMargin;
private int _xRightBackMargin;
private int _thumbWidth;
private int _thumbHeight;
private int _totalHeight;
private int _totalWidth;
private int _rop;
private int _backgroundColours[];
private int _backgroundSelectedColours[];
private int _defaultSelectColour = 0x977DED;
private int _defaultBackgroundColour = 0x000000;
private int _defaultHoverColour = 0x999999;
public SliderField( Bitmap thumb
, Bitmap sliderBackground
, int numStates
, int initialState
, int xLeftBackMargin
, int xRightBackMargin )
{
this( thumb, sliderBackground, sliderBackground, numStates, initialState, xLeftBackMargin, xRightBackMargin, FOCUSABLE );
}
public SliderField( Bitmap thumb
, Bitmap sliderBackground
, int numStates
, int initialState
, int xLeftBackMargin
, int xRightBackMargin
, long style )
{
this( thumb, sliderBackground, sliderBackground, numStates, initialState, xLeftBackMargin, xRightBackMargin, style );
}
public SliderField( Bitmap thumb
, Bitmap sliderBackground
, Bitmap sliderBackgroundFocus
, int numStates
, int initialState
, int xLeftBackMargin
, int xRightBackMargin )
{
this( thumb, sliderBackground, sliderBackgroundFocus, numStates, initialState, xLeftBackMargin, xRightBackMargin, FOCUSABLE );
}
public SliderField( Bitmap thumb
, Bitmap sliderBackground
, Bitmap sliderBackgroundFocus
, int numStates
, int initialState
, int xLeftBackMargin
, int xRightBackMargin
, long style )
{
super( style );
if( initialState > numStates || numStates < 2 ){
}
_imageThumb = thumb;
_imageSlider = sliderBackground;
_imageSliderFocus = sliderBackgroundFocus;
_numStates = numStates;
setState( initialState );
_xLeftBackMargin = xLeftBackMargin;
_xRightBackMargin = xRightBackMargin;
_rop = _imageSlider.hasAlpha() ? Graphics.ROP_SRC_ALPHA : Graphics.ROP_SRC_COPY;
_thumbWidth = thumb.getWidth();
_thumbHeight = thumb.getHeight();
initBitmaps();
}
public SliderField( Bitmap thumb
, Bitmap sliderBackground
, int numStates
, int initialState
, int xLeftBackMargin
, int xRightBackMargin
, int[] colours
, int[] selectColours )
{
this(thumb, sliderBackground, sliderBackground, numStates, initialState, xLeftBackMargin, xRightBackMargin, FOCUSABLE );
if( colours.length != numStates+1 ){
throw new IllegalArgumentException();
}
_backgroundColours = colours;
_backgroundSelectedColours = selectColours;
}
public void initBitmaps()
{
int height = _imageSlider.getHeight();
_imageSliderLeft = new Bitmap( _xLeftBackMargin, height );
_imageSliderCenter = new Bitmap( _imageSlider.getWidth() - _xRightBackMargin - _xLeftBackMargin, height);
_imageSliderRight = new Bitmap( _xRightBackMargin, height );
copy( _imageSlider, 0, 0, _xLeftBackMargin, height, _imageSliderLeft );
copy( _imageSlider, _xLeftBackMargin, 0, _imageSlider.getWidth() - _xRightBackMargin - _xLeftBackMargin, height, _imageSliderCenter);
copy( _imageSlider, _imageSlider.getWidth() - _xRightBackMargin, 0, _xRightBackMargin, height, _imageSliderRight);
_imageSliderFocusLeft = new Bitmap( _xLeftBackMargin, height );
_imageSliderFocusCenter = new Bitmap( _imageSlider.getWidth() - _xRightBackMargin - _xLeftBackMargin, height);
_imageSliderFocusRight = new Bitmap( _xRightBackMargin, height );
copy( _imageSliderFocus, 0, 0, _xLeftBackMargin, height, _imageSliderFocusLeft );
copy( _imageSliderFocus, _xLeftBackMargin, 0, _imageSlider.getWidth() - _xRightBackMargin - _xLeftBackMargin, height, _imageSliderFocusCenter);
copy( _imageSliderFocus, _imageSlider.getWidth() - _xRightBackMargin, 0, _xRightBackMargin, height, _imageSliderFocusRight);
}
private void copy(Bitmap src, int x, int y, int width, int height, Bitmap dest) {
int[] argbData = new int[width * height];
src.getARGB(argbData, 0, width, x, y, width, height);
for(int tx = 0; tx < dest.getWidth(); tx += width) {
for(int ty = 0; ty < dest.getHeight(); ty += height) {
dest.setARGB(argbData, 0, width, tx, ty, width, height);
}
}
}
public void setState(int newState) {
if( newState > _numStates ){
throw new IllegalArgumentException();
} else {
_currentState = newState;
invalidate();
}
}
public int getState() {
return _currentState;
}
public int getNumStates() {
return _numStates;
}
public int getColour() {
if(_backgroundSelectedColours != null) {
return _backgroundSelectedColours[getState()];
}
return 0x000000;
}
public int getPreferredWidth() {
return _totalWidth;
}
public int getPreferredHeight() {
return _totalHeight;
}
protected void layout( int width, int height ) {
if (width < 0 || height < 0)
throw new IllegalArgumentException();
_totalWidth = width;
_totalHeight = Math.max(_imageSlider.getHeight(), _imageThumb.getHeight());
setExtent( _totalWidth, _totalHeight );
}
public void paint( Graphics g )
{
int sliderHeight = _imageSlider.getHeight();
int sliderBackYOffset = ( _totalHeight - sliderHeight ) >> 1;
int backgroundColor = _defaultBackgroundColour;
if( _backgroundSelectedColours != null || _backgroundColours != null ) {
if( _selected ) {
backgroundColor = _backgroundSelectedColours != null ? _backgroundSelectedColours[getState()] : _defaultSelectColour;
} else if(g.isDrawingStyleSet(Graphics.DRAWSTYLE_FOCUS)) {
backgroundColor = _backgroundColours != null ? _backgroundColours[getState()] : _defaultHoverColour;
} else {
backgroundColor = _defaultBackgroundColour;
}
}
g.setColor( backgroundColor );
g.fillRect( 1, sliderBackYOffset + 1, _totalWidth - 2, sliderHeight - 2 );
if(g.isDrawingStyleSet(Graphics.DRAWSTYLE_FOCUS)) {
paintSliderBackground( g, _imageSliderFocusLeft, _imageSliderFocusCenter, _imageSliderFocusRight );
} else {
paintSliderBackground( g, _imageSliderLeft, _imageSliderCenter, _imageSliderRight );
}
int thumbXOffset = ( ( _totalWidth - _thumbWidth ) * _currentState ) / _numStates;
g.drawBitmap( thumbXOffset, ( _totalHeight - _thumbHeight ) >> 1, _thumbWidth, _thumbHeight, _imageThumb, 0, 0 );
}
private void paintSliderBackground( Graphics g, Bitmap left, Bitmap middle, Bitmap right )
{
int sliderHeight = _imageSlider.getHeight();
int sliderBackYOffset = ( _totalHeight - sliderHeight ) >> 1;
g.drawBitmap( 0, sliderBackYOffset, _xLeftBackMargin, sliderHeight, left, 0, 0 );
g.tileRop( _rop, _xRightBackMargin, sliderBackYOffset, _totalWidth - _xLeftBackMargin - _xRightBackMargin, sliderHeight, middle, 0, 0 );
g.drawBitmap( _totalWidth - _xRightBackMargin, sliderBackYOffset, _xRightBackMargin, sliderHeight, right, 0, 0 );
}
public void paintBackground( Graphics g )
{
}
protected void drawFocus( Graphics g, boolean on )
{
boolean oldDrawStyleFocus = g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS );
try {
if( on ) {
g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, true );
}
paint( g );
} finally {
g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, oldDrawStyleFocus );
}
}
protected boolean touchEvent(TouchEvent message)
{
boolean isConsumed = false;
boolean isOutOfBounds = false;
int x = message.getX(1);
int y = message.getY(1);
if(x < 0 || y < 0 || x > getExtent().width || y > getExtent().height) {
isOutOfBounds = true;
}
switch(message.getEvent()) {
case TouchEvent.CLICK:
case TouchEvent.MOVE:
if(isOutOfBounds) return true;
_selected = true;
int stateWidth = getExtent().width / _numStates;
int numerator = x / stateWidth;
int denominator = x % stateWidth;
if( denominator > stateWidth / 2 ) {
numerator++;
}
_currentState = numerator;
invalidate();
isConsumed = true;
break;
case TouchEvent.UNCLICK:
if(isOutOfBounds) {
_selected = false;
return true;
}
_selected = false;
stateWidth = getExtent().width / _numStates;
numerator = x / stateWidth;
denominator = x % stateWidth;
if( denominator > stateWidth / 2 ) {
numerator++;
}
_currentState = numerator;
invalidate();
fieldChangeNotify(0);
isConsumed = true;
break;
}
return isConsumed;
}
protected boolean navigationMovement(int dx, int dy, int status, int time)
{
if( _selected )
{
if(dx > 0 || dy > 0) {
incrementState();
fieldChangeNotify( 0 );
return true;
} else if(dx < 0 || dy < 0) {
decrementState();
fieldChangeNotify( 0 );
return true;
}
}
return super.navigationMovement( dx, dy, status, time);
}
public void decrementState() {
if(_currentState > 0) {
_currentState--;
invalidate();
}
}
public void incrementState() {
if(_currentState < _numStates) {
_currentState++;
invalidate();
}
}
protected boolean invokeAction(int action) {
switch(action) {
case ACTION_INVOKE: {
toggleSelected();
return true;
}
}
return false;
}
protected boolean keyChar( char key, int status, int time ) {
if( key == Characters.SPACE || key == Characters.ENTER ) {
toggleSelected();
return true;
}
return false;
}
protected boolean trackwheelClick( int status, int time ) {
if( isEditable() ) {
toggleSelected();
return true;
}
return super.trackwheelClick(status, time);
}
private void toggleSelected() {
_selected = !_selected;
invalidate();
}
public void setDirty( boolean dirty )
{
}
public void setMuddy( boolean muddy )
{
}
}
If you use the code below, you will get your actual requirement,you can get the slider current value into your screen class by invoking getValue() method on sliderfield reference..
Implement FieldChangeListener interface and try to override fieldChanged() method.
Use HorizontalFieldManager class and setStatus() method,
if you want to display your slider bar at bottom of your screen,other wise you can display it normally.
Here the Code:
public class SliderScreen extends MainScreen implements FieldChangeListener
{
private SliderField slider;
private HorizontalFieldManager hm;
public SliderField(){
slider = new SliderField(
Bitmap.getBitmapResource("slider2_thumb_normal.png"),
Bitmap.getBitmapResource("slider2_progress_normal.png"),
Bitmap.getBitmapResource("slider2_base_normal.png"),
Bitmap.getBitmapResource("slider2_thumb_focused.png"),
Bitmap.getBitmapResource("slider2_progress_focused.png"),
Bitmap.getBitmapResource("slider2_base_focused.png"), 8, 4,
8, 8, FOCUSABLE);
slider.setChangeListener(this);
hm = new HorizontalFieldManager();
hm.add(slider);
setStatus(hm);
}
public void fieldChanged(Field field, int context) {
try {
if (field == slider) {
int value = slider.getValue();
}
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
}
I have done simple example of how to use this code,Check it
public final class MyScreen extends MainScreen implements FieldChangeListener//,FocusChangeListener
{
/**
* Creates a new MyScreen object
*/
public MyScreen()
{
// Set the displayed title of the screen
setTitle("MyTitle");
SliderField slider;
slider = new SliderField(
Bitmap.getBitmapResource( "slider_thumb_normal.png" ), Bitmap.getBitmapResource( "slider_progress_normal.png" ), Bitmap.getBitmapResource( "slider_base_normal.png" ),
Bitmap.getBitmapResource( "slider_thumb_focused.png" ), Bitmap.getBitmapResource( "slider_progress_focused.png" ), Bitmap.getBitmapResource( "slider_base_focused.png"),
Bitmap.getBitmapResource( "slider_thumb_pressed.png" ), Bitmap.getBitmapResource( "slider_progress_pressed.png" ), Bitmap.getBitmapResource( "slider_base_pressed.png"),
10, 0, 12, 12, FOCUSABLE );
slider.setPadding( 20, 20, 20, 20 );
slider.setBackground( BackgroundFactory.createSolidBackground( 0xD3D3D3 ) );
slider.setChangeListener(this);
//slider.focusChangeNotify(0);
add( slider );
}
public void fieldChanged(Field field, int context) {
// TODO Auto-generated method stub
if(field instanceof SliderField)
{
SliderField temp = (SliderField)field;
System.out.println("Temp value is"+temp.getValue());
}
}
}
This is a listfield.
public class Custom_ListField extends ListField {
private String[] title, category, date, imagepath;
private int[] newsid, catsid;
private List_News newslist;
private Bitmap imagebitmap[], localimage = Bitmap
.getBitmapResource("image_base.png");
private BrowserField webpage;
private Custom_BrowserFieldListener listener;
private boolean islatest;
private Vector content = null;
private ListCallback callback = null;
private int currentPosition = 0;
public Custom_ListField(Vector content, boolean islatest) {
this.content = content;
this.islatest = islatest;
newsid = new int[content.size()];
title = new String[content.size()];
category = new String[content.size()];
date = new String[content.size()];
imagepath = new String[content.size()];
catsid = new int[content.size()];
imagebitmap = new Bitmap[content.size()];
for (int i = 0; i < content.size(); i++) {
newslist = (List_News) content.elementAt(i);
newsid[i] = newslist.getID();
title[i] = newslist.getNtitle();
category[i] = newslist.getNewCatName();
date[i] = newslist.getNArticalD();
imagepath[i] = newslist.getImagePath();
if (!imagepath[i].toString().equals("no picture")) {
imagebitmap[i] = Util_ImageLoader.loadImage(imagepath[i]);
} else {
imagebitmap[i] = localimage;
}
catsid[i] = newslist.getCatID();
}
initCallbackListening();
this.setRowHeight(localimage.getHeight() + 10);
}
private void initCallbackListening() {
callback = new ListCallback();
this.setCallback(callback);
}
private class ListCallback implements ListFieldCallback {
public ListCallback() {
setBackground(Config_GlobalFunction
.loadbackground("background.png"));
}
public void drawListRow(ListField listField, Graphics graphics,
int index, int y, int width) {
currentPosition = index;
graphics.drawBitmap(
Display.getWidth() - imagebitmap[index].getWidth() - 5,
y + 3, imagebitmap[index].getWidth(),
imagebitmap[index].getHeight(), imagebitmap[index], 0, 0);
graphics.setColor(Color.WHITE);
graphics.drawRect(0, y, width, imagebitmap[index].getHeight() + 10);
graphics.setColor(Color.BLACK);
graphics.setFont(Font.getDefault().derive(Font.BOLD, 20));
graphics.drawText(title[index], 5, y + 3, 0, Display.getWidth()
- imagebitmap[index].getWidth() - 10);
graphics.setColor(Color.GRAY);
graphics.setFont(Font.getDefault().derive(Font.BOLD, 15));
graphics.drawText(date[index], 5, y + 6
+ Font.getDefault().getHeight() + 3);
if (islatest) {
graphics.setColor(Color.RED);
graphics.setFont(Font.getDefault().derive(Font.BOLD, 15));
graphics.drawText(category[index], Font.getDefault()
.getAdvance(date[index]) + 3, y + 6
+ Font.getDefault().getHeight() + 3);
}
}
public Object get(ListField listField, int index) {
return content.elementAt(index);
}
public int getPreferredWidth(ListField listField) {
return Display.getWidth();
}
public int indexOfList(ListField listField, String prefix, int start) {
return content.indexOf(prefix, start);
}
}
public int getCurrentPosition() {
return currentPosition;
}
protected boolean navigationClick(int status, int time) {
int index = getCurrentPosition();
if (catsid[index] == 9) {
if (Config_GlobalFunction.isConnected()) {
webpage = new BrowserField();
listener = new Custom_BrowserFieldListener();
webpage.addListener(listener);
MainScreen aboutus = new Menu_Aboutus();
aboutus.add(webpage);
Main.getUiApplication().pushScreen(aboutus);
webpage.requestContent("http://www.orientaldaily.com.my/index.php?option=com_k2&view=item&id="
+ newsid[index] + ":&Itemid=223");
} else
Config_GlobalFunction.Message(Config_GlobalFunction.nowifi, 1);
} else
Main.getUiApplication().pushScreen(
new Main_NewsDetail(newsid[index]));
return true;
}
}
Please look at the
graphics.setColor(Color.BLACK);
graphics.setFont(Font.getDefault().derive(Font.BOLD, 20));
graphics.drawText(title[index], 5, y + 3, 0, Display.getWidth()
- imagebitmap[index].getWidth() - 10);
This will only draw the text one line only. I did researched and found out there isn't built in function and must custom a function make the text auto next line.
The function something like this
private int numberoflines(int availablespace){
...
return numberlines
}
The links Rupak shows are good, although one of them references the generic Java problem (and proposes a Swing result that would need to be changed for BlackBerry), and the other references an external (non stack overflow) link.
If you want another option, and don't want the algorithm to figure out where to make the line breaks, you can use this. This code assumes you put '\n' characters into your strings, where you want to split the text into multiple lines. You would probably put this code in the paint() method:
// store original color, to reset it at the end
int oldColor = graphics.getColor();
graphics.setColor(Color.BLACK);
graphics.setFont(_fieldFont);
int endOfLine = _text.indexOf('\n');
if (endOfLine < 0) {
graphics.drawText(_text, _padding, _top);
} else {
// this is a multi-line label
int top = _top;
int index = 0;
int textLength = _text.length();
while (index < textLength) {
// draw one line at a time
graphics.drawText(_text,
index, // offset into _text
endOfLine - index, // number of chars to draw
_padding, // x
top, // y
(int) (DrawStyle.HCENTER | DrawStyle.TOP | Field.USE_ALL_WIDTH), // style flags
_fieldWidth - 2 * _padding); // width available
index = endOfLine + 1;
endOfLine = _text.indexOf('\n', index);
if (endOfLine < 0) {
endOfLine = textLength;
}
top += _fieldFont.getHeight() + _top; // top padding is set equal to spacing between lines
}
}
graphics.setColor(oldColor);
And here you would initialize some of the variables I use in that. I think these are right, based on the code you posted, but you'll need to double-check:
String _text = title[index]; // text to draw
int _padding = 5; // left and right side padding around text
int _top = y + 3; // the y coordinate of the top of the text
Font _fieldFont = Font.getDefault().derive(Font.BOLD, 20);
// the total width reserved for the text, which includes room for _padding:
int _fieldWidth = Display.getWidth() - imagebitmap[index].getWidth();
I just want to know how can I change ListField's item background color. I have two items in my ListField like this one.
|First One|Second One.................|
I need to change first one's background color.
My drawListRow(..) method looks like this
public void drawListRow(ListField listField, Graphics graphics,
int index, int y, int width) {
int oldColor = 0;
try {
oldColor = graphics.getColor();
String txt = (vector.elementAt(index)).toString();
int xPos = 15;
int yPos = 5 + y;
//graphics.clear();
graphics.setColor(Color.GREEN);
graphics.fillRect(0, y, (Display.getWidth()*10/100), yPos);
graphics.drawText(txt, xPos, yPos);
//graphics.fillRect(0,(index*Display.getHeight()/10),Display.getWidth(),Display.getHeight()/10);
} finally {
graphics.setColor(oldColor);
}
}
But this is not working.
Though you have attached an image, I am still confused. The image didn't answer some question, for example, how it will look on a row get focused (I didn't understand actually).
But you can check following output and code. I think you can customize the look as you wish if you check the code.
Generated Output
How to use
public class MyScreen extends MainScreen {
private Vector listElements;
public MyScreen() {
setTitle("Custom ListField Demo");
// data for the ListField
listElements = new Vector();
for (int i = 0; i < 4; i++) {
listElements.addElement("Some text for row " + i);
}
ListField taskList = new ListField() {
// disable default focus drawing
protected void drawFocus(Graphics graphics, boolean on) {
};
};
taskList.setCallback(new ListCallback(listElements));
taskList.setSize(listElements.size());
taskList.setRowHeight(40);
add(taskList);
}
}
ListCallback implementation
class ListCallback implements ListFieldCallback {
final int COLOR_INDEX_NORMAL_BG = 0x1D6789;
final int COLOR_INDEX_FOCUSED_BG = 0x0E8CB3;
final int COLOR_NORMAL_BG = 0x2A2A2A;
final int COLOR_FOCUSED_BG = 0x1F1F1F;
private Vector listElements;
public ListCallback(Vector listElements) {
this.listElements = listElements;
}
public void drawListRow(ListField list, Graphics graphics, int index, int y,
int width) {
int rowHeight = list.getRowHeight(index);
boolean isSelectedRow = (list.getSelectedIndex() == index);
int indexBgColor = isSelectedRow ? COLOR_INDEX_FOCUSED_BG : COLOR_INDEX_NORMAL_BG;
int rowBgColor = isSelectedRow ? COLOR_FOCUSED_BG : COLOR_NORMAL_BG;
final int indexWidth = width / 10;
// draw row background
fillRectangle(graphics, rowBgColor, 0, y, width, rowHeight);
// draw index background
fillRectangle(graphics, indexBgColor, 0, y, indexWidth, rowHeight);
// set text color, draw text
Font font = list.getFont();
graphics.setColor(Color.WHITE );
graphics.setFont(font);
String indexText = "" + (index + 1);
String textToDraw = "";
try {
textToDraw = (String) listElements.elementAt(index);
} catch (Exception exc) {
}
int xText = (indexWidth - font.getAdvance(indexText)) / 2;
int yText = (rowHeight - font.getHeight()) / 2;
graphics.drawText(indexText, xText, y + yText, 0, indexWidth);
final int margin = 5;
int availableWidth = (width - indexWidth) - 2 * margin;
xText = indexWidth + margin;
yText = (rowHeight - font.getHeight()) / 2;
graphics.drawText(textToDraw, xText, y + yText, DrawStyle.ELLIPSIS, availableWidth);
}
private void fillRectangle(Graphics graphics, int color, int x, int y, int width, int height) {
graphics.setColor(color);
graphics.fillRect(x, y, width, height);
}
public Object get(ListField list, int index) {
// not implemented
return "";
}
public int indexOfList(ListField list, String prefix, int string) {
// not implemented
return 0;
}
public int getPreferredWidth(ListField list) {
return Display.getWidth();
}
}
If you need to change onFocus Background color than add drwFocus method on your ListField.
protected void drawFocus(Graphics graphics, boolean on) {
//get the focus rect area
XYRect focusRect = new XYRect();
getFocusRect(focusRect);
boolean oldDrawStyleFocus = graphics.isDrawingStyleSet(Graphics.DRAWSTYLE_FOCUS);
try {
if (on) {
//set the style so the fields in the row will update its color accordingly
graphics.setDrawingStyle(Graphics.DRAWSTYLE_FOCUS, true);
int oldColour = graphics.getColor();
try {
graphics.setColor(0xc8d3db); //set the color and draw the color
graphics.fillRect(focusRect.x, focusRect.y,
focusRect.width, focusRect.height);
} finally {
graphics.setColor(oldColour);
}
//to draw the row again
drawListRow(this, graphics, getSelectedIndex(),
focusRect.y, focusRect.width);
// drawRow(graphics, focusRect.x,focusRect.y, focusRect.width,focusRect.height);
}
} finally {
graphics.setDrawingStyle(Graphics.DRAWSTYLE_FOCUS, oldDrawStyleFocus);
}
}
Check the edited answer,
protected void drawFocus(Graphics graphics, boolean on) {
XYRect focusRect = new XYRect();
getFocusRect(focusRect);
boolean oldDrawStyleFocus = graphics.isDrawingStyleSet(Graphics.DRAWSTYLE_FOCUS);
try {
if (on) {
graphics.setDrawingStyle(Graphics.DRAWSTYLE_FOCUS, true);
int oldColour = Color.BLACK;
try {
graphics.fillRect(focusRect.x, focusRect.y,
focusRect.width, focusRect.height);
} finally {
graphics.setColor(oldColour);
}
//to draw the row again
drawListRow(this, graphics, getSelectedIndex(),
focusRect.y, focusRect.width);
}
} finally {
graphics.setDrawingStyle(Graphics.DRAWSTYLE_FOCUS, oldDrawStyleFocus);
}
}
I am using a customlistfield by extending VerticalFieldManager, and for the row I am usingf another CustoRowManager that extends Manager. The CustomRowManager has 2 TextField and a BitmapField . This list is implemented for a live xml feed. For loading the bitmapfield I am displaying placeholders which is then replaced by the actual image from background thread. I am not able to figure out how I should replace place holders with the bitmapfield. using invalidate() is one option, but on which element I should perform it.
public class CustomList extends VerticalFieldManager{
private int totalHeight = 0;
private int screenHeight = 0;
private int scrollPosition = 0;
protected void sublayout(int width, int height)
{
width = 480;
height = 230;
super.sublayout(width,height);
setExtent(width, height);
}
protected boolean navigationClick(int status, int time)
{
int index;
System.out.println("CLICKED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
if ((status & KeypadListener.STATUS_FOUR_WAY) == KeypadListener.STATUS_FOUR_WAY)
{
index = this.getFieldWithFocusIndex();
UiApplication.getUiApplication().pushScreen(new TopNewsScreen(_vec, index));
}
return true;
}
Bitmap _bmp = null;
BitmapField _bmF = null;
Object _Obj = null;
TopNews _topNews = null;
String _headStr = null, _metaStr = null;
CustTextField _headNews = null, _metaData = null;
CustomRow _custRow = null;
Vector _vec;
public CustomList(Vector _vec,long _property)
{
super(_property);
this._vec = new Vector();
this._vec = _vec;
int _size = _vec.size();
int i ;
for(i = 0; i <_size; i++)
{
_headStr = new String();
_metaStr = new String();
_bmp = Bitmap.getBitmapResource("img/1.jpg");
_bmF = new BitmapField(_bmp);
_topNews = (TopNews)_vec.elementAt(i);
_headStr = _topNews.getHeadline();
_metaStr = _topNews.getMetaData();
int _newsLeng = _headStr.length(), alert = 0;
if(_newsLeng <= 35)
{
alert = 0;
}else if(_newsLeng>35&&_newsLeng<=70)
{
alert = 1;
}else {
alert = 2;
_headStr = this.truncate(_headStr,70);
}
_custRow = new CustomRow(alert);
_headNews = new CustTextField(_headStr,25,0x05235b,TextField.NON_FOCUSABLE);
_metaData = new CustTextField(_metaStr,15,0x666666,TextField.NON_FOCUSABLE);
_custRow.add(_headNews);
_custRow.add(_metaData);
_custRow.add(_bmF);
super.add(_custRow);
}
}
String truncate(String value, int length)
{
if (value != null && value.length() > length)
value = value.substring(0, length);
return value;
}
}
class CustomRow extends Manager implements FocusChangeListener{
private int _headLeng;
private NullField _focus = null;
CustomRow(int _headLeng)
{
super(Manager.FOCUSABLE|
Manager.NO_HORIZONTAL_SCROLL
|Manager.NO_VERTICAL_SCROLL);
this._headLeng = _headLeng;
_focus = new NullField(NullField.FOCUSABLE);
_focus.setFocusListener(CustomRow.this);
this.add(_focus);
}
protected void sublayout(int width, int height)
{
if(_headLeng==0)
{
layoutChild(getField(0),0,0);
setPositionChild(getField(0),0 , 0);
layoutChild(getField(1),360,20);
setPositionChild(getField(1),10 , 10);
layoutChild(getField(2),300, 20);
setPositionChild(getField(2), 10, 65);
layoutChild(getField(3),90,65);
setPositionChild(getField(3), 380, 10);
}else
{
/* layoutChild(getField(0),0,0);
setPositionChild(getField(0),0 , 0);
layoutChild(getField(1),360,20);
setPositionChild(getField(1),10 , 10);
layoutChild(getField(2),300, 20);
setPositionChild(getField(2), 10, 50);
layoutChild(getField(3),90,65);
setPositionChild(getField(3), 380, 10); */
layoutChild(getField(0),0,0);
setPositionChild(getField(0),0 , 0);
layoutChild(getField(1),360,20);
setPositionChild(getField(1),10 , 10);
layoutChild(getField(2),300, 20);
setPositionChild(getField(2), 10, 65);
layoutChild(getField(3),90,65);
setPositionChild(getField(3), 380, 10);
}
height = 80;
width = 480;
setExtent(width, height);
}
protected void paint(Graphics graphics)
{
graphics.setColor(Color.GRAY);
graphics.drawLine(10, 79, Display.getWidth()-10, 79);
super.paint(graphics);
}
public void focusChanged(Field field, int eventType) {
// TODO Auto-generated method stub
this.getManager().invalidate();
}
protected void paintBackground(Graphics g) {
int prevBg = g.getBackgroundColor();
if (_focus.isFocus()) {
g.setBackgroundColor(Color.LIGHTBLUE);
} else {
g.setBackgroundColor(Color.WHITE);
}
g.clear();
g.setBackgroundColor(prevBg);
}
}
the below link has answer for the question, I should change the name to Blackberry lazyloading.
http://supportforums.blackberry.com/t5/Java-Development/Clumsy-layout-invalidate/m-p/1398763
Is it possible in j2me to measure signal amplitude of audio record made by JSR-135 Player?
I know I can access buffer, but then what?
Target model Bold 9000, supported formats PCM and AMR. Which format I should use?
See also
Blackberry Audio Recording Sample Code
How To - Record Audio on a BlackBerry smartphone
Thank you!
Get raw PCM signal level
Use menu and trackwheel to zoom in/out and move left/right within graph.
Audio format: raw 8000 Hz 16 bit mono pcm.
Tested on Bold 9000 RIM OS 4.6
Algorythm should work in any mobile, where j2me and pcm is supported, of course implementation may require changes.
Using thread for audio recording:
class VoiceNotesRecorderThread extends Thread {
private Player _player;
private RecordControl _rcontrol;
private ByteArrayOutputStream _output;
private byte _data[];
VoiceNotesRecorderThread() {
}
public void run() {
try {
_player = Manager
.createPlayer("capture://audio?encoding=audio/basic");
_player.realize();
_rcontrol = (RecordControl) _player
.getControl("RecordControl");
_output = new ByteArrayOutputStream();
_rcontrol.setRecordStream(_output);
_rcontrol.startRecord();
_player.start();
} catch (final Exception e) {
UiApplication.getUiApplication().invokeAndWait(new Runnable() {
public void run() {
Dialog.inform(e.toString());
}
});
}
}
public void stop() {
try {
_rcontrol.commit();
_data = _output.toByteArray();
_output.close();
_player.close();
} catch (Exception e) {
synchronized (UiApplication.getEventLock()) {
Dialog.inform(e.toString());
}
}
}
byte[] getData() {
return _data;
}
}
And method for painting graph using byte[] buffer:
private Bitmap getGraph(byte[] buffer, int zoom, int startFrom) {
Bitmap result = new Bitmap(Display.getWidth(), Display.getHeight());
Graphics g = new Graphics(result);
g.setColor(Color.BLACK);
int xPos = 0;
int yPos = Display.getHeight() >> 1;
for (int i = startFrom; i < buffer.length; i += 2 * zoom) {
byte[] b = new byte[] { buffer[i], buffer[i + 1] };
int level = (signedShortToInt(b) * 100 / 32767);
if (100 < level) {
level -= 200;
}
g.drawPoint(xPos, yPos - level);
xPos++;
}
return result;
}
public static final int signedShortToInt(byte[] b) {
int result = (b[0] & 0xff) | (b[1] & 0xff) << 8;
return result;
}
Screen class:
class Scr extends MainScreen {
BitmapField mGraphField = new BitmapField(new Bitmap(Display.getWidth(),
Display.getHeight()));
private VoiceNotesRecorderThread m_thread;
public Scr() {
add(mGraphField);
add(new NullField(FOCUSABLE));
}
boolean mRecording = false;
private int mZoom = 1;
private int mStartFrom = 0;
byte[] mAudioData = null;
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
menu.add(mRecordStopMenuItem);
menu.add(mPaintZoomIn);
menu.add(mPaintZoomOut);
menu.add(mPaintZoomToFitScreen);
menu.add(mPaintMoveRight);
menu.add(mPaintMoveLeft);
menu.add(mPaintMoveToBegin);
}
MenuItem mRecordStopMenuItem = new MenuItem("Record", 0, 0) {
public void run() {
if (!mRecording) {
m_thread = new VoiceNotesRecorderThread();
m_thread.start();
mRecording = true;
this.setText("Stop");
} else {
m_thread.stop();
mAudioData = m_thread.getData();
zoomToFitScreen();
mRecording = false;
this.setText("Record");
}
}
};
MenuItem mPaintZoomIn = new MenuItem("Zoom In", 0, 0) {
public void run() {
zoomIn();
}
};
MenuItem mPaintZoomOut = new MenuItem("Zoom Out", 0, 0) {
public void run() {
zoomOut();
}
};
MenuItem mPaintZoomToFitScreen = new MenuItem("Fit Screen", 0, 0) {
public void run() {
zoomToFitScreen();
}
};
MenuItem mPaintMoveLeft = new MenuItem("Left", 0, 0) {
public void run() {
moveLeft();
}
};
MenuItem mPaintMoveRight = new MenuItem("Right", 0, 0) {
public void run() {
moveRight();
}
};
MenuItem mPaintMoveToBegin = new MenuItem("To Begin", 0, 0) {
public void run() {
moveToBegin();
}
};
private void zoomOut() {
if (mZoom < 200)
mZoom++;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
}
private void zoomIn() {
if (mZoom > 1)
mZoom--;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
}
private void zoomToFitScreen() {
int lenght = mAudioData.length;
mZoom = (lenght / 2) / Display.getWidth();
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
}
private void moveRight() {
if (mStartFrom < mAudioData.length - 30)
mStartFrom += 30;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
}
private void moveLeft() {
if (mStartFrom > 30)
mStartFrom -= 30;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
}
private void moveToBegin() {
mStartFrom = 0;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
}
protected boolean navigationMovement(int dx, int dy, int status,
int time) {
if (dx < 0) {
moveLeft();
} else if (dx > 0) {
moveRight();
}
if (dy < 0) {
zoomIn();
} else if (dy > 0) {
zoomOut();
}
return super.navigationMovement(dx, dy, status, time);
}
}
Was helpfull:
ADC -> integer PCM file -> signal processing
SO - How is audio represented with numbers?
Convert byte array to integer
In most devices, only MID format with a single track is supported. That is the mid0 format that supports multiple instruments in one single track. I am not sure if the api provides the facility to measure the amplitude of a signal. To convert mid files to you can use Anvil Studio that has both free and pro versions
To record audio you need to use Manager.createPlayer("capture://audio"). Also leave the encoding (PCM or AMR) to the device implementation because some phones don't support PCM/AMR
Hope this helps!