I created for BlackberryMaps a own menu item with help of "MenuItem" and invoke Blackberry Maps. After using this Item the current location (MapView) should be send back to my Application. This works fine.
The problem is I found no solution for closing the app after using the menu Item. Is there a possibility to close Blackberry Maps? Or set my own App to foreground?
private static class MapMenuItem extends ApplicationMenuItem {
//creates a new MenuItem for Blackberry Maps and defines the action which should //happen after a click on the MenuItem
CustomDialog_GPS customDialogGps;
StartScreen startScreen;
MapMenuItem(StartScreen startScreen, CustomDialog_GPS customDialogGps) {
super(20);
this.startScreen = startScreen;
this.customDialogGps = customDialogGps;
}
public String toString() {
//creates the name for the navigation Menu
String itemName = ""+_res.getString(CUSTOMDIALOG_GPS_USE_AS_NEW_LOCATION);
return itemName;
}
public Object run(Object context) {
//defines what should happen after a click on the menu
//get the location at which the cursor is pointing at.
MapView mv = (MapView)context;
if (mv != null) {
//opens a method inside of CustomDialogGPS which handles the latitude and longitude
customDialogGps.saveAdjustedPosition(mv);
//TODO pop Screen
//Screen screen = (Screen)UiApplication.getUiApplication().getActiveScreen();
}
else {
throw new IllegalStateException("Context is null, expected a MapView instance");
}
return null;
}
}
Unfortunately you can't close another app programmatically (Actually you can if you know where is menu item to close for example) but you can foreground your app UiApplication.getApplication().requestForeground(). What is probably appropriate solution for you.
Instead of passing the user to the Maps application, which is outside your app and you have no control over it, create your own screen with a MapField in it. Using your own screen and perhaps extending the MapField class to override functions if needed, allows you to go back to the previous screen once the user selects a location.
Related
When using DockPanelSuite, is it possible to have a context menu for the tab strip that is different from the one for a document tab? For example, right click an empty space on the tab strip and get one context menu then right click a document tab and get a different context menu specific to the document.
I tried setting the ContextMenuStrip property of the DockPanel. I got a context menu for any empty space on the DockPanel control as well as the document tab strip when visible and all open document tabs. That's a good start but I really only wanted the context menu for the tab strip. Not the main control or any tabs.
I also followed along with the sample project to make a context menu for the document by setting the TabPageContextMenuStrip property of the DockContent form. I discovered that you get a document specific context menu by right clicking the document tab, but it also overrides the DockPanel's ContextMenuStrip. While that is useful, it's still not the desired result.
Edit:
Updating this post in case anyone else is interested in achieving the objective of the question.
After much source code analysis and testing, I concluded that the objective could not be achieved using the available public Properties, Methods, and Events. However, we can achieve the goal by using a bit of reflection.
Discoveries:
DockContent.ContextMenuStrip
This property does nothing for the DockPanel. It will provide a context menu in the client area of the document. However, for some reason, the RichTextBox control set to Fill in the provided sample blocks the context menu from popping up.
DockContent.TabPageContextMenuStrip
This property causes the associated ContextMenuStrip to display when the document is active. However, it displays when you right click anywhere on the tab strip, not just when you right click the document tab.
Solution:
First, add a public property to the DockContent form which will contain a reference to the context menu.
public ContextMenuStrip TabContextMenu { get { return contextMenuTabPage; } }
Next, add an event handler in the MDI main form for the DockPanel.ActiveDocmentChanged event. This will be used to add an event handler to the tab strip after it’s been created.
this.dockPanel.ActiveDocumentChanged += new System.EventHandler(this.dockPanel_ActiveDocumentChanged);
private void dockPanel_ActiveDocumentChanged(object sender, EventArgs e)
{
// Hook into the document pane tabstrip mouse up event
// if we haven't already.
if (dockPanel.ActiveDocumentPane != null
&& dockPanel.ActiveDocumentPane.TabStripControl != null
&& dockPanel.ActiveDocumentPane.TabStripControl.Tag == null)
{
dockPanel.ActiveDocumentPane.TabStripControl.Tag = "MouseUp Hooked";
dockPanel.ActiveDocumentPane.TabStripControl.MouseUp +=
TabStripControl_MouseUp;
}
}
Finally, add the event handler for the TabStripControl.
private void TabStripControl_MouseUp(object sender, MouseEventArgs e)
{
// Capture right click action
if (e.Button == MouseButtons.Right)
{
ContextMenuStrip menu = contextMenuDocumentPane;
Point screenPos = Cursor.Position;
Point tabstripsPos = dockPanel.ActiveDocumentPane
.TabStripControl.PointToClient(screenPos);
// Determine if cursor is over a tab
var tabstrip = dockPanel.ActiveDocumentPane.TabStripControl;
var tabs = tabstrip.GetType()
.GetProperty("Tabs", BindingFlags.Instance |
BindingFlags.NonPublic).GetValue(tabstrip);
foreach (var tab in (IEnumerable)tabs)
{
var bounds = tab.GetType()
.GetProperty("Rectangle")
.GetValue(tab);
if (((Rectangle)bounds).Contains(tabstripsPos))
{
// Display context menu for this document tab
var document = tab.GetType()
.GetProperty("Content")
.GetValue(tab);
menu = ((ContentWindow)document).TabContextMenu;
}
}
// Show appropriate context menu
menu.Show(screenPos);
}
}
enter image description hereI can't find way to add button with icon to top screen menu. I don't even know name of this bar. I mean swiping down of top screen menu however your are, there are buttons like wifi, bluetooth, screen etc.(picture attached). Maybe someone know name of this bar, link to sdk or how add this button or something connected to it.
It is the Tile Service for the quick settings in the Android, you can check the official document about this.
In addition, I have done a sample to test this api and it worked well.
Just declare a class to extend the TileService, such as:
[Service(Permission = "android.permission.BIND_QUICK_SETTINGS_TILE", Icon = "#drawable/icon", Label = "mymenu", Enabled = true, Exported = true)]
[IntentFilter(new[] { "android.service.quicksettings.action.QS_TILE" })]
public class DemoTitle : TileService
{
public override void OnClick()
{
refresh();
}
public void refresh()
{
var state = QsTile.State;
state = (state == TileState.Active)?TileState.Inactive:TileState.Active;
QsTile.State = state;
QsTile.UpdateTile();
}
}
After this, you can find and add the your custom button to the quick settings when you click the editing button in the bar.
In my BlackBerry application, I have a home screen. The user can then navigate to a settings screen. When the user goes back to the home screen, is there no method that is called on the home screen indicating that the screen has come to the foreground?
I have tried onFocus() with no avail.
Thanks!
Unfortunately, hooking on the onExposed is not enough. I found that in Blackberry dialogs are also screens and even context menus are screens too. They are pushed on top of your screen so you receive onExposed callback when they are dismissed.
Though it's OK in many cases, in other cases it poses a problem - e.g. if I must refresh the screen's content only when the user returns to it, but not after menus/dialogs, then how do I do that? My case is, unfortunately, one of those.
I found no documented way of detecting "covered"/"uncovered" events. Here is my approach. onCovered/onUncovered callbacks are called when the current screen is covered/uncovered by another screen of the app, but not by dialogs/menus/virtual keyboard:
public class MyAppScreen extends MainScreen {
private boolean isCovered;
protected void onExposed() {
Log.d("onExposed");
super.onExposed();
if (isCovered) {
onUncovered();
isCovered = false;
}
}
protected void onObscured() {
Log.d("onObscured");
super.onObscured();
final Screen above = getScreenAbove();
if (above != null) {
if (isMyAppScreen(above)) {
isCovered = true;
onCovered();
}
}
}
private boolean isMyAppScreen(final Screen above) {
return (above instanceof MyAppScreen);
}
protected void onUncovered() {
Log.d("onUncovered");
}
protected void onCovered() {
Log.d("onCovered");
}
protected void onUiEngineAttached(final boolean attached) {
if (attached) {
Log.d("UI Engine ATTACHED");
} else {
Log.d("UI Engine DETACHED");
}
super.onUiEngineAttached(attached);
}
protected void onFocusNotify(final boolean focus) {
if(focus){
Log.d("focus GAINED");
} else {
Log.d("focus LOST");
}
super.onFocusNotify(focus);
}
}
And a test. Try various combinations and see what events you receive in the log.
public class TestLifecycle extends MyAppScreen implements FieldChangeListener {
private final ABNTextEdit txt1;
private final ButtonField btn1;
private final ButtonField btn2;
public TestLifecycle() {
final Manager manager = getMainManager();
txt1 = new ABNTextEdit();
manager.add(txt1);
btn1 = new ButtonField("Dialog", ButtonField.CONSUME_CLICK);
btn1.setChangeListener(this);
manager.add(btn1);
btn2 = new ButtonField("Screen", ButtonField.CONSUME_CLICK);
btn2.setChangeListener(this);
manager.add(btn2);
}
public void fieldChanged(final Field field, final int context) {
if (field == btn1) {
Dialog.alert("Example alert");
} else if (field == btn2) {
UiApplication.getUiApplication().pushScreen(new TestLifecycle());
}
}
}
Update:
This method has a limitation: if a new screen is pushed when a dialog or the soft keyboard has focus your current screen will not receive onCovered/onUncovered notification.
Example A: if you have an input field of fixed size and you push a new screen when the user completes it, your current screen will not receive the notification if the user types very quickly. This happens because in the moment between you call push(newScreen) and it is actually pushed the user clicks on a letter on soft KB and it grabs the focus. So only onObscured is called, but not onCovered.
Solution: explicitly hide the soft keyboard before the push(newScreen).
Example B: if you have a customized dialog which pushes new screen and then dismisses itself, your current screen will not receive the notification. This happens because your customized dialog is not recognized as a screen, so only onObscured is called, but not onCovered.
Solution: dismiss the dialog in the first place returning a result value, and let your screen push the new screen based on that value. -OR- override isMyAppScreen() to return true also for your customized dialog.
You should be able to use protected void onExposed() to detect when it is displayed again.
I started writing a bb app with a menu.
My problem is I don't know how to react if the selected item is clicked. The menu contains some fields in a VerticalFieldManager that is added in a class that extends MainScreen.
I'm sorry for asking such basic stuff, but i googled 1.5 hours now and didnt find a solution or example, Its my very first blackberry app.
Here you go.
This snippet of code defines a new menu item, with a constructor where you specify the label of the menu item and its position on the menu, and a run method which is called when the user clicks on your menu item.
The run method is called on the UI (event) thread, so you are free to update your user interface components from here, or do whatever else you need to do.
I also included a snippet of a screen class that adds the menu item to its menu.
final class MyMenuItem extends MenuItem
{
MyMenuItem()
{
super("Menu item text", 100000, 0);
}
public void run()
{
// The user has clicked on the menu item, and
// this method was called. Do what you need to do.
}
}
final class MyScreen extends MainScreen
{
// ...
protected void makeMenu ( Menu menu, int instance )
{
// let the system build a default menu first
super.makeMenu(menu, instance);
// add your menu item to the screen
menu.add ( new MyMenuItem() );
}
// ...
}
Here is my problem : I would like to create a specific component with the camera and an image representing a target overlaying the VideoControl's view.
First I would like to display the camera in a MainScreen with a TitleBar.
Here is my code :
public class ScanScreen extends MainScreen {
private ScanScreen()
{
super();
this.vfm = new VerticalFieldManager(Field.FIELD_VCENTER);
this.controller = new ScanController(this);
//Initialize the player.
try
{
this.player = javax.microedition.media.Manager.createPlayer("capture://video?encoding=jpeg&width=1024&height=768");
this.player.realize();
this.player.prefetch();
this.videoControl = (VideoControl) this.player.getControl("VideoControl");
if(this.videoControl != null)
{
// Initialize the field where the content of the camera shall be displayed.
Field videoField = (Field) this.videoControl.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field");
// Display the video control.
this.videoControl.setDisplayFullScreen(true);
this.videoControl.setVisible(true);
// Start the player.
this.player.start();
// Add the video field to the main screen.
if(videoField != null)
{
this.vfm.add(videoField);
}
else
{
LabelField sorry = new LabelField("Sorry, we cannot use camera right now.");
this.vfm.add(sorry);
}
}
}
catch(Exception e)
{
Dialog.alert(e.toString());
}
// TODO : the camera is hiding the title bar
this.setTitle("Title");
this.add(this.vfm);
}
}
The first problem is that the view of the VideoContol is hiding my title bar. How can I fix that ?
The second thing : I have a specific rectangular image representing a target with transparency which I would like to displaying over the view of the VideoControl.
I first tried to create a new class extending Field returning the dimensions of this image and make the image displayed in the paint method (this class is "mypackage.CameraField"). Then I tried to instantiate my VideoField with the name of my new class "mypackage.CameraField" in the initDisplayMode ; but the created videoField is null.
So, is there a solution to create that kind of behaviour ? I am thinking about the native application "Video Camera" in the "Multimedia" folder that displays a VideoControl in a specific area of the screen.
Thank you.
Ok, it seems that is not possible to customize the VideoControl in any way. We must use it in fullscreen and cannot display anything on it.