Gluon 移动滚动 Pane 优化

标签 gluon gluon-mobile javafxports

我正在尝试使用嵌套的 VBox 实现 JavaFX ScrollPane,并且在移动设备中滚动太快时遇到一个奇怪的问题。问题是,如果我以较小但快速的向上手势滚动,滚动 Pane 首先会停止半秒,然后继续。它在随机滑动手势中变得滞后。我可以优化这个吗?

这不会发生在桌面版本上,所以我猜测这可能是我的手机和 JavaFX 本身的限制。 当我为滚动 Pane 视口(viewport)设置背景图像时,此问题更加明显。以下是 View 的一些示例代码:

public class StackUserView extends View {

    private Label label;

    public StackUserView(String name) {
        super(name);
        initDisplay();
    }

    private void initDisplay() {
        this.label = new Label("10");
        label.setFont(Font.font(40d));
        VBox box = new VBox();
        box.setSpacing(10);
        box.setAlignment(Pos.CENTER_RIGHT);

        for(int i = 0; i < 100; i++){
            Label label = new Label("HELLO");
            label.setCache(true);
            label.setCacheHint(CacheHint.SPEED);
            label.setCacheShape(true);
            box.getChildren().add(label);
        }

        ScrollPane pane = new ScrollPane(box);
        pane.setCacheHint(CacheHint.QUALITY);
        pane.setFitToHeight(true);
        pane.setFitToHeight(true);

        this.setCenter(pane);
    }

    @Override
    protected void updateAppBar(AppBar appBar) {
        appBar.setNavIcon(MaterialDesignIcon.MENU.button(e -> MobileApplication.getInstance().showLayer(SpeedSelect.MENU_LAYER)));
        appBar.setTitleText(this.getName());
        appBar.getActionItems().add(MaterialDesignIcon.SEARCH.button(e -> System.out.println("Search")));
    }

}

最终,我试图让它滚动尽可能接近实际的 native 移动环境。

我已经能够优化需要滚动的情况,创建一个使用 HBox 作为单元格的自定义 CharmListView,但是我无法将 SceneBuilder 用于我的 View ,这会影响可维护性。

注意:我使用 LG G5 进行测试。

这是有关该问题的简短视频。刷卡后就可以看到了。滚动停止一秒钟然后继续:

Scroll lag display.

最佳答案

A.Sharma 提供的答案解决了一些问题,因为它完全删除了内置 ScrollPane 事件处理的底层实现。

当然,要彻底解决这个问题,需要在JavaFXPorts中找到合适的解决方案。

同时,另一种可能的方法可以通过直接在 ScrollPaneSkin 中解决问题来与现有实现更紧密地配合,而 ScrollPaneSkin 又是负责事件处理的类。控制。

可以找到该类 here .

好消息是,此类可以克隆到您的项目(即 MyScrollPaneSkin)、修改并添加为现有 ScrollPane 的外观 控制。

可能的修复

经过一些测试,问题的根源可以定位在 contentsToViewTimeline 动画中。它执行 1.35 秒的暂停来:

block out 'aftershocks'

然后,滚动事件处理程序中有这一行,用于检查动画是否结束并仅在之后更新滚动条位置:

if (!(((ScrollEvent)event).isInertia()) || (((ScrollEvent)event).isInertia()) && 
    (contentsToViewTimeline == null || 
     contentsToViewTimeline.getStatus() == Status.STOPPED)) {
    vsb.setValue(newValue);
    ...
}   

虽然不应删除此动画,但即使动画处于空闲状态,滚动条也应更新。

我进行了以下更改,将第 517-527 行替换为:

    /*
    ** if there is a repositioning in progress then we only
    ** set the value for 'real' events
    */
    if ((newValue <= vsb.getMax() && newValue >= vsb.getMin())) {
        vsb.setValue(newValue);
    }
    boolean stop = ! ((ScrollEvent) event).isInertia() || ((ScrollEvent) event).isInertia() && (contentsToViewTimeline == null || contentsToViewTimeline.getStatus() == Status.STOPPED);
    if ((newValue > vsb.getMax() || newValue < vsb.getMin()) && (!mouseDown && !touchDetected) && stop) {
        startContentsToViewport();
    }
    if (stop) {
        event.consume();
    }

在您的项目中,现在替换内置皮肤:

 ScrollPane pane = new ScrollPane(box);
 pane.setSkin(new MyScrollPaneSkin(pane));

我已经在 Android 和 iOS 上对其进行了测试,在这两种情况下,动画都很流畅,并且没有任何问题的痕迹。

此外,这些属性可能会有所帮助(使用添加到 /src/main/resourcesjava.custom.properties):

gluon.experimental.performance=true
com.sun.javafx.gestures.scroll.inertia.velocity=2000

如果可行,可以将其提交到 JavaFXPorts 问题或作为 PR。

关于Gluon 移动滚动 Pane 优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48489652/

相关文章:

ios - JavaFXPorts - 移动设备上的滚动条问题

scenebuilder - 无法在场景生成器中添加魅力库

java - 有一种方法可以在 javafx 移动设备上更改文本选择句柄光标样式吗?

java - 下载数据时 UI-Thread 似乎滞后

javafx - 在 Raspberry Pi 上使用 JavaFX 播放视频

java - 使用 JavaFX 端口的 Android 上的 NFC

ios - Java FX Gluon移动版

gluon - 配置的compileSdkVersion无效

java - 本地保存列表时 GluonClient 数据丢失

java - 如何将 javaFX 14 应用程序导出为 IntelliJ 中的可执行文件?