如何在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
相关产品推荐
相关产品推荐

