BlackBerry Touch not going through Fields - blackberry

I have a manager that is handling the Touch click.
In order to have the Manager Focusable I have a Field that is acting as a Background and is focusable, This field change color when it is focused.
The problem is, I have multiple fields on this manager (which are not focusable), like LabelField, BitmapField, etc...
If the user click on one of non-focusable Field, it won't take into account the click on the Cell.
But if the user clicks between 2 non-focusable fields (and then click on the Background Field), the click is took into account and works fine...
I would need some kind of click through set to true, how would I do that ?
P.S. : I do not want to put all Field focusable, because when using the trackball it would go through every Field, I just want the Whole Manager to be selected, not elements inside.

The Manager will actually get the click events - normally it will just pass them on. But you can process them if you want. The following code demonstrates the easiest way I find to make sure I process everything as I want. Try it on a touch screen and non touchscreen phone.
VerticalFieldManager testVFM = new VerticalFieldManager(Manager.USE_ALL_WIDTH) {
protected boolean touchEvent(TouchEvent message) {
int x = message.getX( 1 );
int y = message.getY( 1 );
if( x < 0 || y < 0 || x >= getExtent().width || y >= getExtent().height ) {
// Outside the field
return false;
}
if ( message.getEvent() == TouchEvent.UNCLICK ) {
Status.show("Manager Clicked");
return true;
}
return super.touchEvent(message);
}
};
LabelField testlab = new LabelField("test", LabelField.FIELD_HCENTER);
testVFM.add(testlab);
LabelField testlab2 = new LabelField("test2", LabelField.FIELD_HCENTER);
testVFM.add(testlab2);
testVFM.add(new NullField() {
protected boolean navigationClick(int status, int time){
Status.show("NullField Clicked");
return true;
}
}); // So Manager can get focus

Related

JavaFXPorts - Problems with ScrollBar on Mobile Devices

