2016-03-28 5 views
1

Как центральный узел gluon view У меня есть scrollpane, который содержит несколько текстовых полей в vbox. Когда одно из этих текстовых полей становится фокусным менеджером и появляется клавиатура, текстовое поле не перестраивается в соответствии с расположением клавиатуры, поэтому оно остается закрытым клавиатурой. Я попытался положитьПокрытия клавиатуры TextField

android:windowSoftInputMode="adjustResize" 

в AndroidManifest, но без какого-либо успеха.

В качестве обходного пути я переводю y-координаты закрытого текстового поля в видимую область. Когда вы нажимаете кнопку обратной связи Android, чтобы скрыть клавиатуру, позиция текстовых полей будет сброшена в исходное состояние. Вопрос я получаю здесь в том, что я не получаю событие для кнопки андроида назад, независимо от того, где я добавить слушатель:

view.addEventFilter(MobileEvent.BACK_BUTTON_PRESSED, evt -> eventFilter); 

MobileApplication.getInstance().getGlassPane().addEventFilter(MobileEvent.BACK_BUTTON_PRESSED, evt -> eventFilter); 

Есть ли возможность обрабатывать позиционирование узла под клавиатуры или получить ссылку на клавиатуру?

ответ

1

Это решение, которое я мог придумать до сих пор:

public class PositionAdjuster { 

    public static void main(String[] args) { launch(args); } 

    private static final float SCALE = FXActivity.getInstance().getResources().getDisplayMetrics().density; 

    private Node     nodeToAdjust; 
    private ObservableValue<Node> focusOwner; 

    private ViewGroup    viewGroup; 
    private Rect     currentBounds; 
    private DoubleProperty height; 

    private OnGlobalLayoutListener layoutListener; 

    public PositionAdjuster(Node nodeToAdjust, ObservableValue<Node> focusOwner) { 
     this.nodeToAdjust = nodeToAdjust; 
     this.focusOwner = focusOwner; 

     initLayoutListener(); 
    } 

    private void initLayoutListener() { 
     double screenHeight = MobileApplication.getInstance().getScreenHeight(); 
     height = new SimpleDoubleProperty(screenHeight); 
     height.addListener((ov, n, n1) -> onHeightChanged(n, n1)); 

     layoutListener =() -> height.set(getCurrentHeigt()); 

     viewGroup = FXActivity.getViewGroup(); 
     viewGroup.getViewTreeObserver().addOnGlobalLayoutListener(layoutListener); 
     currentBounds = new Rect(); 
    } 

    private float getCurrentHeigt() { 
     viewGroup.getRootView().getWindowVisibleDisplayFrame(currentBounds); 
     return currentBounds.height()/SCALE; 
    } 

    private void onHeightChanged(Number oldValue, Number newValue) { 
     double heightDelta = newValue.doubleValue() - oldValue.doubleValue(); 

     if (heightDelta < 0) { 
      double maxY = getBoundsInScene(nodeToAdjust)).getMaxY(); 
      double currentMaxY = heightDelta + maxY; 

      double result = currentMaxY- getBoundsInScene(focuseOwner.getValue()).getMaxY(); 

      if (result < 0) { 
       nodeToAdjust.setTranslateY(result); 
      } 

     } else if (heightDelta > 0) { 
      nodeToAdjust.setTranslateY(0); 
     } 
    } 

    private Bounds getBoundsInScene(Node node) { 
     return node.localToScene(node.getBoundsInLocal()); 
    } 

    public void removeListener() { 
     viewGroup.getViewTreeObserver().removeOnGlobalLayoutListener(layoutListener); 
    } 
} 

EDIT:

Я думаю, что это более простой подход. Предыдущая версия зависела от максимума noteToAdjust, равного высоте экрана, не принимая во внимание, например, наличие нижнего бара. Теперь позиция maxY focusedNode проверяется против видимой высоты экрана, а разность используется для перестановки ее родителя.

public AndroidPositionAdjuster(Node parent, ObservableValue<Node> focusOwner) { 
    this.parent = parent; 
    this.focusOwner = focusOwner; 

    initLayoutListener(); 
} 

private void onHeightChanged(Number oldHeight, Number newHeight) { 
    double heightDelta = newHeight.doubleValue() - oldHeight.doubleValue(); 

    if (heightDelta < 0) { 
     double maxY = newHeight.doubleValue(); 
     double focusedNodeY = getBoundsInScene(focusOwner.getValue()).getMaxY(); 
     double result = maxY - focusedNodeY; 

     if (result < 0) { 
      parent.setTranslateY(result); 
     } 

    } else if (heightDelta > 0) { 
     parent.setTranslateY(0); 
    } 
} 
+0

Красиво сделано! Получили ли вы его полностью? Для установки обработчика требуется несколько дополнительных шагов. –

+0

Кажется работать. Интересно, что вы имеете в виду, «для этого требуется несколько дополнительных шагов»? GlobalLayoutListener отлично работает. Я просто не знал, как получить доступ к rootView. Либо «FXActivity.getViewGroup(). GetRootView() или FXActivity.getInstance(). GetWindow(). GetDecorView()'. – jns

+0

Я имел в виду, что в проекте с несколькими представлениями установка регулятора для текстового поля требует прослушивания, когда отображается представление. –

1

Только слои получают событие MobileEvent.BACK_BUTTON_PRESSED. Одним из решений является переход на родной язык и использование Android API.

+0

Интересный намек, спасибо педро. возможно, это должно быть в документации об очаровании. – jns

+0

Это изменится в будущем. При нажатии кнопки Charm down будут возвращены кнопки. – Pedro