简体   繁体   中英

Gluon Mobile Charm 5.0 Cannot Hide Layer

I have a loading gif for all backend requests. Prior to Charm 5.0.0, it worked fine in which the loading gif would show, backend would finish what it needed to, then the loading gif would be hidden. Now, the loading gif shows, but it doesn't hide.

addLayerFactory(LOADING_GIF, () -> new Layer() {
            private final Node root;
            private final double sizeX = getGlassPane().getWidth();
            private final double sizeY = getGlassPane().getHeight();

            {
                ProgressIndicator loading = new ProgressIndicator();
                loading.setRadius(50);
                loading.setStyle("-fx-text-fill:white");
                root = new StackPane(loading);
                root.setStyle("-fx-background-color: rgba(0,0,0,0);");
                getChildren().add(root);
                this.setStyle("-fx-background-color:rgba(255,255,255,0.7)");
                this.setShowTransitionFactory(v -> {
                    FadeInTransition ft = new FadeInTransition(v);
                    ft.setRate(2);
                    return ft;
                });
            }

            @Override
            public void show() {
                this.setBackgroundFade(0.0);
                super.show();
                Layer pane = this;
                Task<Integer> task = new Task<Integer>() {
                    @Override
                    protected Integer call() throws Exception {
                        int iterations = 0;
                        int max = DataService.readOutTime / 1000;
                        while (iterations <= max) {
                            Thread.sleep(1000);
                            iterations++;
                        }
                        Platform.runLater(new Runnable() {
                            @Override
                            public void run() {
                                if (pane.isVisible()) {
                                    pane.setShowTransitionFactory(v -> {
                                        FadeOutTransition ft = new FadeOutTransition(v);
                                        ft.setRate(2);
                                        return ft;
                                    });
                                    pane.hide();
                                    MobileApplication.getInstance().showMessage("There was an error in sending your data.");
                                }
                            }
                        });
                        return iterations;
                    }
                };
                Thread thread = new Thread(task);
                thread.start();
            }

            @Override
            public void hide() {
                this.setBackgroundFade(0.0);
                super.hide();
            }

            @Override
            public void layoutChildren() {
                root.setVisible(isShowing());
                if (!isShowing()) {
                    return;
                }
                root.resize(sizeX, sizeY);
                resizeRelocate((getGlassPane().getWidth() - sizeX) / 2, (getGlassPane().getHeight() - sizeY) / 2, sizeX, sizeY);
            }
        });

I have a couple of utility methods that show and hide the loader:

public void showLoader() {
    MobileApplication.getInstance().showLayer(App.LOADING_GIF);
}

public void hideLoader() {
    MobileApplication.getInstance().hideLayer(App.LOADING_GIF);
}

Interestingly, the custom timeout I created (to hide the loader in case there is a stall in the backend) doesn't hide the layer either.

There is an issue with your code: you are overriding Layer::layoutChildren , but you are not calling super.layoutChildren() .

If you check the JavaDoc :

Override this method to add the layout logic for your layer. Care should be taken to call this method in overriden methods for proper functioning of the Layer.

This means that you are getting rid of some important parts of the Layer control, such as animations, events and visibility control.

This should work:

@Override
public void layoutChildren() {
    super.layoutChildren();
    root.setVisible(isShowing());
    if (!isShowing()) {
        return;
    }
    root.resize(sizeX, sizeY);
    resizeRelocate(getGlassPane().getWidth() - sizeX) / 2, getGlassPane().getHeight() - sizeY) / 2, sizeX, sizeY);
}

On a side note, for the hide transition, you should use setHideTransitionFactory .

So this is what I have done to solve this. From the Gluon Docs on the hide() method:

If this layer is showing, calling this method will hide it. If a hide transition is present, it is played before hiding the Layer. Care should be taken to call this only once LifecycleEvent.SHOWN has been fired.

Thus, I was realizing that the response from the backend was coming before the layer was fully shown. Thus, I modified the overridden hide() method as follows:

@Override
public void hide() {
   if (this.isShowing()) {
     this.setOnShown(e -> {
        this.setBackgroundFade(0.0);
        super.hide();
     });
   } else {
     super.hide();
   }
}

So if the layer is still in LifecycleEvent.SHOWING mode when being told to hide, make sure that it hides when it is shown. Otherwise it is already shown so hide it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM