
本文介绍一种绕过 progressbar 内置动画、通过手动控制 setvalue 实现精准暂停/恢复的方案,结合 applicationlistener 的 pause()/resume() 生命周期方法,确保进度条状态与应用生命周期同步。
在 LibGDX 中,ProgressBar 默认启用的 setAnimateDuration() 会启动内部动画计时器,但该动画无法直接暂停或中断——它独立于主渲染循环运行,且无公开 API 控制其播放状态。因此,若需实现「点击暂停按钮即刻冻结进度」的效果,推荐采用主动控制值更新 + 生命周期联动的方案,而非依赖内置动画。
✅ 推荐实现思路:手动驱动 + 状态开关
核心思想是:
- 禁用动画:创建 ProgressBar 时不调用 setAnimateDuration()(或设为 0);
- 手动更新值:在 render() 中按需递增 setValue(),基于 Gdx.graphics.getDeltaTime() 实现平滑、帧率无关的进度增长;
- 暂停即停止更新:利用 ApplicationListener.pause() 和 resume() 统一控制全局更新开关(如布尔标志 active);
- 保持 UI 响应性:即使暂停,stage.act() 和 stage.draw() 仍正常执行,确保按钮等交互组件持续可用。
以下是关键代码示例(已适配现代 LibGDX 最佳实践):
public class ProgressBarController implements ApplicationListener {
private boolean isActive = true;
private SpriteBatch batch;
private Stage stage;
private ProgressBar progressBar;
@Override
public void create() {
batch = new SpriteBatch();
stage = new Stage(new FitViewport(800, 600));
// 构建自定义样式(省略重复纹理逻辑,保留核心结构)
ProgressBarStyle style = new ProgressBarStyle();
style.background = generateDrawable(Color.CYAN, 100, 50);
style.knob = generateDrawable(Color.RED, 10, 50); // 小滑块(窄条)
style.knobBefore = generateDrawable(Color.RED, 100, 50); // 已填充部分
// 关键:禁用动画,范围设为 0→25(对应 25 秒),步进精度 0.01
progressBar = new ProgressBar(0f, 25f, 0.01f, false, style);
progressBar.setBounds(100, 400, 600, 30);
progressBar.setValue(0f);
stage.addActor(progressBar);
}
private Drawable generateDrawable(Color color, int width, int height) {
Pixmap pixmap = new Pixmap(width, height, Pixmap.Format.RGBA8888);
pixmap.setColor(color);
pixmap.fill();
TextureRegionDrawable drawable = new TextureRegionDrawable(new TextureRegion(new Texture(pixmap)));
pixmap.dispose();
return drawable;
}
@Override
public void render() {
// ✅ 仅当激活时才更新进度值
if (isActive && progressBar.getValue() < progressBar.getMaxValue()) {
float delta = Gdx.graphics.getDeltaTime();
float newValue = Math.min(progressBar.getValue() + delta, progressBar.getMaxValue());
progressBar.setValue(newValue);
if (newValue >= progressBar.getMaxValue()) {
System.out.println("✅ 进度已完成!");
// 可在此触发完成回调、切换场景等
}
}
// ✅ 持续驱动 UI 逻辑(含按钮监听器)
stage.act();
Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
stage.draw();
batch.end();
}
// ? 系统级暂停:自动调用(如切到后台、锁屏)
@Override
public void pause() {
System.out.println("⏸️ 应用已暂停 → 进度条冻结");
isActive = false;
}
// ? 系统级恢复:自动调用(如返回前台)
@Override
public void resume() {
System.out.println("▶️ 应用已恢复 → 进度条继续");
isActive = true;
}
// ? 手动暂停(例如绑定到 UI 按钮)
public void togglePause() {
isActive = !isActive;
System.out.println(isActive ? "▶️ 手动恢复" : "⏸️ 手动暂停");
}
@Override
public void dispose() {
batch.dispose();
stage.dispose();
}
}⚠️ 注意事项与进阶建议
- 避免内存泄漏:每次 new Texture(...) 后务必调用 pixmap.dispose(),示例中已严格遵循;
- 响应式暂停按钮:可将 togglePause() 绑定至 TextButton 的 addListener(new ClickListener() { ... }),实现用户主动控制;
- 动画保留方案(备选):若必须使用 setAnimateDuration(),可通过条件调用 stage.act() 控制时间推进(如 if (isActive) stage.act();),但此方式对动画起始/暂停点控制较粗糙,不推荐用于精确场景;
- 跨平台一致性:pause()/resume() 在 Android/iOS/Desktop 均有效,但桌面端需确保 Lwjgl3ApplicationConfiguration.setPauseOnFocusLost(true) 已启用(默认开启)。
通过该方案,你不仅能实现毫秒级精度的暂停/恢复,还能无缝集成事件系统、多任务协同及复杂状态管理,是 LibGDX 游戏与工具开发中的稳健实践。










