It's easy to show some animation within one field - BitmapField or Screen:
[Blackberry - background image/animation RIM OS 4.5.0][1]
But what if you need to move fields, not just images?
May be used:
game workflow functionality, like chess, puzzle etc
application user-defined layout, like in Google gadgets
enhanced GUI animation effects
So, I'd like to exchange my expirience in this task, on the other hand, I'd like to know about any others possibilities and suggestions.
This effect may be easily achived with custom layout:
class AnimatedManager extends Manager {
int ANIMATION_NONE = 0;
int ANIMATION_CROSS_FLY = 1;
boolean mAnimationStart = false;
Bitmap mBmpBNormal = Bitmap.getBitmapResource("blue_normal.png");
Bitmap mBmpBFocused = Bitmap.getBitmapResource("blue_focused.png");
Bitmap mBmpRNormal = Bitmap.getBitmapResource("red_normal.png");
Bitmap mBmpRFocused = Bitmap.getBitmapResource("red_focused.png");
Bitmap mBmpYNormal = Bitmap.getBitmapResource("yellow_normal.png");
Bitmap mBmpYFocused = Bitmap.getBitmapResource("yellow_focused.png");
Bitmap mBmpGNormal = Bitmap.getBitmapResource("green_normal.png");
Bitmap mBmpGFocused = Bitmap.getBitmapResource("green_focused.png");
int[] width = null;
int[] height = null;
int[] xPos = null;
int[] yPos = null;
BitmapButtonField mBButton = new BitmapButtonField(mBmpBNormal,
mBmpBFocused);
BitmapButtonField mRButton = new BitmapButtonField(mBmpRNormal,
mBmpRFocused);
BitmapButtonField mYButton = new BitmapButtonField(mBmpYNormal,
mBmpYFocused);
BitmapButtonField mGButton = new BitmapButtonField(mBmpGNormal,
mBmpGFocused);
public AnimatedManager() {
super(USE_ALL_HEIGHT | USE_ALL_WIDTH);
add(mBButton);
add(mRButton);
add(mYButton);
add(mGButton);
width = new int[] { mBButton.getPreferredWidth(),
mRButton.getPreferredWidth(),
mYButton.getPreferredWidth(),
mGButton.getPreferredWidth() };
height = new int[] { mBButton.getPreferredHeight(),
mRButton.getPreferredHeight(),
mYButton.getPreferredHeight(),
mGButton.getPreferredHeight() };
xPos = new int[] { 0, getPreferredWidth() - width[1], 0,
getPreferredWidth() - width[3] };
yPos = new int[] { 0, 0, getPreferredHeight() - height[2],
getPreferredHeight() - height[3] };
Timer timer = new Timer();
timer.schedule(mAnimationTask, 0, 100);
}
TimerTask mAnimationTask = new TimerTask() {
public void run() {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
updateLayout();
};
});
};
};
MenuItem mAnimationMenuItem = new MenuItem("Start", 0, 0) {
public void run() {
mAnimationStart = true;
};
};
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
menu.add(mAnimationMenuItem);
}
public int getPreferredHeight() {
return Display.getHeight();
}
public int getPreferredWidth() {
return Display.getWidth();
}
protected void sublayout(int width, int height) {
width = getPreferredWidth();
height = getPreferredHeight();
if (getFieldCount() > 3) {
Field first = getField(0);
Field second = getField(1);
Field third = getField(2);
Field fourth = getField(3);
layoutChild(first, this.width[0], this.height[0]);
layoutChild(second, this.width[1], this.height[1]);
layoutChild(third, this.width[2], this.height[2]);
layoutChild(fourth, this.width[3], this.height[3]);
if (mAnimationStart) {
boolean anim1 = performLayoutAnimation(0,
width - this.width[0],
height - this.height[0]);
boolean anim2 = performLayoutAnimation(1, 0,
height - this.height[1]);
boolean anim3 = performLayoutAnimation(2,
width - this.width[2], 0);
boolean anim4 = performLayoutAnimation(3, 0, 0);
mAnimationStart = anim1 || anim2 || anim3 || anim4;
}
setPositionChild(first, xPos[0], yPos[0]);
setPositionChild(second, xPos[1], yPos[1]);
setPositionChild(third, xPos[2], yPos[2]);
setPositionChild(fourth, xPos[3], yPos[3]);
}
setExtent(width, height);
}
boolean performLayoutAnimation(int fieldIndex, int x, int y) {
boolean result = false;
if (xPos[fieldIndex] > x) {
xPos[fieldIndex] -= 2;
result = true;
} else if (xPos[fieldIndex] < x) {
xPos[fieldIndex] += 2;
result = true;
}
if (yPos[fieldIndex] > y) {
yPos[fieldIndex] -= 1;
result = true;
} else if (yPos[fieldIndex] < y) {
yPos[fieldIndex] += 1;
result = true;
}
return result;
}
}
BitmapButtonField class I've used:
class BitmapButtonField extends ButtonField {
Bitmap mNormal;
Bitmap mFocused;
int mWidth;
int mHeight;
public BitmapButtonField(Bitmap normal, Bitmap focused) {
super(CONSUME_CLICK);
mNormal = normal;
mFocused = focused;
mWidth = mNormal.getWidth();
mHeight = mNormal.getHeight();
setMargin(0, 0, 0, 0);
setPadding(0, 0, 0, 0);
setBorder(BorderFactory.createSimpleBorder(new XYEdges(0, 0, 0, 0)));
setBorder(VISUAL_STATE_ACTIVE, BorderFactory
.createSimpleBorder(new XYEdges(0, 0, 0, 0)));
}
protected void paint(Graphics graphics) {
Bitmap bitmap = null;
switch (getVisualState()) {
case VISUAL_STATE_NORMAL:
bitmap = mNormal;
break;
case VISUAL_STATE_FOCUS:
bitmap = mFocused;
break;
case VISUAL_STATE_ACTIVE:
bitmap = mFocused;
break;
default:
bitmap = mNormal;
}
graphics.drawBitmap(0, 0, bitmap.getWidth(), bitmap.getHeight(),
bitmap, 0, 0);
}
public int getPreferredWidth() {
return mWidth;
}
public int getPreferredHeight() {
return mHeight;
}
protected void layout(int width, int height) {
setExtent(mWidth, mHeight);
}
protected void applyTheme(Graphics arg0, boolean arg1) {
}
}
Related
I have set list border using trigger according to my requirement but when I scroll up the listview and selected view cell is gone than I scroll down when ViewCell is appearing on screen than selected border is gone
To prevent this I also created frame renderer but still ViewCell border gone.
Attached image here
class FrameHighLightRenderer : VisualElementRenderer<Frame>
{
ACanvas _canvas = null;
private FrameDrawable _frameDrawable;
protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
if (_frameDrawable != null && e.NewElement.ClassId != null) //This block execute while any cell appearing in scroll time up/dowm
{ // I added classId =10 to identify colored/selected cell
if (e.NewElement.ClassId=="10")
{
e.NewElement.OutlineColor = Xamarin.Forms.Color.Red;
this.Invalidate();
}
else
{
e.NewElement.BackgroundColor = Xamarin.Forms.Color.TransParent;
}
}
else
{
UpdateBackground();
}
}
}
void UpdateBackground()
{
_frameDrawable = new FrameDrawable(Element, Context.ToPixels);
this.SetBackground(_frameDrawable);
}
class FrameDrawable : Drawable
{
readonly Frame _frame;
readonly Func<double, float> _convertToPixels;
public ACanvas _canvas;
bool _isDisposed;
Bitmap _normalBitmap;
public FrameDrawable(Frame frame, Func<double, float> convertToPixels)
{
_frame = frame;
_convertToPixels = convertToPixels;
frame.PropertyChanged += FrameOnPropertyChanged;
}
public override bool IsStateful
{
get { return false; }
}
public override int Opacity
{
get { return 0; }
}
public override void Draw(ACanvas canvas)
{
SetBorderColorandWidth(canvas);
}
private void SetBorderColorandWidth(ACanvas canvas)
{
int width = Bounds.Width();
int height = Bounds.Height();
if (width <= 0 || height <= 0)
{
if (_normalBitmap != null)
{
_normalBitmap.Dispose();
_normalBitmap = null;
}
return;
}
if (_normalBitmap == null || _normalBitmap.Height != height || _normalBitmap.Width != width)
{
_normalBitmap = CreateBitmap(false, width, height);
}
Bitmap bitmap = _normalBitmap;
// if(canvas)
if (InspectionQAPage._highlight_color)
{
using (var paint = new Paint { AntiAlias = true })
using (var path = new Path())
using (Path.Direction direction = Path.Direction.Cw)
using (Paint.Style style = Paint.Style.Stroke)
using (var rect = new RectF(0, 0, width, height))
{
float rx = Forms.Context.ToPixels(4);
float ry = Forms.Context.ToPixels(4);
path.AddRoundRect(rect, rx, ry, direction);
if (this._frame.OutlineColor == Xamarin.Forms.Color.Red)
{
paint.Color = Android.Graphics.Color.Red;
this._frame.ClassId = "10";
// this._frame.BackgroundColor = Xamarin.Forms.Color.Red;
// paint.SetStyle = (Paint.Style)(Resource.Style.WithBorder);
}
else
{
// paint.Reset();
paint.Color = Android.Graphics.Color.Transparent;
// this._frame.BackgroundColor = Xamarin.Forms.Color.Transparent;
}
paint.StrokeWidth = 10f; //set outline stroke
paint.SetStyle(style);
canvas.DrawPath(path, paint);
}
InspectionQAPage._highlight_color = false;
}
else
{
using (var paint = new Paint())
canvas.DrawBitmap(bitmap, 0, 0, paint);
}
// InvalidateSelf();
}
public override void SetAlpha(int alpha)
{
}
public override void SetColorFilter(ColorFilter cf)
{
}
protected override void Dispose(bool disposing)
{
if (disposing && !_isDisposed)
{
if (_normalBitmap != null)
{
_normalBitmap.Dispose();
_normalBitmap = null;
}
_isDisposed = true;
}
base.Dispose(disposing);
}
protected override bool OnStateChange(int[] state)
{
return false;
}
Bitmap CreateBitmap(bool pressed, int width, int height)
{
Bitmap bitmap;
using (Bitmap.Config config = Bitmap.Config.Argb8888)
if (width <= 0 || height <= 0)
{
return null;
}
else
bitmap = Bitmap.CreateBitmap(width, height, config);
using (var canvas = new ACanvas(bitmap))
{
// DrawCanvas(canvas, width, height, pressed);
}
return bitmap;
}
void FrameOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName ||
e.PropertyName == Frame.OutlineColorProperty.PropertyName ||
e.PropertyName == Frame.CornerRadiusProperty.PropertyName)
{
try
{
if (_normalBitmap == null)
return;
int width = Bounds.Width();
int height = Bounds.Height();
if (width <= 0 || height <= 0)
{
return;
}
if (_canvas == null)
{
var canvas = new ACanvas(_normalBitmap);
_canvas = canvas;
_canvas.DrawColor(global::Android.Graphics.Color.Red, PorterDuff.Mode.Clear);
DrawCanvas(_canvas, width, height, false, sender);
}
else
{
_canvas.DrawColor(global::Android.Graphics.Color.Red, PorterDuff.Mode.Clear);
DrawCanvas(_canvas, width, height, false, sender);
}
InvalidateSelf();
}
catch (Exception ex)
{
Console.WriteLine(">>>>>>>>>>>>>>>>>>>>>>>>>>" + ex);
throw;
}
}
}
public void DrawCanvas(ACanvas canvas, int width, int height, bool pressed, object sender)
{
using (var paint = new Paint { AntiAlias = true })
using (var path = new Path())
using (Path.Direction direction = Path.Direction.Cw)
using (Paint.Style style = Paint.Style.Stroke)
using (var rect = new RectF(0, 0, width, height))
{
float rx = Forms.Context.ToPixels(4);
float ry = Forms.Context.ToPixels(4);
path.AddRoundRect(rect, rx, ry, direction);
if (((Frame)sender).OutlineColor == Xamarin.Forms.Color.Red)
{
paint.Color = Android.Graphics.Color.Red;
((Frame)sender).ClassId = "10";
}
else
{
((Frame)sender).BackgroundColor = Xamarin.Forms.Color.Transparent;
}
paint.StrokeWidth = 10f; //set outline stroke
paint.SetStyle(style);
canvas.DrawPath(path, paint);
}
}
}
}
}
I have added logic to show the Sprite animating but it's simply not showing on the screen. What am I doing wrong?
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input.Touch;
namespace MyXNAGame.Game_Classes
{
public class Player : Sprite
{
private int _frameCount = 6;
private int _frameIndex;
private Rectangle[] _frames;
public float _jumpVelocity = 12f;
public PlayerState _playerState;
public Rectangle BoundingBox
{
get { return new Rectangle {X = (int) Position.X, Y = (int) Position.Y, Height = Texture.Height, Width = Texture.Width}; }
}
public void Initialize()
{
_frames = new Rectangle[_frameCount];
int width = Texture.Width / _frameCount;
for (int i = 0; i < _frameCount; i++)
{
_frames[i] = new Rectangle(i*width, 0, width, Texture.Height);
}
}
public void Load(ContentManager contentManager, string assetName)
{
Texture = contentManager.Load<Texture2D>(assetName);
}
public void Update(GameTime gameTime)
{
while (TouchPanel.IsGestureAvailable)
{
GestureSample gestureSample = TouchPanel.ReadGesture();
if (gestureSample.GestureType == GestureType.Tap)
{
if (_playerState == PlayerState.Running)
{
_playerState = PlayerState.NormalJump;
}
}
if (gestureSample.GestureType == GestureType.Hold)
{
if (_playerState == PlayerState.Running)
{
_playerState = PlayerState.LongJump;
}
}
}
// NormalJump Logic
switch (_playerState)
{
case PlayerState.NormalJump:
Position.Y -= _jumpVelocity;
_jumpVelocity -= 0.5f;
if (_jumpVelocity == 0)
{
_playerState = PlayerState.Falling;
}
break;
case PlayerState.LongJump:
Position.Y -= _jumpVelocity;
_jumpVelocity -= 0.5f;
if (_jumpVelocity == 0)
{
_playerState = PlayerState.Falling;
}
break;
case PlayerState.Falling:
Position.Y += _jumpVelocity;
_jumpVelocity += 0.5f;
break;
case PlayerState.Running:
_frameIndex++;
if (_frameIndex > 5)
{
_frameIndex = 0;
}
break;
}
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(Texture, Position, _frames[_frameIndex], Color.White, 0, new Vector2(0, 0), new Vector2(0, 0), SpriteEffects.None, 0);
}
}
}`
Can anyone see the obvious mistake? I am using WP7
I changed the 'Scale' parameter in the Draw() method from new Vector(0,0) to new Vector(1,1) as obviously, having a Scale of 0 will not show anything at all.
Do you know some way to programmaticaly show different typing indicators on the screen?
I know I can simply draw bitmap but I'd like to do it universally for any RIM OS version.
Also, there is a setMode(int) function in 4.2.1 but in 4.3 it's already deprecated...
Any suggestions will be helpful, thanks!
since there is no alternatives, I made a sample with provided images:
alt text http://img42.imageshack.us/img42/6692/typeindicator.jpg
alt text http://img3.imageshack.us/img3/5259/inputind.jpg
custom Title Field class code:
class TITitleField extends Field implements DrawStyle {
static final boolean mIsDimTheme = Integer.parseInt(DeviceInfo
.getDeviceName().substring(0, 4)) < 8900;
static final Bitmap ALT = Bitmap.getBitmapResource(mIsDimTheme ?
"typ_ind_alt_mode_Gen_Zen_328560_11.jpg" :
"typ_ind_alt_mode_Precsn_Zen_392908_11.jpg");
static final Bitmap MULTITAP = Bitmap.getBitmapResource(mIsDimTheme ?
"typ_ind_mltap_mode_Gen_Zen_328975_11.jpg" :
"typ_ind_mutlitap_mode_Precsn_Zen_452907_11.jpg");
static final Bitmap NUMLOCK = Bitmap
.getBitmapResource(mIsDimTheme ?
"typ_ind_num_lock_Gen_Zen_328568_11.jpg" :
"typ_ind_num_lock_Precsn_Zen_392925_11.jpg");
static final Bitmap SHIFT = Bitmap.getBitmapResource(mIsDimTheme ?
"typ_ind_shift_mode_Gen_Zen_328574_11.jpg" :
"typ_ind_shift_mode_Precsn_Zen_392931_11.jpg");
public static final int MODE_NONE = 0;
public static final int MODE_ALT = 1;
public static final int MODE_MULTITAP = 2;
public static final int MODE_NUMLOCK = 3;
public static final int MODE_SHIFT = 4;
public void setTypingIndicatorMode(int mode) {
mMode = mode;
updateLayout();
}
public int getTypingIndicatorMode()
{
return mMode;
}
int mWidth = 0;
int mMode = 0;
String mTitle = "";
XYRect mIndicatorDestRect = new XYRect();
public TITitleField() {
this("");
}
public TITitleField(String title) {
mTitle = title;
}
protected void paint(Graphics graphics) {
graphics.drawText(mTitle, 0, 0, LEFT | ELLIPSIS, mWidth);
if (0 != mMode) {
graphics.drawBitmap(mIndicatorDestRect,getIndicator(mMode),0,0);
}
}
private static Bitmap getIndicator(int mode) {
Bitmap result = null;
switch (mode) {
case MODE_ALT:
result = ALT;
break;
case MODE_MULTITAP:
result = MULTITAP;
break;
case MODE_NUMLOCK:
result = NUMLOCK;
break;
case MODE_SHIFT:
result = SHIFT;
break;
case MODE_NONE:
break;
default:
break;
}
return result;
}
protected void layout(int width, int height) {
mWidth = width;
if (0 != mMode) {
Bitmap indicator = getIndicator(mMode);
mIndicatorDestRect.width = indicator.getWidth();
mIndicatorDestRect.height = indicator.getHeight();
mIndicatorDestRect.y = 0;
mIndicatorDestRect.x = mWidth - mIndicatorDestRect.width;
}
setExtent(width, getPreferredHeight());
}
public int getPreferredHeight() {
int height = getFont().getHeight() + 4;
if (0 != mMode) {
int indicatorHeight = getIndicator(mMode).getHeight();
height = Math.max(height, indicatorHeight);
}
return height;
}
}
Sample of use code:
class Scr extends MainScreen {
static final TITitleField mTitle = new TITitleField("Start");
public Scr() {
this.setTitle(mTitle);
}
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
int typingIndicatorMode = mTitle.getTypingIndicatorMode();
if(typingIndicatorMode != mTitle.MODE_NONE)
menu.add(new MenuItem("None Mode", 0, 0) {
public void run() {
mTitle.setTypingIndicatorMode(mTitle.MODE_NONE);
}
});
if(typingIndicatorMode != mTitle.MODE_ALT)
menu.add(new MenuItem("Alt Mode", 0, 0) {
public void run() {
mTitle.setTypingIndicatorMode(mTitle.MODE_ALT);
}
});
if(typingIndicatorMode != mTitle.MODE_MULTITAP)
menu.add(new MenuItem("Multitap Mode", 0, 0) {
public void run() {
mTitle.setTypingIndicatorMode(mTitle.MODE_MULTITAP);
}
});
if(typingIndicatorMode != mTitle.MODE_NUMLOCK)
menu.add(new MenuItem("NumLock Mode", 0, 0) {
public void run() {
mTitle.setTypingIndicatorMode(mTitle.MODE_NUMLOCK);
}
});
if(typingIndicatorMode != mTitle.MODE_SHIFT)
menu.add(new MenuItem("Shift Mode", 0, 0) {
public void run() {
mTitle.setTypingIndicatorMode(mTitle.MODE_SHIFT);
}
});
}
}
I have a background bitmap in my Blackberry application screen. Screen has scrolling enabled as i must to have a scroll. The problem which i'm facing is, when i scroll down the page, background bitmap doesn't fit for the scrolled page, rather it shows just plain white background. Do we need to draw the background bitmap for every scrolling page?
My bitmap size is: 360 * 480
Updated code is:
class BGVerticalFieldManager extends VerticalFieldManager {
Bitmap mBgBitmap = null;
int mBgWidth = -1;
int mBgHeight = -1;
int mBgX = -1;
int mBgY = -1;
public BGVerticalFieldManager(Bitmap background) {
super(USE_ALL_WIDTH | USE_ALL_HEIGHT | VERTICAL_SCROLL
| VERTICAL_SCROLLBAR);
mBgBitmap = background;
mBgWidth = mBgBitmap.getWidth();
mBgHeight = mBgBitmap.getHeight();
mBgX = (Display.getWidth() - mBgWidth) >> 1;
mBgY = (Display.getHeight() - mBgHeight) >> 1;
}
protected void paintBackground(Graphics graphics) {
paintBackgroundBitmap(graphics);
invalidate();
}
/*private void paintBackgroundBitmap(Graphics graphics) {
if (null != mBgBitmap) {
int x = mBgX + ((MainScreen)getScreen())
.getMainManager().getHorizontalScroll();
int y = mBgY + ((MainScreen)getScreen())
.getMainManager().getVerticalScroll();
graphics.drawBitmap(x, y, mBgWidth,
mBgHeight, mBgBitmap, 0, 0);
}
} */
private void paintBackgroundBitmap(Graphics graphics) {
if (null != mBgBitmap) {
int x = mBgX
+ getHorizontalScroll();
int y = mBgY
+ getVerticalScroll();
graphics.drawBitmap(x, y, mBgWidth, mBgHeight, mBgBitmap, 0, 0);
}
}
}
CALLING THE ABOVE BACKGROUND BITMAP CODE FROM THE ANOTHER FILE AS BELOW :
public MyFirstScreen ( String label, int screenState, int selectedObj, boolean bUI )
{
super(VERTICAL_SCROLL | VERTICAL_SCROLLBAR); // I must need it ...
appTitle = label;
setTitle(appTitle);
background = Bitmap.getBitmapResource ("HomeBack.png");
add(_container = new BGVerticalFieldManager(background));
..............................
..............................
..............................
}
To get actual scroll position you can use getVerticalScroll():
class BGVerticalFieldManager extends VerticalFieldManager {
Bitmap mBgBitmap = null;
int mBgWidth = -1;
int mBgHeight = -1;
int mBgX = -1;
int mBgY = -1;
public BGVerticalFieldManager(Bitmap background) {
super(USE_ALL_WIDTH | USE_ALL_HEIGHT | VERTICAL_SCROLL
| VERTICAL_SCROLLBAR);
mBgBitmap = background;
mBgWidth = mBgBitmap.getWidth();
mBgHeight = mBgBitmap.getHeight();
mBgX = (Display.getWidth() - mBgWidth) >> 1;
mBgY = (Display.getHeight() - mBgHeight) >> 1;
}
protected void paintBackground(Graphics graphics) {
paintBackgroundBitmap(graphics);
invalidate();
}
private void paintBackgroundBitmap(Graphics graphics) {
if (null != mBgBitmap) {
int x = mBgX
+ getHorizontalScroll();
int y = mBgY
+ getVerticalScroll();
graphics.drawBitmap(x, y, mBgWidth, mBgHeight, mBgBitmap, 0, 0);
}
}
}
alt text http://img693.imageshack.us/img693/6245/9000.jpg
Sample of use:
class Scr extends MainScreen {
private BGVerticalFieldManager mContainer;
public Scr() {
super(NO_VERTICAL_SCROLL);
setTitle("Screen Title");
Bitmap bitmap = Bitmap.getBitmapResource("BoldOEM.jpg");
add(mContainer = new BGVerticalFieldManager(bitmap));
for (int i = 0; i < 100; i++) {
mContainer.add(new LabelField("List item #" + String.valueOf(i)));
mContainer.add(new NullField(FOCUSABLE));
}
}
}
Max Gontar's response is a battery killer;
protected void paintBackground(Graphics graphics) {
paintBackgroundBitmap(graphics);
invalidate();
}
As invalidate() will result in a call to paintBackground(Graphics).
I need to display a custom icon and two hyperlinks in model pop up on Blackberry map. How can I do this?
alt text http://img689.imageshack.us/img689/2886/maplinkicon.jpg
First implement extention of ButtonField which will:
look like icon
on click will open Browser with predefined link
will use context menu
Code for such control:
class MapLinkIcon extends ButtonField implements FieldChangeListener {
Bitmap mNormal;
Bitmap mFocused;
String mLink;
String mDescription;
int mWidth;
int mHeight;
public MapLinkIcon(Bitmap normal, Bitmap focused, String link,
String description) {
super(CONSUME_CLICK);
mNormal = normal;
mFocused = focused;
mLink = link;
mDescription = description;
mWidth = mNormal.getWidth();
mHeight = mNormal.getHeight();
setMargin(0, 0, 0, 0);
setPadding(0, 0, 0, 0);
setBorder(BorderFactory.createSimpleBorder(new XYEdges(0, 0, 0, 0)));
setBorder(VISUAL_STATE_ACTIVE, BorderFactory
.createSimpleBorder(new XYEdges(0, 0, 0, 0)));
this.setChangeListener(this);
}
protected void paint(Graphics graphics) {
Bitmap bitmap = null;
switch (getVisualState()) {
case VISUAL_STATE_NORMAL:
bitmap = mNormal;
break;
case VISUAL_STATE_FOCUS:
bitmap = mFocused;
break;
case VISUAL_STATE_ACTIVE:
bitmap = mFocused;
break;
default:
bitmap = mNormal;
}
graphics.drawBitmap(0, 0, bitmap.getWidth(), bitmap.getHeight(),
bitmap, 0, 0);
}
public int getPreferredWidth() {
return mWidth;
}
public int getPreferredHeight() {
return mHeight;
}
protected void layout(int width, int height) {
setExtent(mWidth, mHeight);
}
protected void applyTheme(Graphics arg0, boolean arg1) {
}
public void fieldChanged(Field field, int context) {
openLink(mLink);
}
MenuItem mMenuItem = new MenuItem("Go To Link", 0, 0) {
public void run() {
openLink(mLink);
}
};
protected void makeContextMenu(ContextMenu contextMenu) {
super.makeContextMenu(contextMenu);
contextMenu.addItem(mMenuItem);
}
private static void openLink(String link) {
Browser.getDefaultSession().displayPage(link);
}
}
Now we can use this button control in combination with MapField, override sublayout to place button over the map:
class CustomMapField extends VerticalFieldManager {
MapField mMapField;
MapLinkIcon mButton;
public CustomMapField() {
add(mMapField = new MapField());
}
public int getPreferredHeight() {
return getScreen().getHeight();
}
public int getPreferredWidth() {
return getScreen().getWidth();
}
public void moveTo(Coordinates coordinates, Bitmap icoNorm, Bitmap icoAct,
String link, String description) {
mMapField.moveTo(coordinates);
add(mButton = new MapLinkIcon(icoNorm, icoAct, link, description));
}
protected void sublayout(int maxWidth, int maxHeight) {
int width = getPreferredWidth();
int height = getPreferredHeight();
layoutChild(mMapField, width, height);
setPositionChild(mMapField, 0, 0);
layoutChild(mButton, mButton.mWidth, mButton.mHeight);
XYPoint fieldOut = new XYPoint();
mMapField.convertWorldToField(mMapField.getCoordinates(), fieldOut);
int xPos = fieldOut.x - mButton.mWidth / 2;
int yPos = fieldOut.y - mButton.mHeight;
setPositionChild(mButton, xPos, yPos);
setExtent(width, height);
}
}
Example of use:
class Scr extends MainScreen {
CustomMapField mMapField;
Coordinates mCoordinates;
public Scr() {
double latitude = 51.507778;
double longitude = -0.128056;
mCoordinates = new Coordinates(latitude, longitude, 0);
mMapField = new CustomMapField();
Bitmap icoNormal = Bitmap.getBitmapResource("so_icon_normal.png");
Bitmap icoActive = Bitmap.getBitmapResource("so_icon_active.png");
String link = "http://stackoverflow.com";
String description = "StackOverflow";
mMapField.moveTo(mCoordinates, icoNormal, icoActive, link, description);
add(mMapField);
}
}
See also:
How to show our own icon in BlackBerry Map?
How to show more than one location in Blackberry MapField?