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

如何在Codenameone中实现类似StepViewPager的步骤进度条?

Codename One 步骤进度条实现方案(类似StepViewPager效果)

方案一:自定义组件实现(推荐)

直接继承Container自定义可复用的步骤进度条组件,能精准控制每个步骤的状态、样式与交互逻辑。

核心代码实现

import com.codename1.ui.*;
import com.codename1.ui.geom.Dimension;
import com.codename1.ui.plaf.Style;

public class StepProgressBar extends Container {
    private int totalSteps;
    private int currentStep = 0;
    private final int stepSize = 30; // 步骤点尺寸
    private final int lineHeight = 2; // 连线高度

    public StepProgressBar(int totalSteps) {
        this.totalSteps = totalSteps;
        setLayout(new BoxLayout(BoxLayout.X_AXIS));
        setPreferredSize(new Dimension(Display.getInstance().getDisplayWidth(), 60));
        revalidate();
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        int width = getWidth();
        int height = getHeight();
        int stepSpacing = (width - totalSteps * stepSize) / (totalSteps - 1);

        // 绘制连线与步骤点
        for (int i = 0; i < totalSteps; i++) {
            int x = i * (stepSize + stepSpacing);
            int y = height / 2;

            // 绘制连线(跳过最后一个步骤)
            if (i < totalSteps - 1) {
                int lineXEnd = x + stepSize + stepSpacing;
                g.setColor(i < currentStep ? 0x2196F3 : 0xE0E0E0); // 已完成用蓝色,未完成用灰色
                g.fillRect(x + stepSize / 2, y - lineHeight / 2, lineXEnd - x - stepSize, lineHeight);
            }

            // 绘制步骤点
            Style stepStyle = getUIManager().getComponentStyle("Label");
            if (i < currentStep) {
                // 已完成步骤:填充色+对勾图标
                g.setColor(0x2196F3);
                g.fillArc(x, y - stepSize / 2, stepSize, stepSize, 0, 360);
                g.setColor(0xFFFFFF);
                g.drawString("✓", x + stepSize / 2 - 5, y - stepSize / 2 + 5, stepStyle);
            } else if (i == currentStep) {
                // 当前步骤:加粗边框+填充色
                g.setColor(0x2196F3);
                g.drawArc(x, y - stepSize / 2, stepSize, stepSize, 0, 360);
                g.fillArc(x + 2, y - stepSize / 2 + 2, stepSize - 4, stepSize - 4, 0, 360);
                g.setColor(0xFFFFFF);
                g.drawString(String.valueOf(i + 1), x + stepSize / 2 - 5, y - stepSize / 2 + 5, stepStyle);
            } else {
                // 未完成步骤:灰色边框+数字
                g.setColor(0xE0E0E0);
                g.drawArc(x, y - stepSize / 2, stepSize, stepSize, 0, 360);
                g.setColor(0x757575);
                g.drawString(String.valueOf(i + 1), x + stepSize / 2 - 5, y - stepSize / 2 + 5, stepStyle);
            }
        }
    }

    // 设置当前步骤(从0开始计数)
    public void setCurrentStep(int step) {
        if (step >= 0 && step < totalSteps) {
            currentStep = step;
            repaint();
        }
    }

    public int getCurrentStep() {
        return currentStep;
    }
}

使用示例

Form form = new Form("步骤进度条示例", new BorderLayout());
StepProgressBar progressBar = new StepProgressBar(4);
form.add(BorderLayout.NORTH, progressBar);

// 添加步骤切换按钮
Container buttonContainer = new Container(new BoxLayout(BoxLayout.X_AXIS));
Button prevBtn = new Button("上一步");
Button nextBtn = new Button("下一步");

prevBtn.addActionListener(e -> {
    if (progressBar.getCurrentStep() > 0) {
        progressBar.setCurrentStep(progressBar.getCurrentStep() - 1);
    }
});

nextBtn.addActionListener(e -> {
    if (progressBar.getCurrentStep() < 3) {
        progressBar.setCurrentStep(progressBar.getCurrentStep() + 1);
    }
});

buttonContainer.addAll(prevBtn, nextBtn);
form.add(BorderLayout.SOUTH, buttonContainer);

form.show();

方案二:现有组件组合实现

如果不想自定义组件,可通过Label(步骤点)与Separator(连线)组合,修改组件样式实现状态切换。

核心代码示例

Form form = new Form("组合式步骤进度条", new BorderLayout());
Container progressContainer = new Container(new BoxLayout(BoxLayout.X_AXIS));
progressContainer.setUIID("ProgressContainer");

int totalSteps = 4;
Label[] steps = new Label[totalSteps];
Separator[] lines = new Separator[totalSteps - 1];

// 初始化步骤与连线
for (int i = 0; i < totalSteps; i++) {
    steps[i] = new Label(String.valueOf(i + 1));
    steps[i].setPreferredSize(new Dimension(30, 30));
    steps[i].setUIID(i == 0 ? "CurrentStep" : "InactiveStep");
    progressContainer.add(steps[i]);

    if (i < totalSteps - 1) {
        lines[i] = new Separator();
        lines[i].setUIID("InactiveLine");
        lines[i].setPreferredSize(new Dimension(50, 2));
        progressContainer.add(lines[i]);
    }
}

form.add(BorderLayout.NORTH, progressContainer);

// 下一步按钮逻辑
Button nextBtn = new Button("下一步");
nextBtn.addActionListener(e -> {
    int current = -1;
    for (int i = 0; i < steps.length; i++) {
        if (steps[i].getUIID().equals("CurrentStep")) {
            current = i;
            break;
        }
    }
    if (current < steps.length - 1) {
        steps[current].setUIID("CompletedStep");
        lines[current].setUIID("CompletedLine");
        steps[current + 1].setUIID("CurrentStep");
        progressContainer.revalidate();
    }
});

form.add(BorderLayout.SOUTH, nextBtn);

// 自定义样式配置
Style completedStep = UIManager.getInstance().getComponentStyle("Label").copy();
completedStep.setFgColor(0xFFFFFF);
completedStep.setBgColor(0x2196F3);
completedStep.setBgTransparency(255);
completedStep.setBorder(Border.createCircleBorder());
UIManager.getInstance().addStyle("CompletedStep", completedStep);

Style currentStep = completedStep.copy();
currentStep.setBgTransparency(0);
currentStep.setBorder(Border.createCircleBorder(2, 0x2196F3));
UIManager.getInstance().addStyle("CurrentStep", currentStep);

Style inactiveStep = completedStep.copy();
inactiveStep.setBgColor(0xE0E0E0);
inactiveStep.setFgColor(0x757575);
UIManager.getInstance().addStyle("InactiveStep", inactiveStep);

Style completedLine = UIManager.getInstance().getComponentStyle("Separator").copy();
completedLine.setBgColor(0x2196F3);
UIManager.getInstance().addStyle("CompletedLine", completedLine);

Style inactiveLine = completedLine.copy();
inactiveLine.setBgColor(0xE0E0E0);
UIManager.getInstance().addStyle("InactiveLine", inactiveLine);

form.show();

关键注意事项

  • 自定义组件方案灵活性更高,适合复杂交互与样式定制;组合方案实现更快,适合简单场景。
  • 可根据需求替换步骤点的图标(比如用FontAwesome图标替代文字)、调整颜色与尺寸。
  • 适配不同屏幕时,建议用动态计算的间距替代固定值,避免布局错乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 07:11:05