2017-06-06 9 views
1

私はScrollpaneのVBoxにたくさんのTextfieldを持っています。テキストフィールドをスクロールしたりタッチしたりすると、フォーカスがグラブされます。スムーズなスクロールは不可能です。どのように私はそれを任意のテキストフィールドに望ましくない焦点を当てずに素敵なスクロールを得ることができます。私はスクロールしながら、テキストフィールド上のイベントを消費する必要がありますか?ここでたくさんのテキストフィールドを使ってVBoxをスクロール

答えて

0

は、私はあなたが記述の目的のために使用するクラスです:

public class MouseClickedFilter{ 

    private final Node      observableNode; 

    private BooleanProperty     scrolling   = new ReadOnlyBooleanWrapper(false); 

    private EventHandler<? super MouseEvent> dragDetectedFilter = e -> scrolling.set(true); 
    private EventHandler<? super MouseEvent> mouseExitedHandler = e -> scrolling.set(false); 

    private EventHandler<? super MouseEvent> mouseClickedFilter = evt -> 
                    { 
                     if (scrolling.get()) { 
                      evt.consume(); 
                      scrolling.set(false); 
                     } 
                    }; 

    private boolean       listenersEnabled; 

    public MouseClickedFilter(Node observableNode) { 
     this.observableNode = observableNode; 
    } 

    public void activate() { 
     if (!listenersEnabled) { 
      observableNode.addEventFilter(MouseEvent.DRAG_DETECTED, dragDetectedFilter); 
      observableNode.addEventHandler(MouseEvent.MOUSE_EXITED, mouseExitedHandler); 
      observableNode.addEventFilter(MouseEvent.MOUSE_CLICKED, mouseClickedFilter); 
     } 
    } 

    public void deactivate() { 
     if (listenersEnabled) { 
      observableNode.removeEventFilter(MouseEvent.DRAG_DETECTED, dragDetectedFilter); 
      observableNode.removeEventHandler(MouseEvent.MOUSE_EXITED, mouseExitedHandler); 
      observableNode.removeEventFilter(MouseEvent.MOUSE_CLICKED, mouseClickedFilter); 
     } 
    } 

    public final ReadOnlyBooleanProperty scrollingProperty() { 
     return scrolling; 
    } 

    public final boolean isScrolling() { 
     return scrolling.get(); 
    } 

} 

ObservableNodeこれは、あなたが上をスクロールしたい場合のために可能な解決策であるテキストフィールドに

+0

コードのおかげで、それは助けをdidntの。スクロールしてもまだTextFieldが固執しています。 – tonimaroni

+0

はいスクロールしています。これは、ScrollPaneで使用されているノードにかかわらず、javafxportと組み合わせてAndroid上のScrollPaneの基本的な問題と思われます。 – jns

0

を含むあなたのScrollPaneですテキストフィールドの長いリストを、スクロールを止めるまで、フォーカスを取らずに、明確にテキストフィールドの1つを選択することができます。

これは、この「question」に触発されたカスタムの「プレスアンドホールド」イベントに基づいています。

コントロールはTextFieldコントロールをHBoxにバンドルし、コンテナのマウス透過プロパティを使用してコントロールへのアクセスを無効にすることです。

次に、コンテナをタップするたびに、コンテナがコントロールにアクセスできるようになり、キーボードが表示されます。そうしないと、スクロールは続行されますが、キーボードは表示されません。

このquestionに記載されているKeyboardServiceは、iOSでのみ使用します。

public class BasicView extends View { 

    public BasicView(String name) { 
     super(name); 

     setTop(new Button("Button")); 

     VBox controls = new VBox(15.0); 

     controls.setAlignment(Pos.CENTER); 

     ScrollPane pane = new ScrollPane(controls); 
     controls.prefWidthProperty().bind(pane.widthProperty().subtract(20)); 

     for (int i = 0; i < 100; i++) { 
      final Label label = new Label("TextField " + (i + 1)); 
      final TextField textField1 = new TextField(); 
      HBox.setHgrow(textField1, Priority.ALWAYS); 
      HBox box = new HBox(10, label, textField1); 
      box.setMouseTransparent(true); 

      box.setAlignment(Pos.CENTER_LEFT); 
      box.setPadding(new Insets(5)); 
      controls.getChildren().add(box); 
     } 

     addPressAndHoldHandler(controls, Duration.millis(300), eStart -> { 
       for (Node box : controls.getChildren()) { 
        box.setMouseTransparent(true); 
       } 
      }, eEnd -> { 
       for (Node box : controls.getChildren()) { 
        if (box.localToScene(box.getBoundsInLocal()).contains(eEnd.getSceneX(), eEnd.getSceneY())) { 
         box.setMouseTransparent(false); 
         ((HBox) box).getChildren().get(1).requestFocus(); 
         break; 
        } 
       } 
      }); 
     setCenter(pane); 

     // iOS only 
     Services.get(KeyboardService.class).ifPresent(keyboard -> { 
      keyboard.visibleHeightProperty().addListener((obs, ov, nv) -> { 
       if (nv.doubleValue() > 0) { 
        for (Node box : controls.getChildren()) { 
         Node n1 = ((HBox) box).getChildren().get(1); 
         if (n1.isFocused()) { 
          double h = getScene().getHeight() - n1.localToScene(n1.getBoundsInLocal()).getMaxY(); 
          setTranslateY(-nv.doubleValue() + h); 
          break; 
         } 
        } 
       } else { 
        setTranslateY(0); 
       } 
      }); 
     }); 
    } 

    @Override 
    protected void updateAppBar(AppBar appBar) { 
     appBar.setNavIcon(MaterialDesignIcon.MENU.button(e -> System.out.println("Menu"))); 
     appBar.setTitleText("Scrolling over TextFields"); 
    } 

    private void addPressAndHoldHandler(Node node, Duration holdTime, 
      EventHandler<MouseEvent> handlerStart, EventHandler<MouseEvent> handlerEnd) { 
     class Wrapper<T> { 
      T content; 
     } 

     Wrapper<MouseEvent> eventWrapper = new Wrapper<>(); 

     PauseTransition holdTimer = new PauseTransition(holdTime); 
     holdTimer.setOnFinished(event -> handlerEnd.handle(eventWrapper.content)); 

     node.addEventHandler(MouseEvent.MOUSE_PRESSED, event -> { 
      handlerStart.handle(event); 
      eventWrapper.content = event; 
      holdTimer.playFromStart(); 
     }); 
     node.addEventHandler(MouseEvent.MOUSE_RELEASED, event -> holdTimer.stop()); 
     node.addEventHandler(MouseEvent.DRAG_DETECTED, event -> holdTimer.stop()); 
    } 
} 

ビューを表示すると、最初にフォーカスを得るためにボタンを追加しました。

controls VBoxをクリック/タップすると、すべてのボックスが透明に設定されます(box.setMouseTransparent(true);)。PauseTransitionを開始します。

300ミリ秒前にマウスを離した場合やドラッグした場合(これはあなたの都合で変更できます)、トランジションは停止します。それ以外の場合は、300 ms後にボックスをbox.setMouseTransparent(false);に設定し、TextFieldにフォーカスを合わせると、その時点でキーボードが表示されます。

関連する問題