I'm currently developing a mobile application with JavaFX, using GluonHQ and JavaFXPorts. One of my screens contains a listview as you can see from the screenshot below, which was taken from my iPhone 6.
I have noticed the following problems with the scrollbar in mobile devices:
The first time i touch the screen the scroll bar appears a bit off place and then moves to the correct right position. This just happens quickly only the first time. (Screenshot)
I noticed that the scrollbar appears every time i touch the screen and not only when I touch and drag. On native iOS applications the scrollbar appears only when you touch and drag. If you keep your finger on screen and then remove it the scrollbar does not appear.
The scrollbar always takes some time to disappear when I remove my finger from the screen, whilst in native apps it disappears instantly.
Can anyone help me on fixing these issues. How can you define the time the scrollbar appears before it hides again?
You can experience this situation by just creating a ListView and load it with some items.
UPDATE
Thanks to the answer of Jose Pereda below, I have managed to overcome all three problems described above. Here is the code I used to reach the desired results. Watch this short video to get a quick idea of how the new scrolling bar appears and behaves. Again, Jose, you are the boss! Please go ahead with any comments for improvement.
public class ScrollBarView {
public static void changeView(ListView<?> listView) {
listView.skinProperty().addListener(new ChangeListener<Object>() {
private StackPane thumb;
private ScrollBar scrollBar;
boolean touchReleased = true, inertia = false;
#Override
public void changed(ObservableValue<? extends Object> observable, Object oldValue, Object newValue) {
scrollBar = (ScrollBar) listView.lookup(".scroll-bar");
// "hide" thumb as soon as the scroll ends
listView.setOnScrollFinished(e -> {
if (thumb != null) {
touchReleased = true;
playAnimation();
} // if
});
// Fix for 1. When user touches first time, the bar is set invisible so that user cannot see it is
// placed in the wrong position.
listView.setOnTouchPressed(e -> {
if (thumb == null) {
thumb = (StackPane) scrollBar.lookup(".thumb");
thumb.setOpacity(0);
initHideBarAnimation();
} // if
});
// Try to play animation whenever an inertia scroll takes place
listView.addEventFilter(ScrollEvent.SCROLL, e -> {
inertia = e.isInertia();
playAnimation();
});
// As soon as the scrolling starts the thumb become visible.
listView.setOnScrollStarted(e -> {
sbTouchTimeline.stop();
thumb.setOpacity(1);
touchReleased = false;
});
} // changed
private Timeline sbTouchTimeline;
private KeyFrame sbTouchKF1, sbTouchKF2;
// Initialize the animation that hides the thumb when no scrolling takes place.
private void initHideBarAnimation() {
if (sbTouchTimeline == null) {
sbTouchTimeline = new Timeline();
sbTouchKF1 = new KeyFrame(Duration.millis(50), new KeyValue(thumb.opacityProperty(), 1));
sbTouchKF2 = new KeyFrame(Duration.millis(200), (e) -> inertia = false, new KeyValue(thumb.opacityProperty(), 0));
sbTouchTimeline.getKeyFrames().addAll(sbTouchKF1, sbTouchKF2);
} // if
} // initHideBarAnimation
// Play animation whenever touch is released, and when an inertia scroll is running but thumb reached its bounds.
private void playAnimation() {
if(touchReleased)
if(!inertia || (scrollBar.getValue() != 0.0 && scrollBar.getValue() != 1))
sbTouchTimeline.playFromStart();
} // playAnimation()
});
} // changeView
} // ScrollBarView
As mentioned in the comments, the first issue is known, and for now it hasn't been fixed. The problem seems to be related to the initial width of the scrollbar (20 pixels as in desktop), and then is set to 8 pixels (as in touch enabled devices), and moved to its final position with this visible shift of 12 pixels to the right.
As for the second and third issues, if you don't want to patch and build the JDK yourself, it is possible to override the default behavior, as the ScrollBar control is part of the VirtualFlow control of a ListView, and both can be found on runtime via lookups.
Once you have the control, you can play with its visibility according to your needs. The only problem with this property is that it is already bound and constantly called from the layoutChildren method.
This is quite a hacky solution, but it works for both 2) and 3):
public class BasicView extends View {
private final ListView<String> listView;
private ScrollBar scrollbar;
private StackPane thumb;
public BasicView(String name) {
super(name);
listView = new ListView<>();
// add your items
final InvalidationListener skinListener = new InvalidationListener() {
#Override
public void invalidated(Observable observable) {
if (listView.getSkin() != null) {
listView.skinProperty().removeListener(this);
scrollbar = (ScrollBar) listView.lookup(".scroll-bar");
listView.setOnScrollFinished(e -> {
if (thumb != null) {
// "hide" thumb as soon as scroll/drag ends
thumb.setStyle("-fx-background-color: transparent;");
}
});
listView.setOnScrollStarted(e -> {
if (thumb == null) {
thumb = (StackPane) scrollbar.lookup(".thumb");
}
if (thumb != null) {
// "show" thumb again only when scroll/drag starts
thumb.setStyle("-fx-background-color: #898989;");
}
});
}
}
};
listView.skinProperty().addListener(skinListener);
setCenter(listView);
}
}

Bitmap field taking focus on whole screen

I have added 2 BitmapFields(left and right arrow) on one HorizontalFieldManager, but when I click anywhere on HFM, BitmapFields taking focus and shows that it is selected.
I want not to show focus anywhere until it doesn't click on BitmapFields.
Following is the code for it:
bmfBottomRight = new BitmapField(bmpBottomRightFocused, FOCUSABLE) {
protected boolean navigationClick(int status, int time) {
int fieldIndex = getCurrentFieldIndex();
if (fieldIndex < (surveyList.size() - 1))
updateIncrField(fieldIndex);
return super.navigationClick(status, time);
}
};
bmfBottomLeft.setPadding(5, 0, 5, ((Display.getWidth() - bmfBottomRight.getPreferredWidth()) >> 1) - bmfBottomRight.getPreferredWidth());
I am setting Padding for it..
Have added null fields new NullField(Field.NON_FOCUSABLE). And added two different null fields at left and right of bitmap field. SO I am able to getting the focus on bitmapfield, when only tapping on it.

