【问题标题】:BoxLayout(X_AXIS_SCROLLING) layout manager for Codename One代号一的 BoxLayout(X_AXIS_SCROLLING) 布局管理器
【发布时间】:2018-10-21 14:55:12
【问题描述】:

读者注意:这个问题只针对代号一。

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

我需要一个布局管理器:

  • 将所有组件放在 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();

相反,我需要以下屏幕截图中的内容。我想用手指水平滚动按钮栏(exampleCnt)。该应用程序应该足够智能,不会将点击按钮与水平滑动以滚动按钮混淆:

【问题讨论】:

    标签: codenameone


    【解决方案1】:

    有几种方法可以做到这一点,它们各有优缺点。让我们从这个问题开始:

    • 箭头按钮应该可以点击吗?
    • 应该将它们绘制为叠加层(当它们出现时,您会看到它们下方的按钮)还是应该作为单独的组件?

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

    内置滚动支持

    这将生成一些会呈现为覆盖且不可点击的内容,因为滚动假定为滚动条样式 UI,但也适用于这种情况。

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

    然后覆盖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);
    }
    

    【讨论】:

    • 非常感谢!每次我读到你时,我都会学到一些东西:) 关于你的回答,我有两个观察结果。在addScrolListener 内部,需要在更改可见性后添加leftright 组件的repaint(使用模拟器测试)。关于你不确定的那条线,我找到了这个解决方案:right.setVisible(scrollX &lt; scrollableCnt.getLayoutWidth() - scrollableCnt.getWidth());(用 Android 和 iPhone 皮肤测试过)。
    猜你喜欢
    • 1970-01-01
    • 2016-12-07
    • 2016-03-07
    • 2018-06-12
    • 2016-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多