代号为One的BoxLayout(X_AXIS_SCROLLING)布局管理器

时间:2018-10-21 14:55:13

标签: codenameone

给读者的注释:此问题仅适用于代号One。

我的用例是使一个或多个带有Button的水平滚动条。

我需要一个布局管理器:

  • 将所有组件放置在X轴上;
  • 为每个组件赋予其首选大小;
  • 如果有足够的水平空间,它的作用与BoxLayout(X_AXIS_NO_GROW);
  • 如果水平空间不足,则允许水平滚动以查看所有组件;
  • 在最后一种情况下,它在左侧和右侧添加了一个小箭头,表示可以滚动。

例如,以下代码产生以下屏幕截图:

    Form hi = new Form("BoxLayout X scrolling", BoxLayout.y());

    Container exampleCnt = new Container();
    exampleCnt.setLayout(new BoxLayout(BoxLayout.X_AXIS_NO_GROW));

    for (int i=0; i<=10; i++) {
        int j = i; // for lambda expression
        Button button = new Button("Button " + i);
        button.addActionListener(l -> {Log.p("Button " + j + " tapped");});
        exampleCnt.add(button);
    }

    hi.add(exampleCnt);
    hi.show();

enter image description here

相反,我需要以下屏幕快照中的类似内容。我想用手指水平滚动按钮栏(exampleCnt)。该应用程序应该足够聪明,以免将按钮上的点击与水平滑动以使按钮滚动混淆:

enter image description here

enter image description here

enter image description here

enter image description here

1 个答案:

答案 0 :(得分:1)

有几种方法可以做到这一点,每种方法都有其优点/缺点。让我们开始问这个:

  • 箭头按钮是否可以单击?
  • 它们应该作为覆盖层绘制(当它们出现时,您会在其下方看到按钮)还是应该充当单独的组件?

根据您的回复,您可以选择以下选项之一。

内置滚动支持

这将生成一些内容,这些内容将呈现为叠加层,并且无法滚动,因为滚动采用了滚动条样式的UI,但也适用于这种情况。

您可能需要在setScrollVisible(true)上调用Container

然后在Container中覆盖:

protected void paintScrollbarX(Graphics g) {
    float scrollW = getScrollDimension().getWidth();
    float block = ((float) getWidth()) / scrollW;
    float offset;
    if(getScrollX() + getWidth() == scrollW) {
        // normalize the offset to avoid rounding errors to the bottom of the screen
        offset = 1 - block;
    } else {
        offset = (((float) getScrollX() + getWidth()) / scrollW) - block;
    }
    // here paint the arrows to the left/right based on the values
}

使用包装纸

使用包装纸,您可以仅使用按钮表示箭头。您可以将它们放置在分层布局中以创建叠加效果,也可以将其放置在侧面以创建分隔效果,例如这将导致出现单独的按钮:

BorderLayout wrap = BorderLayout.centerEastWest(scrollableCnt, right, left);

这将导致覆盖:

BorderLayout border = BorderLayout.centerEastWest(null, right, left);
LayeredLayout wrap = LayeredLayout(scrollableCnt, border);

要完成这项工作,我们要基于滚动隐藏/显示组件。 isScrollableX()对于不可滚动的组件将返回false,因此:

if(scrollableCnt.isScrollableX()) {
    left.setVisible(false);
    scrollableCnt.addScrollListener((scrollX, scrollY, oldscrollX, oldscrollY) -> {
        left.setVisible(scrollX > 0);
        // not 100% sure about this line but it should be something close to this
        right.setVisible(scrollX < getScrollDimension().getWidth() - scrollableCnt.getWidth());
    });
} else {
    right.setVisible(false);
    left.setVisible(false);
}