You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法为SwipeableContainer设置宽度约束及容器重复添加报错求助

问题解决:SwipeableContainer宽度约束与样式优化

错误根源分析

原代码抛出Component is already contained in Container异常,核心原因是循环内重复将同一个lsd、rsd容器实例添加到contactsForm——Codename One中组件不能同时存在于多个容器,也不能在同一容器中重复添加。同时原逻辑试图在循环中为每个联系人单独构建三列布局,不符合TableLayout的使用逻辑,导致仅能显示首个联系人。

彻底解决宽度约束的方案

核心调整点

  1. 仅在循环外初始化一次左右空白容器与中间列表容器,统一添加到contactsForm的TableLayout中,确保布局结构唯一。
  2. 循环内仅将单个联系人的SwipeableContainer添加到中间列表容器,避免重复组件添加。
  3. 修正删除逻辑:操作单个SwipeableContainer而非整个列表容器,保证删除动画正常执行。

修正后的完整代码

private void showContactsList(boolean forward) {
    try {
        Contact c = new Contact();
        List<PropertyBusinessObject> contacts = sm.select(c, c.name, true, 1000, 0);
        
        // 初始化布局容器:左右空白+中间可滚动列表容器
        Container leftSpacer = new Container();
        Container rosterList = new Container(BoxLayout.y());
        rosterList.setScrollableY(true); // 开启垂直滚动,适配大量球员数据
        Container rightSpacer = new Container();
        
        // 为contactsForm设置三列布局:左25%空白,中50%列表,右25%空白,实现居中效果
        contactsForm.add(tL.createConstraint().heightPercentage(100).widthPercentage(25), leftSpacer);
        contactsForm.add(tL.createConstraint().heightPercentage(100).widthPercentage(50), rosterList);
        contactsForm.add(tL.createConstraint().heightPercentage(100).widthPercentage(25), rightSpacer);
        
        for(PropertyBusinessObject currentContact : contacts) {
            String name = ((Contact)currentContact).name.get();
            if(name == null || name.isEmpty()) {
                name = "[null]";
            }
            
            // 创建球员姓名按钮
            MultiButton contactBtn = new MultiButton(name);
            contactBtn.setUIID("RosterMultiButton"); // 自定义UIID用于样式配置
            contactBtn.addActionListener(e -> editContact((Contact)currentContact));
            
            // 创建删除按钮
            Button deleteBtn = new Button("");
            FontImage.setMaterialIcon(deleteBtn, FontImage.MATERIAL_DELETE, 6);
            
            // 创建可滑动容器
            SwipeableContainer swipeItem = new SwipeableContainer(deleteBtn, contactBtn);
            
            // 删除逻辑修正:操作当前滑动项而非整个列表
            deleteBtn.addActionListener(e -> {
                try {
                    sm.delete(currentContact);
                    // 执行删除动画
                    swipeItem.setX(contactsForm.getWidth());
                    contactsForm.getContentPane().animateUnlayoutAndWait(200, 255);
                    rosterList.remove(swipeItem);
                    contactsForm.getContentPane().animateLayout(180);
                } catch(IOException err) {
                    Log.e(err);
                    ToastBar.showErrorMessage("删除失败: "+ err);
                }
            });
            
            // 将单个滑动项添加到列表容器
            rosterList.add(swipeItem);
        }
        
        if(forward) {
            contactsForm.show();
        } else {
            contactsForm.showBack();
        }
    } catch(Exception err) {
        Log.e(err);
    }
}

界面样式完善建议

1. MultiButton字体样式调整

可以通过代码直接设置,或通过主题编辑器配置UIID:

  • 代码方式:
// 自定义字体大小与样式
Font customFont = Font.createTrueTypeFont("native:MainLight", "native:MainLight").derive(20f, Font.STYLE_PLAIN);
contactBtn.getUnselectedStyle().setFont(customFont);
contactBtn.getSelectedStyle().setFont(customFont);
// 设置文本居中对齐
contactBtn.getAllStyles().setAlignment(Component.CENTER);
  • 主题UIID方式:在theme.res中为RosterMultiButton设置:
    • font:选择合适的字体与大小
    • alignment:居中对齐
    • padding:调整上下左右内边距,优化项间距

2. 列表项视觉优化

  • 为SwipeableContainer设置UIID,添加背景色或边框区分列表项:
swipeItem.setUIID("RosterSwipeItem");

在主题中为RosterSwipeItem配置bgColor(背景色)、border(边框)属性,提升视觉层次感。

3. 平板适配细节

  • 中间列表容器的宽度百分比可根据平板尺寸调整(如40%-60%区间),保证视觉舒适。
  • 为删除按钮添加红色背景,增强滑动后的操作提示:
deleteBtn.getAllStyles().setBgColor(0xffcc0000);
deleteBtn.getAllStyles().setBgTransparency(255);

内容的提问来源于stack exchange,提问作者curtjacobs1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 00:24:51