SurfaceView叠加ImageView旋转后宽高设置及竖屏锁定适配问题
Hey there! Let’s tackle your two Android issues step by step—they’re both rooted in how the system handles view transformations and screen metrics when orientation is locked.
1. Setting Correct Width/Height for Rotated ImageView Over SurfaceView
When you rotate an ImageView, its visible bounds shift, but the default getWidth()/getHeight() still return the original unrotated values. To fix this, you need to calculate the bounding box size of the rotated image and update the ImageView’s layout params dynamically.
How to Calculate Rotated Dimensions
You can use either trigonometry or Android’s Matrix class to compute the new width and height after rotation:
- Trigonometry Approach: For a rotation angle
theta(converted to radians), the rotated dimensions are:float radians = (float) Math.toRadians(rotationAngle); float cos = Math.abs((float) Math.cos(radians)); float sin = Math.abs((float) Math.sin(radians)); int originalWidth = imageView.getDrawable().getIntrinsicWidth(); int originalHeight = imageView.getDrawable().getIntrinsicHeight(); int newWidth = (int) (originalWidth * cos + originalHeight * sin); int newHeight = (int) (originalWidth * sin + originalHeight * cos); - Matrix Approach: Use a
Matrixto map the original bounds to rotated bounds:Matrix matrix = new Matrix(); matrix.setRotate(rotationAngle); RectF originalRect = new RectF(0, 0, originalWidth, originalHeight); RectF rotatedRect = new RectF(); matrix.mapRect(rotatedRect, originalRect); int newWidth = (int) rotatedRect.width(); int newHeight = (int) rotatedRect.height();
Update ImageView Layout Params
Once you have the new dimensions, update the ImageView’s LayoutParams (make sure your parent layout is FrameLayout or RelativeLayout for flexible overlaying):
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) imageView.getLayoutParams(); params.width = newWidth; params.height = newHeight; imageView.setLayoutParams(params);
Pro Tip: Always set the ImageView’s pivotX and pivotY to its center before rotating to avoid unexpected positioning:
imageView.setPivotX(imageView.getWidth() / 2f); imageView.setPivotY(imageView.getHeight() / 2f);
2. Fixing Wrong Width/Height When Rotating ImageView in Locked Portrait Mode
When you lock your Activity to portrait, the system still reports portrait-oriented metrics even if the device is held horizontally. To get the actual physical screen dimensions (regardless of locked orientation), use getRealMetrics() instead of standard display metrics.
Step 1: Get Real Screen Dimensions
Display display = getWindowManager().getDefaultDisplay(); DisplayMetrics realMetrics = new DisplayMetrics(); display.getRealMetrics(realMetrics); // Adjust dimensions based on actual device rotation int rotation = display.getRotation(); int screenWidth, screenHeight; if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) { // Device is in landscape (even if Activity is locked to portrait) screenWidth = realMetrics.heightPixels; screenHeight = realMetrics.widthPixels; } else { // Device is in portrait screenWidth = realMetrics.widthPixels; screenHeight = realMetrics.heightPixels; }
Step 2: Use Real Dimensions for ImageView Calculations
When computing the rotated ImageView’s size or positioning, use screenWidth and screenHeight from above instead of the Activity’s locked metrics. For example, to scale the rotated image to fit the screen:
// Calculate scale factor to fit rotated image within screen bounds float scaleX = (float) screenWidth / newWidth; float scaleY = (float) screenHeight / newHeight; float scale = Math.min(scaleX, scaleY); // Apply scale to the ImageView imageView.setScaleX(scale); imageView.setScaleY(scale);
Step 3: Listen for Orientation Changes (Optional)
Even with the Activity locked, you can use OrientationEventListener to detect device rotation and update your ImageView dynamically:
OrientationEventListener orientationListener = new OrientationEventListener(this) { @Override public void onOrientationChanged(int orientation) { // Re-calculate screen dimensions and update ImageView here updateRotatedImageViewDimensions(); } }; orientationListener.enable();
Final Notes
- Set your ImageView’s
scaleType="matrix"if applying custom transformations (rotation + scaling) to avoid automatic scaling conflicts. - Use
FrameLayoutas the parent container for SurfaceView and ImageView to easily overlay them without layout constraints interfering.
内容的提问来源于stack exchange,提问作者Machhi Sudke

