I have a scrollabillity issue in a Form, layered out by BoxLayout.y().
The form contains many Tabs (with fixed size), each tab of the Tabs can contain an image or a video (the video is inside a BorderLayout to scale it at the tab size).
If an image is shown, the scrolling up and down works correctly.
If a video is shown, the y scrolling is not possibile, I can only swipe to change the tab.
I suppose that the cause of this issue is that videos are native component (I used the Codename One API to show the videos).
How can I solve or workaround this issue? This is crucial for the app design. Thanks for the tips.
The video.setEnabled(false) workaround (Make videos scrollable) doesn't work.
I workaround in a different way, inserting the MediaPlayer container in a LayeredLayout container, and then placing a Button over the MediaPlayer. A generic empty Label doesn't work, but an empty Button works. Of course I have to override calcPreferredSize to make the MediaPlayer and the Button of the same size (or use a different approach to make them of the same size).
This allows scrolling, but prevents the tapping of the play and pause Buttons (that are over the video). I solved also this issue.
In short, this is my solution, tested on Simulator, Android and iOS (in the following code, note that videoBtnsCnt is a Container over the video, in which I inserted play and pause Buttons):
MediaPlayer mediaPlayer = new MediaPlayer(video) {
#Override
public Dimension getPreferredSize() {
return new Dimension(size, size);
}
};
Container mediaPlayerCnt = new Container(new LayeredLayout(), "NoMarginNoPadding") {
#Override
public Dimension getPreferredSize() {
return new Dimension(size, size);
}
};
mediaPlayerCnt.add(mediaPlayer);
Button allowScrollingLabel = new Button() {
#Override
public Dimension getPreferredSize() {
return new Dimension(size, size);
}
};
allowScrollingLabel.setUIID("NoMarginNoPadding");
allowScrollingLabel.addActionListener(l -> {
Component responder = videoBtnsCnt.getResponderAt(l.getX(), l.getY());
if (responder instanceof Button) {
// it can be a play button or a pause button
((Button) responder).pressed();
((Button) responder).released();
}
});
mediaPlayerCnt.add(allowScrollingLabel);
Related
how can I add a budge to that SideMenu Icon
mainToolbar.addComponentToSideMenu(avatarBox);
mainToolbar.addMaterialCommandToSideMenu(" Home", FontImage.MATERIAL_HOME, e -> {
ManagementDashboard mdas = new ManagementDashboard(this);
mdas.Home();
});
The questions is a bit vague and I am not sure that i understand what you are asking, but in my experience, the only way to customize the toolbar to do anything beyond what the out-of-the-box toolbars methods offer is to use setTitleComponent and add your own custom container to your toolbar. The downside of this is that you will have to redesing a lot of your toolbars as you will be basically creating them again from scratch. You can center a new container with setTitleComponent, override its calcPreferredSize to stretch it across the entire toolbar horizontally, and stick stuff in it as you would in any Container (use any Layout, etc)
Another way of achieving your goal would be to extend the Toolbar class and manually change things within it. But the Toolbar class is quite heavy and you might spend much more time trying to figure out what to change than by using the first method
Method #1 sample code:
//stick stuff in this container to create your own toolbar
Container titleContainer = new Container(new BorderLayout()) {
#Override
protected Dimension calcPreferredSize() {
Dimension original = super.calcPreferredSize();
return new Dimension(Display.getInstance().getDisplayWidth(), original.getHeight());
}
};
form.getToolbar().setTitleComponent(titleContainer);
Here is an example of what could be achieved if you go this route (pretty much anything):
With Codename One components can change their size and this even can be animated, which is nice.
But what is the expected behaviour with shrinking Container instances, specifically if they are scrollable?
Having a Container, scrollable in the Y-axis and content that is smaller than the container the content sticks to the top. The container can be dragged and the content scrolls back to the top of the container. However, when the content shrinks and becomes smaller than the container the behaviour is - somewhat strange.
I have made an example - when the coloured components are tapped they expand. If tapped again they shrink. One can tap the green Label and it expands. Tapping it again it shrinks and everything is as of before.
However, if one taps a coloured label and scrolls any amount down before tapping it again to shrink it this is the resulting view:
Only if one then drags the scrolling container ever so lightly then the contant scrolls back to the top.
I assume this is a bug. Though I wonder - what should be the behaviour when the content shrinks beyond the scrolling containers size? Since the user might expect the component just tapped to remain where it was - can the scrolling behaviour be controlled somehow?
This is just an example but I want to build expandable "drawer" components.
Here is the code:
public class FormContentSmallerScrollableContainer extends Form {
private class LabelExpandable extends Label {
boolean expanded = false;
LabelExpandable(String aTitle, int aColor) {
super(aTitle);
getAllStyles().setBgPainter((aGraphics, aRectangle) -> {
aGraphics.setColor(aColor);
aGraphics.fillRoundRect(getX(), getY(), aRectangle.getWidth() - 1, aRectangle.getHeight() - 1, 20, 20);
});
setOpaque(true);
}
#Override
public void pointerReleased(int x, int y) {
super.pointerReleased(x, y);
expanded = !expanded;
setShouldCalcPreferredSize(true);
getParent().animateLayout(400);
}
#Override
protected Dimension calcPreferredSize() {
if (!expanded) {
return super.calcPreferredSize();
}
Dimension dimension = super.calcPreferredSize();
dimension.setHeight(Display.getInstance().getDisplayHeight());
return dimension;
}
}
public FormContentSmallerScrollableContainer() {
super("FormContentSmallerScrollableContainer");
setScrollable(false);
setLayout(new BorderLayout());
add(BorderLayout.NORTH, new Label("The container below is scrollable in the y-axis"));
Container containerScrollable = BoxLayout.encloseY(
new LabelExpandable("LabelExpandable green", 0x00ff00),
new LabelExpandable("LabelExpandable blue", 0x00c0ff));
containerScrollable.setScrollableY(true);
add(BorderLayout.CENTER, containerScrollable);
add(BorderLayout.SOUTH, new Label("The container above is scrollable in the y axis"));
}
}
This is a long standing behavior when we animate a scrollable area to what's effectively a non-scrollable area. We tried working around this in the past but couldn't find the right approach. You can file the issue on this but I'm not optimistic as it's really hard to even find a workaround for this.
In my cn1-project, the top and left line border for Label, Button and TextField are not shown on an Android 7.0 device. The simulator shows all borders correct. The issue can be easily reproduced with the code from the SignatureComponentDemo on the current cn1 version 4.x for the themes FlatXXXX which also use line borders instead of border images.
I created a new FlatBlue "Get Started App" on Intellij Idea and replaced the code for init(), start(), stop() and destroy() in MyApplication by the code from the SignatureComponentDemo.
The TextField for the name in the demo shows correctly with a line border on the simulator. One the Galaxy S7 edge with Android 7.0 the top and left border of the TextField are missing. Adding more padding for these components has no effect. Also disabling loading of native theme by setting includeNativeBool to false has no effect. The only relevant code is in the following method:
public void start() {
if(current != null){
current.show();
return;
}
Form hi = new Form("Signature Component");
hi.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
hi.add("Enter Your Name:");
hi.add(new TextField());
hi.add("Signature:");
SignatureComponent sig = new SignatureComponent();
sig.addActionListener((evt)-> {
System.out.println("The signature was changed");
Image img = sig.getSignatureImage();
// Now we can do whatever we want with the image of this signature.
});
hi.addComponent(sig);
hi.show();
}
Is there a workaround for this issue? I need to build a table of Components using TableLayout. The table class is no option, because i need to draw borders of different color and thickness and wanted to apply these to the Containers and Components within the container using TableLayout as a layout manager.
I don't need toolbar, title and all that. But I need back button (back button icon with a string back to Home). There is a status bar in iOS. Can I put back btn with icon and text in statusbar? I have seen it in fb. If I go to messenger from fb, back to facebook is in the status bar with time battery icons etc. Can we do that in codenameone?
Back button in status bar (not in title bar) in iOS
What I have done so far. I think this is similar to what have been suggested in the answer. It works in android but in iOS I want to keep the back btn in the status bar with time, battery icons etc.
t = new Toolbar();
t.setUIID("TitleAreaa");
f.setToolBar(t);
Style s = UIManager.getInstance().getComponentStyle("Button");
s.setFont(Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM));
Image backtoRTN = FontImage.createMaterial(FontImage.MATERIAL_ARROW_BACK, s);
back = new Command("Back to RTN", backtoRTN) {
#Override
public void actionPerformed(ActionEvent evt) {
showForm("Main", this);
}
};
back.putClientProperty("uiid", "BacktoRTN");
f.setBackCommand(back);
t.addCommandToLeftBar(back);
The right thing to do here is something similar to what we do in this demo
Notice that the smiley is part of the UI and not part of the title...
The trick for doing this is simple override this method in your Form:
#Override
protected void initGlobalToolbar() {
Toolbar tb = new Toolbar(true);
tb.setUIID("Container");
setToolbar(tb);
getTitleArea().setUIID("Container");
}
That creates a toolbar that is layered (floats on top of the UI). Setting it to Container UIID makes it invisible.
I'm developing a reporting dashboard application using W8 Metro UI style application. The application has a dark theme, so most of the screen is black. I'm using the WebView control to display SSRS .rdl reports from our report server (which all have black backgrounds). The problem I'm seeing is that when I navigate to a new report, the WebView control flashes white for a split second and then loads the new report. To get around this, I tried putting an Easing opacity animation on the WebView control to make it fade out, load the report, and then fade back in. However, no matter what I try, I can't get the flickering to go away.
I then tried putting a black rectangle on top of the WebView and fading that one in and out... still no luck. The WebView is always on top at runtime, meaning I can't put any control on top of it. Does anyone know of a way around this?
I breifly looked into the WebView.Transitions, but couldn't find many resources on this. Could this be my answer?
EDIT:
Event to load the new report:
void ItemListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// Create a WebViewBrush of the content currently loaded in the WebView
WebViewBrush b = new WebViewBrush();
b.SourceName = "WebView1";
b.Redraw();
Rectangle1.Fill = b;
// Hide the WebView
WebView1.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
// Navigate to the new report
var selectedItem = ItemListView.SelectedItem;
WebView1.Navigate(((Report)selectedItem).ReportUri);
}
void WebView1_LoadCompleted(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e)
{
// Show the new report
WebView1.Visibility = Windows.UI.Xaml.Visibility.Visible;
Rectangle1.Fill = new SolidColorBrush(Colors.Transparent);
}
This is just the way WebView works because internally its loading the trident COM control into a separate hwnd. The workaround is to set Visibility to Hidden on the webview and instead show a webviewbrush which isn't interactive but does integrate with the rest of your UI so it can be animated, etc