diff --git a/res/layout/main.xml b/res/layout/main.xml index 219c1af..9b45153 100644 --- a/res/layout/main.xml +++ b/res/layout/main.xml @@ -1,5 +1,5 @@ - @@ -71,4 +71,4 @@ - + diff --git a/src/com/froop/app/kegs/BitmapSize.java b/src/com/froop/app/kegs/BitmapSize.java index 3a7637d..7132b3a 100644 --- a/src/com/froop/app/kegs/BitmapSize.java +++ b/src/com/froop/app/kegs/BitmapSize.java @@ -24,14 +24,12 @@ class BitmapSize { } public boolean showActionBar() { - if (mScaleFactorY != 1.0f && mScaleFactorX != mScaleFactorY) { - return false; - } else if (mHeight < getViewHeight()) { - // However, beware that disabling the action bar may increase - // the space enough to think that we should reenable it. - return false; - } else { + if (mWidth < mHeight) { + // portrait mode return true; + } else { + // TODO FIXME: also if the screen is BIG, return true. + return false; } } @@ -40,25 +38,17 @@ class BitmapSize { } public int getViewHeight() { - if (!doCropBorder()) { - return (int)(Const.A2Height * mScaleFactorY); - } else { - return (int)((Const.A2Height - 32 - 30) * mScaleFactorY); - } - } - - private boolean doCropBorder() { - return mCropped; - } - - public int getCropPixelCount() { if (doCropBorder()) { - return 30; // pixels dropped from the *bottom* + return (int)(400 * mScaleFactorY); } else { - return 0; + return (int)(Const.A2Height * mScaleFactorY); } } + public boolean doCropBorder() { + return mCropped; + } + public boolean isScaled() { return (mScaleFactorX != 1.0f || mScaleFactorY != 1.0f); } @@ -87,32 +77,35 @@ class BitmapSize { } } -// If we can fit at least 90% of a scaled screen into the display area, do it. -// If we hit less than 100% height, turn off system action bar and title. -// If ((400 + 32) * scale) > height, then crop border. private void calculateScale(int width, int height) { - float scaleX = 1.0f; - float scaleY = 1.0f; + float scaleX; + float scaleY; boolean crop = false; // Force integer scaling on X axis. scaleX = (float)Math.round((width * 0.9) / 640); scaleX = Math.max(1, scaleX); - scaleY = Math.min(scaleX, height / 400.0f); + scaleY = scaleX; - // NOTE: scaleY should really never be less than '1', - // although theoretically 0.5-1 would look OK, it causes poor performance + if (height < Const.A2Height * scaleY) { + // Scale it so that only the 400 pixels that matter take up the view. + scaleY = Math.min(scaleX, height / 400.0f); + + // User should only use the 400 pixels that matter. + crop = true; + } // If Y would be compressed in a weird way, reduce the scale and use 1:1. if ((scaleX - scaleY) > 0.5) { scaleX = Math.max(1, scaleX - 1); scaleY = scaleX; - } - // If the 32 line border and the 400 pixel display do not fit, try - // cropping out the 32 line border. - if (height < 432 * scaleY) { - crop = true; + // See whether we should crop it at that height. + if (height < Const.A2Height * scaleY) { + crop = true; + } else { + crop = false; + } } mCropped = crop; @@ -120,13 +113,4 @@ class BitmapSize { mScaleFactorY = scaleY; Log.w("kegs", "using scale " + scaleX + ":" + scaleY + " crop=" + crop + " from screen " + width + "x" + height); } - -// call us when you update your screen size/configuration - -// helper to calculate view area for KegsView:onMeasure - -// helper to create size struct - -// helper struct for scale factors (&isScaled), crop info, source/dest rects -// KegsView can get this and pass it into the thread. } diff --git a/src/com/froop/app/kegs/KegsMain.java b/src/com/froop/app/kegs/KegsMain.java index a2ea86c..8fdcd71 100644 --- a/src/com/froop/app/kegs/KegsMain.java +++ b/src/com/froop/app/kegs/KegsMain.java @@ -43,7 +43,8 @@ public class KegsMain extends Activity implements KegsKeyboard.StickyReset, Asse private boolean mAssetsReady = false; private boolean mModeMouse = true; - private int mLastActionBar = 0; // window height at last ActionBar change. + + private long mScreenSizeTime = 0; private View.OnClickListener mButtonClick = new View.OnClickListener() { public void onClick(View v) { @@ -241,63 +242,37 @@ public class KegsMain extends Activity implements KegsKeyboard.StickyReset, Asse } } - private void setScreenSize(boolean quick) { - int width; - int height; - - if (quick) { - width = getResources().getDisplayMetrics().widthPixels; - height = getResources().getDisplayMetrics().heightPixels; - if (android.os.Build.VERSION.SDK_INT >= 11) { - // NOTE: 48 is a guess at the System Bar obstruction. - // These are 'visible insets' into the display from the window manager. - height -= 48; - } - } else { - Rect displaySize = new Rect(); - // We use the mKegsView object here, but we could ask any view. - mKegsView.getWindowVisibleDisplayFrame(displaySize); - width = displaySize.width(); - height = displaySize.height(); + private void updateScreenSize(int width, int height, long sent) { + if (mScreenSizeTime != sent) { + // There's a newer event coming soon, wait for it. + return; } final BitmapSize bitmapSize = new BitmapSize(width, height); - mKegsView.updateScreenSize(bitmapSize); + updateActionBar(bitmapSize.showActionBar()); - // Only change action bar if the window height is significantly - // different from the last time we changed the action bar. - if (height < (mLastActionBar * 0.85) || height > (mLastActionBar * 1.15)) { - mLastActionBar = height; - updateActionBar(bitmapSize.showActionBar()); - } + mKegsView.updateScreenSize(bitmapSize); // Force another redraw of the bitmap into the canvas. Bug workaround. getThread().updateScreen(); } - private void workaroundScreenSize() { - // First use displayMetrics. - setScreenSize(true); - - // Then update with getWindowVisibleDisplayFrame in 250ms. - // - // We want to use getWindowVisibleDisplayFrame, but it's not - // always immediately available. Bug workaround. - // - // BUG: Sometimes if the device rotates as the soft keyboard - // is becoming visible for the first time, the reported - // window size is reduced and we don't scale to full screen. - // The user can fix this by rotating the screen again. - // We may want to trap IME visible/hidden events and update the size. - mKegsView.postDelayed(new Runnable() { - public void run() { setScreenSize(false); } - }, 250); - } - - @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - workaroundScreenSize(); + + // Fire off a guess at a new size during this request, + // it makes the animation transition look better. + int width = getResources().getDisplayMetrics().widthPixels; + int height = getResources().getDisplayMetrics().heightPixels; + if (android.os.Build.VERSION.SDK_INT >= 11) { + // NOTE: 48 is a guess at the System Bar obstruction. + // These are 'visible insets' into the display from the window manager. + height -= 48; + } + final BitmapSize bitmapSize = new BitmapSize(width, height); + updateActionBar(bitmapSize.showActionBar()); + mKegsView.updateScreenSize(bitmapSize); + getThread().updateScreen(); } @Override @@ -380,12 +355,10 @@ public class KegsMain extends Activity implements KegsKeyboard.StickyReset, Asse mKegsView.getBitmap()); mKegsThread.registerUpdateScreenInterface(mKegsView); - workaroundScreenSize(); - mKegsTouch = new KegsTouch(this, getThread().getEventQueue()); mJoystick = new TouchJoystick(getThread().getEventQueue()); - final View mainView = findViewById(R.id.mainview); + final SpecialRelativeLayout mainView = (SpecialRelativeLayout)findViewById(R.id.mainview); mainView.setClickable(true); mainView.setLongClickable(true); mainView.setOnTouchListener(new OnTouchListener() { @@ -398,6 +371,15 @@ public class KegsMain extends Activity implements KegsKeyboard.StickyReset, Asse } } }); + mainView.setNotifySizeChanged( + new SpecialRelativeLayout.NotifySizeChanged() { + public void onSizeChanged(final int w, final int h, int oldw, int oldh) { + final long now = System.currentTimeMillis(); + mScreenSizeTime = now; + mKegsView.postDelayed(new Runnable() { public void run() { updateScreenSize(w, h, now); } }, 250); + } + } + ); mKegsKeyboard = new KegsKeyboard(getThread().getEventQueue()); mKegsKeyboard.setOnStickyReset(this); diff --git a/src/com/froop/app/kegs/KegsRenderer.java b/src/com/froop/app/kegs/KegsRenderer.java index fda7020..ffebb5f 100644 --- a/src/com/froop/app/kegs/KegsRenderer.java +++ b/src/com/froop/app/kegs/KegsRenderer.java @@ -51,7 +51,7 @@ class KegsRenderer implements GLSurfaceView.Renderer { private int mHeight = 0; private float mScaleX = 1.0f; private float mScaleY = 1.0f; - private float mCropBorder = 0.0f; + private boolean mCropBorder = false; private boolean mScaled = false; private boolean mSizeChange = false; @@ -86,11 +86,12 @@ class KegsRenderer implements GLSurfaceView.Renderer { private void setupOrtho(GL10 gl) { gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); - // 50.0f is 512-(400+32+30) (the distance from the bottom of the texture to our actual bitmap) - float cropBorder = 50.0f; - cropBorder *= mScaleY; - cropBorder += mCropBorder * mScaleY; // likely zero - gl.glOrthof(0.0f, (float)mWidth, cropBorder, mHeight + cropBorder, 0.0f, 1.0f); + // 50.0f is 512-(30+400+32) (the distance from the bottom of the texture to our actual bitmap) + if (mCropBorder) { + gl.glOrthof(0.0f, (float)mWidth, (50.0f+30.0f) * mScaleY, (50.0f+400.0f+30.0f) * mScaleY, 0.0f, 1.0f); + } else { + gl.glOrthof(0.0f, (float)mWidth, 50.0f * mScaleY, (50.0f+30.0f+400.0f+32.0f) * mScaleY, 0.0f, 1.0f); + } gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); } @@ -210,7 +211,7 @@ class KegsRenderer implements GLSurfaceView.Renderer { mHeight = bitmapSize.getViewHeight(); mScaleX = bitmapSize.getScaleX(); mScaleY = bitmapSize.getScaleY(); - mCropBorder = (float)bitmapSize.getCropPixelCount(); + mCropBorder = bitmapSize.doCropBorder(); mScaled = bitmapSize.isScaled(); mSizeChange = true; Log.e("kegs", "screen size " + mWidth + "x" + mHeight + " " + mScaleX + ":" + mScaleY + " crop=" + mCropBorder); diff --git a/src/com/froop/app/kegs/SpecialRelativeLayout.java b/src/com/froop/app/kegs/SpecialRelativeLayout.java new file mode 100644 index 0000000..541410f --- /dev/null +++ b/src/com/froop/app/kegs/SpecialRelativeLayout.java @@ -0,0 +1,39 @@ +package com.froop.app.kegs; + +import android.widget.RelativeLayout; +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; + +class SpecialRelativeLayout extends RelativeLayout { + public SpecialRelativeLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + interface NotifySizeChanged { + void onSizeChanged(int w, int h, int oldw, int oldh); + } + + private NotifySizeChanged mNotify; + private int mWidth = 0; + private int mHeight = 0; + + public void setNotifySizeChanged(NotifySizeChanged notify) { + mNotify = notify; + + // In case the call had come in earlier. + if (notify != null && mWidth != 0 && mHeight != 0) { + mNotify.onSizeChanged(mWidth, mHeight, 0, 0); + } + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + mWidth = w; + mHeight = h; + if (mNotify != null) { + mNotify.onSizeChanged(w, h, oldw, oldh); + } + } +}