libGDX如何实现任意屏幕尺寸下全屏显示背景并保持图片宽高比
实现背景等比例铺满全屏的解决方法
问题原因
你当前的代码有两个核心问题:
- 只按照屏幕高度计算背景宽度,当屏幕宽高比小于背景原始宽高比(540:720=0.75)时,比如横屏状态下屏幕宽高比通常大于1,计算出来的背景宽度会小于屏幕实际宽度,就会出现侧边白边。
- 背景的大小、位置只在类初始化时计算一次,窗口大小变化(resize触发)时没有同步更新背景参数。
实现逻辑
要保证背景等比例铺满全屏且无黑边,核心是取宽、高两个方向的最大缩放系数,确保缩放后的背景尺寸完全覆盖屏幕,多余部分居中裁剪:
- 分别计算「屏幕宽度/背景原始宽度」、「屏幕高度/背景原始高度」两个缩放值
- 取更大的缩放值作为最终缩放系数,保证缩放后的背景宽、高都不小于屏幕对应尺寸
- 将缩放后的背景居中放置,超出屏幕的部分会被自动裁剪
修改后的代码
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Image; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; import com.badlogic.gdx.utils.viewport.ScreenViewport; public class MainMenuScreen implements Screen, InputProcessor { final MyGame game; private Texture backgroundTexture; private TextureRegionDrawable backgroundDrawable; private Stage stageBackground; private Image backgroundImage; // 缓存背景原始宽高,避免重复读取 private float bgOriginalWidth; private float bgOriginalHeight; public MainMenuScreen(MyGame game) { this.game = game; // 修复重复创建Texture的问题,避免资源泄漏 backgroundTexture = new Texture(game.backgroundFileName); backgroundDrawable = new TextureRegionDrawable(new TextureRegion(backgroundTexture)); bgOriginalWidth = backgroundDrawable.getRegion().getRegionWidth(); bgOriginalHeight = backgroundDrawable.getRegion().getRegionHeight(); // ScreenViewport即可满足需求,直接对应屏幕像素坐标 stageBackground = new Stage(new ScreenViewport()); backgroundImage = new Image(backgroundDrawable); stageBackground.addActor(backgroundImage); // 初始化时调用一次resize,适配初始窗口大小 resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); } @Override public void render(float delta) { // 清屏避免画面残留,可根据需求调整清屏颜色 Gdx.gl.glClearColor(0,0,0,1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); stageBackground.getViewport().apply(); stageBackground.draw(); } @Override public void resize(int width, int height) { // 先更新viewport stageBackground.getViewport().update(width, height, true); // 计算两个方向的缩放系数 float scaleX = (float) width / bgOriginalWidth; float scaleY = (float) height / bgOriginalHeight; // 取较大的缩放系数,保证背景完全覆盖屏幕 float finalScale = Math.max(scaleX, scaleY); // 计算缩放后的背景尺寸 float scaledWidth = bgOriginalWidth * finalScale; float scaledHeight = bgOriginalHeight * finalScale; // 更新背景大小和位置,居中放置,超出屏幕部分自动裁剪 backgroundImage.setSize(scaledWidth, scaledHeight); backgroundImage.setPosition( (width - scaledWidth) / 2f, (height - scaledHeight) / 2f ); } // 补充资源销毁逻辑,避免内存泄漏 @Override public void dispose() { stageBackground.dispose(); backgroundTexture.dispose(); } // 其他Screen和InputProcessor的接口方法按你原有逻辑实现即可 }
额外注意事项
- 如果你的游戏其他UI有独立的Viewport,不要和背景的Viewport混淆,渲染时分别apply各自的Viewport即可
- 安卓端横竖屏切换时会自动触发resize方法,无需额外处理
- 记得在AndroidManifest里配置横竖屏切换的
configChanges属性,避免Activity重建导致的资源重加载
内容的提问来源于stack exchange,提问作者user2342558
相关产品推荐
相关产品推荐

