Reputation: 80
I had created small mobile apps using Gluon Mobile and now on beta testing trough Google Play. but I realized that start-time of my mobile apps on android device is quite slow (take around more than 10 seconds).
it would be great if I can add a SplashScreen before the apps is loaded so user will not waiting in total for 10 times, but they feel only half of it because they got response from apps while seeing the SplashScreen.
on native android development, we just build 2 activity (one for SplashScreen and one the main apps) like blow :
<activity
android:name=”.SplashScreen”>
<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>
<activity
android:name=”.MainActivity”
android:label=”@string/app_name”
>
<intent-filter>
<action android:name=”android.intent.action.MAIN” />
</intent-filter>
</activity>
my Question, is there any approach to show SplashScreen that build on JavaFX/GluOn that will be run both on andorid/ios rather than native. is there any disadvantages if we build on javaFX rather than this native approach.
since the the young age of gluon/javaFX on mobile, is not easy to get the best practice the ideal approach. please en-light me
rgrds
Upvotes: 3
Views: 1143
Reputation: 33
Okay this is old but this still pops up on a google search so here it is. With version 4.x of the plugin, a SplashView is available which hides the appBar by default and can be registered like a normal view only with the name SPLASH_VIEW. The FXML should look like this:
<?xml version="1.0" encoding="UTF-8"?>
<?import com.gluonhq.charm.glisten.mvc.SplashView?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.BorderPane?>
<SplashView fx:id="splash" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/9" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.shara.views.SplashPresenter">
<center>
<ImageView fitHeight="150.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true" BorderPane.alignment="CENTER">
<image>
<Image url="@../../../icon.png" />
</image>
</ImageView>
</center>
<bottom>
<Label BorderPane.alignment="CENTER" />
</bottom>
</SplashView>
Then its controller should look like this:
import com.gluonhq.charm.down.Services;
import com.gluonhq.charm.down.plugins.LifecycleService;
import com.gluonhq.charm.glisten.afterburner.GluonPresenter;
import com.gluonhq.charm.glisten.animation.FadeInTransition;
import com.gluonhq.charm.glisten.application.MobileApplication;
import com.gluonhq.charm.glisten.control.Alert;
import com.gluonhq.charm.glisten.control.LifecycleEvent;
import com.gluonhq.charm.glisten.mvc.SplashView;
import com.shara.Shara;
import com.shara.Network;
import javafx.animation.PauseTransition;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.util.Duration;
/**
*
* @author mighty
*/
public class SplashPresenter extends GluonPresenter<Shara> {
@FXML private SplashView splash;
public void initialize(){
splash.setShowTransitionFactory(FadeInTransition::new);
splash.setOnShown((LifecycleEvent e) -> {
PauseTransition pause = new PauseTransition(Duration.seconds(3));
pause.setOnFinished((ActionEvent f) -> {
splash.hideSplashView();
});
pause.play();
});
}
}
The view is initialized as normal and it can be switched by calling hideSplashView(). The splash view can be styled as normal and and can use stylesheets. The view can be registered in the AppViewManager as such:
public static final AppView SPLASH_VIEW = view("Splash", SplashPresenter.class, MaterialDesignIcon.PAGES);
And in your registerViewsAndDrawer method replace
REGISTRY.getViews().forEach((view) -> {
view.registerView(app);
});
with
REGISTRY.getViews().forEach((view) -> {
if(view.getId() != "SPLASH_VIEW"){
view.registerView(app);
}
});
To be certain your splash screen won't appear in your drawer.
Upvotes: 0
Reputation: 87
I'm a little late but for future Projects this might be useful:
There is a Project on Github that is extending the functionality of Gluon.
https://github.com/Ciruman/QuarkFX
It includes:
Upvotes: 1
Reputation: 45476
While a Splash screen could be a nice idea, actually the Gluon Mobile Multi-View projects created with the Gluon Plugin allow you creating a similar effect by using the Home View as a placeholder for an image or any other lightweight content you want to display, while having all the heavy stuff loaded in a secondary view.
By default, the Home View is the initial view that is loaded during the Application.start()
method. The other views won't be loaded until the user switches to them.
With the following view, only when the user clicks on the floating action button, the actual load of the heavy stuff starts, but the splash view on the mobil device is displayed in no time:
public class SplashView extends View {
public SplashView(String name) {
super(name);
setCenter(new ImageView(new Image(getClass().getResourceAsStream("splash.png"))));
FloatingActionButton action = new FloatingActionButton(MaterialDesignIcon.ARROW_FORWARD.text, e ->
MobileApplication.getInstance().switchView(GluonSplash.SECONDARY_VIEW));
getLayers().add(action);
}
@Override
protected void updateAppBar(AppBar appBar) {
appBar.setVisible(false);
}
}
To avoid the need of user intervention, you can get rid of the action button and start loading the second view, after a certain time of displaying the splash.
In this other sample, after the splash view has been shown, a pause transition starts. After one second, it displays the label to indicate the new view will be loaded. At the same time, a task to load that view is started. When all the heavyweight view is loaded, it will be shown.
public class SplashView extends View {
public SplashView(String name) {
super(name);
Label access = new Label("Accessing...");
access.setTranslateY(200);
access.setVisible(false);
setCenter(new StackPane(new ImageView(new Image(getClass().getResourceAsStream("splash.png"))),
access));
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
Platform.runLater(() -> MobileApplication.getInstance().switchView(GluonSplash.SECONDARY_VIEW));
return null;
}
};
addEventHandler(LifecycleEvent.SHOWN, e -> {
PauseTransition pause = new PauseTransition(Duration.seconds(1));
pause.setOnFinished(f -> {
access.setVisible(true);
new Thread(task).start();
});
pause.play();
});
}
@Override
protected void updateAppBar(AppBar appBar) {
appBar.setVisible(false);
}
}
Upvotes: 2