【问题标题】:Android - Scaling my UI to fit all screen sizes?Android - 缩放我的 UI 以适应所有屏幕尺寸?
【发布时间】:2014-06-12 17:51:12
【问题描述】:

到目前为止,我已经尝试了许多将图像缩放到屏幕尺寸的方法,但它们似乎都不适合我。我对 java 还是很陌生,拥有适合任何屏幕尺寸的 UI 的想法对我来说似乎很陌生。我正在用 Canvas 类绘制位图。我试过创建一个 scaledBitmap 并没有看到任何区别。我想要一个像这样的简单主菜单屏幕

这一定是一个非常普遍的问题,因为所有应用都需要这样做。我真的可以使用一些帮助来理解它是如何工作的。在某些手机上看起来不错,但在其他手机上图像太大或偏离中心。

我的代码如下。如果有人可以在这里帮助我,这是一个即将到期的学校项目:P 谢谢大家!

public MainMenu(Context context) {
    super(context);

    titleBounds = new RectF();
    playBounds = new RectF();
    scoreBounds = new RectF();
    soundBounds = new RectF();
    creditBounds = new RectF();

    titlePaint = new Paint();
    playPaint = new Paint();

    play = BitmapFactory.decodeResource(getResources(), R.drawable.play);
    playGlow = BitmapFactory.decodeResource(getResources(), R.drawable.playglow);


    sound = BitmapFactory.decodeResource(getResources(), R.drawable.sound);
    soundGlow = BitmapFactory.decodeResource(getResources(), R.drawable.soundglow);


    // Get window size and save it to screenWidth and screenHeight.
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    Point size = new Point();
    display.getSize(size); 
    screenWidth = size.x;
    screenHeight = size.y;

    playy = Bitmap.createScaledBitmap(play, convertToPx(screenWidth), convertToPx(screenHeight), true);


    playSound(context, R.raw.loop);


}

public int convertToPx(int dp) {
    // Get the screen's density scale
    final float scale = getResources().getDisplayMetrics().density;
    // Convert the dps to pixels, based on density scale
    return (int) (dp * scale + 0.5f);
}


@Override protected void onDraw(Canvas canvas) {


    ViewGroup parent = (ViewGroup)getParent();

    playBounds.set(screenWidth / 2 - play.getWidth() / 2, screenHeight * 1/3 - play.getHeight() / 2, playBounds.left + play.getWidth(), playBounds.top + play.getHeight());
    soundBounds.set(playBounds.centerX() - sound.getWidth() / 2, playBounds.bottom + 10, soundBounds.left + sound.getWidth(), soundBounds.top + sound.getHeight());


    if (playClick == false) canvas.drawBitmap(playy, null, playBounds, null);
    else canvas.drawBitmap(playGlow, null, playBounds, null);   

    if (soundClick == false) canvas.drawBitmap(sound, null, soundBounds, null);
    else canvas.drawBitmap(soundGlow, null, soundBounds, null); 

【问题讨论】:

    标签: java android canvas bitmap scaling


    【解决方案1】:

    试试这个,在图像上使用 scaleType="fitXY" ,它会跨越到视图的边界。

    【讨论】:

    • 我没有使用 XML,我该怎么做
    【解决方案2】:

    您从 wm.getDefaultDisplay().getSize() 获得的屏幕尺寸以像素为单位,而不是以 dp 为单位。因此,您可以直接使用它们而无需转换它们。

    类似...

    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    Point size = new Point();
    display.getSize(size); 
    screenWidth = size.x;
    screenHeight = size.y;
    playy = Bitmap.createScaledBitmap(play, screenWidth, screenHeight, true);
    

    如果您尝试创建游戏,我建议您不要使用 Canvas。相反,您应该使用更快的 GLSurfaceView。更好的是,使用 Corona SDK 或 Unity 或 Cocos2dx 等跨平台游戏引擎。这样开发会容易得多,性能也会很棒。

    编辑:您最终想要的是在不改变其纵横比的情况下对所有资产进行一致的缩放。您需要编写一个辅助方法来计算这个比率,然后将该比率乘以您的所有维度。

    // The code below assume some variables are already populated by the above code
    // I HAVE NOT TESTED THIS CODE. I'M JUST WRITING IT HERE OFF THE TOP OF MY HEAD.
    
    private static float dimRatio;
    private static float xOffset;
    private static float yOffset;
    private static Matrix transformMatrix;
    
    private void initializeBitmapTransformMatrix {
        float ratio = (float)screenWidth / (float)gameWidth; //gameWidth is the width of your background image asset - so it's base size of the game
        if(gameHeight * ratio > screenHeight ){
            // the ratio we calculated above is for the width based scaling.
            // seems like if we use this ratio, the height will go off the boundary.
            // so use the height based ratio instead
            dimRatio = (float)screenHeight / (float)gameHeight;   
            xOffset = (screenWidth - (gameWidth * dimRatio)) / 2;
        } else {
            dimRatio = ratio;
            yOffset = (screenHeight - (gameHeight * dimRatio)) / 2;
        }
    
        // Now you have the ratio and offset values make a transform matrix
    
        transformMatrix = new Matrix();
        transformMatrix.setScale(dimRatio, dimRatio);
        transformMatrix.setTranslate(xOffset, yOffset);
    }
    

    说明:我们有dimRatio 来计算您所有位图资源的最终像素值。当您定位它们时,您必须相应地添加xOffsetyOffset 以正确偏移屏幕的空白区域,这是由于设备屏幕的纵横比与游戏预期的纵横比不同的事实造成的。矩阵结合了所有这些,因此我们不必在每次绘制时都使用这些变量。我们可以只使用矩阵。

    绘制示例:

    canvas.drawBitmap(play, transformMatrix, null); // for background
    // for a button
    Matrix buttonMatrix = new Matrix(transformMatrix);
    buttonMatrix.postTranslate(20f*dimRatio, 100f*dimRatio);
    canvas.drawBitmap(button, buttonMatrix, null);
    

    我只是写了这个,没有真正测试它。这只是为了想法。希望你能明白。

    EDIT2:实现的 xOffset 和 yOffset 颠倒了。修好了。

    【讨论】:

    • 为了游戏的简单性,我使用的画布效果很好。我已经尝试过你告诉我的,但它不起作用。你介意团队查看我吗?
    • 您能更具体地谈谈这个问题吗?我会首先尝试使用上面的代码(只是缩放到屏幕大小)让背景占据整个屏幕。然后,您可以编写一个方法来计算位图大小与设备上所需大小的比率。然后,您可以将此比率乘以您将在整个过程中使用的所有维度。您还需要注意的另一件事是,您始终必须对宽度和高度应用相同的比率以保持资产的纵横比。你不希望你的圆是一个椭圆。
    • 哇。这听起来很难 :'( 就像我真的不明白这是如何工作的,我可以花点时间了解一下团队的观点吗?我不明白这些比率
    • 这并不难。我会尽量写在我的答案中。
    • 好的,可以吗?我已经尝试了很长时间了
    猜你喜欢
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多