1

gluon ビューの中心ノードとして、vbox にいくつかのテキスト フィールドを含むスクロールペインがあります。これらのテキストフィールドの 1 つがフォーカス所有者になり、キーボードが表示されると、テキストフィールドはキーボードのレイアウトに従って再配置されないため、キーボードで覆われたままになります。入れてみた

 android:windowSoftInputMode="adjustResize"

AndroidManifest にありますが、成功しませんでした。

回避策として、カバーされたテキストフィールドの y 座標を可視領域に変換します。Android の戻るボタンを押してキーボードを非表示にすると、テキスト フィールドの位置が元の状態にリセットされます。私がここで得ている問題は、リスナーをどこに追加しても、Android の [戻る] ボタンのイベントが発生しないことです。

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

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

キーボードの下のノードの配置を処理したり、キーボード自体への参照を取得したりする可能性はありますか?

4

2 に答える 2

1

レイヤーのみが MobileEvent.BACK_BUTTON_PRESSED イベントを取得します。1 つの解決策は、ネイティブに移行して Android API を使用することです。

于 2016-03-29T17:10:03.937 に答える
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);
    }
}

編集:

これはより直接的なアプローチだと思います。noteToAdjust以前のバージョンは、たとえば、bottomBar の存在を考慮せずに、maxY が画面の高さに等しくなるように依存していました。の 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);
    }
}
于 2016-03-31T23:19:12.190 に答える