Automatically change focus among Editfields in Blackberry

I have five EditField objects in my BlackBerry app, each one will accept only one numeric character.
I want to change the focus from the first EditField to the second EditField when a character is entered. Note the focus from one to another EditField must go automatically and not by pressing Enter key or some other key.
You want to set a FieldChangeListener on the EditField to monitor when the contents of the field changes. Once the user has entered a single character you can move to the next field by calling Field.setFocus().
Lets assume your EditFields are added to screen one by one.
You could use next code:
editField<i>.setFieldChangeListener(this);
...
public void fieldChanged(Field field, int status) {
if (field instanceof EditField) {
EditField editField = (EditField)field;
if (field.getText().length() > 0) {//don't move focus in case of deleted text
Manager manager = field.getManager();
Field nextField = manager.getField(manager.getFieldIndex(editField) + 1);
if (nextField instanceof EditField) {
nextField.setFocus();
}
}
}
}

How to change row color background in a ListField after navigation Click?

I'm beginner in BB dev. I create a CustomListField and when I click on a row, the background color of this row must change and a new screen must be displayed (it's done!).
Could any one please help me to get this done?
thx
Below is the code:
protected boolean navigationClick(int status, int time)
{Field field = this.getLeafFieldWithFocus();
if(field instanceof ListField)
{
// listValues is String[] where you store your list elements.
// listField is the ListField instance you are using
UiApplication.getUiApplication().pushScreen(new ReadMsgScreen());
int index= getIndex();
if(index== this.getSelectedIndex())
{
**// I think the code to change the row's background color must be set here!**
}
return true;
}
return super.navigationClick(status, time);
}
use this it will definately work...
int tmpcolor = graphics.getColor();
graphics.setColor(Color.CYAN);
graphics.fillRect(0, y, width, getRowHeight());
graphics.setColor(tmpcolor);
thanks...
onerride the paint() method in blackberry as showed the code below..
_specialNumbers = new LabelField(Constants.SPECIAL_NUMBERS,LabelField.USE_ALL_WIDTH) {
protected void paintBackground(Graphics arg0) {
int color = arg0.getBackgroundColor();
arg0.setBackgroundColor(Color.LIGHTGREY);
arg0.clear();
arg0.setBackgroundColor(color);
}
};
In the drawListRow() method of the ListFieldCallback for your CustomListField draw that selected line differently and call a Transition to display the other Screen slowly.

scroll change listener on blackberry

I already posted my question below link..
scroll change listener on blackberry
The error has been resolved.
But i need to move the field center position after scrolling . pls give any idea... Thanks in advance...
there are number of fields add in the scroll bar...
after scrolling its show like this.
But i need to move the field center position like this.
Pls give any idea..
Looks like you just need some flag to detect whether this is a sroll event originated by user, or from the code (programmatically).
If you originate a scroll event programmatically, then set some boolean, let's call it ignoreScrollEvent, to true. Smth like this (pseudo code):
private boolean ignoreScrollEvent = false;
public void scrollChanged(Manager manager, int newHorizontalScroll,
int newVerticalScroll) {
if (!ignoreScrollEvent) {
ignoreScrollEvent = true;
// recalculate the newHorizontalScroll so the field in the focus
// gets in the middle
horizontalScrollLayout.setHorizontalScroll(newHorizontalScroll);
int fieldIndex = horizontalScrollLayout.getFieldAtLocation(
newHorizontalScroll + customfieldwidth, 0
);
Field f = horizontalScrollLayout.getField(fieldIndex);
f.setFocus();
invalidate();
} else {
ignoreScrollEvent = false;
}
}

Resources