Search code examples
androidwebviewandroid-xml

How to fill screen with rotated webview?


I have opened a bug report at https://bugs.chromium.org/p/chromium/issues/detail?id=1144713

When I rotate the webview it does not fill the screen.

I want to rotate the webview because AndroidTV requires landscape mode... but we are gonna have the TV in a portrait setting.

i use fill_parent && match_parent but it does not work in either case.

here is a screen shot of Android Studio preview.

Also to note when i test it like this it seems like the webview matchs the screen size but doesn't adapt to the rotation... it just rotates the webview and does not resize it to the new dimensions

rotated webview not filling parent

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerInParent="true"
    android:background="@drawable/game_bg"
    android:orientation="vertical"

    tools:context="com.surveyswithgames.app.wheel.KeypadActivity">
    <FrameLayout
        android:id="@+id/frameParent"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerHorizontal="true"
        android:layout_centerInParent="true"
        android:layout_gravity="center"
        android:layout_marginLeft="2dp"
        android:layout_marginStart="2dp"
        android:layout_marginTop="2dp"
        android:background="@android:color/transparent"
        android:foregroundGravity="center"
        android:keepScreenOn="true">
        <WebView
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/keypadWebView"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:rotation="-90"
            />

    </FrameLayout>
</RelativeLayout>

UPDATE: Based on the answer https://stackoverflow.com/a/64672893/1815624 I used a custom WebView class, yet it seems like setMeasuredDimension is not functioning...


public class CustomWebView extends WebView {

    public CustomWebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public CustomWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomWebView(Context context) {
        super(context);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int desiredWidth = MeasureSpec.getSize(heightMeasureSpec);//getMeasuredHeight();
        int desiredHeight = MeasureSpec.getSize(widthMeasureSpec);//getMeasuredWidth();
        Log.e("CustomWebView", "desiredWidth: "+ desiredWidth);
        Log.e("CustomWebView", "desiredHeight: "+ desiredHeight);
        setMeasuredDimension(desiredWidth, desiredHeight);
    }
}

UPDATE 2: I had to use the code and layout suggested by the answer https://stackoverflow.com/a/64672893/1815624 and then it worked...Cheers


Solution

  • The issue that you are having is that rotation occurs post-layout. This means that the measurements occur for the landscape mode (width > height) then the view is rotated but the new width is the old height and the new height is the old width. That is what you are seeing and it is not a bug.

    One way around this is to create a custom view that swaps the width and height and pivots at the origin -90 degrees then translates the whole view down by the desired height.

    Here is the code for the custom view:

    RotatedWebView.kt

    class RotatedWebView @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
    ) : WebView(context, attrs, defStyleAttr) {
    
        override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
            val desiredWidth = MeasureSpec.getSize(heightMeasureSpec)
            val desiredHeight = MeasureSpec.getSize(widthMeasureSpec)
            translationY = desiredWidth.toFloat()
            setMeasuredDimension(desiredWidth, desiredHeight)
        }
    }
    

    RotatedWebView.java

    public class RotatedWebView extends WebView {
        public RotatedWebView(Context context) {
            super(context);
        }
    
        public RotatedWebView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public RotatedWebView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int desiredWidth = MeasureSpec.getSize(heightMeasureSpec);
            int desiredHeight = MeasureSpec.getSize(widthMeasureSpec);
            setTranslationY(desiredWidth);
            setMeasuredDimension(desiredWidth, desiredHeight);
        }
    }
    

    The layout will look something like this:

    activity_main.xml

    <RelativeLayout 
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:orientation="vertical"
        tools:context=".MainActivity">
    
        <FrameLayout
            android:id="@+id/frameParent"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_centerInParent="true"
            android:layout_centerHorizontal="true"
            android:layout_gravity="center"
            android:layout_marginStart="2dp"
            android:layout_marginLeft="2dp"
            android:layout_marginTop="2dp"
            android:background="@android:color/transparent"
            android:foregroundGravity="center"
            android:keepScreenOn="true">
    
            <com.example.webviewrotation.RotatedWebView
                android:id="@+id/keypadWebView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:rotation="-90"
                android:transformPivotX="0dp"
                android:transformPivotY="0dp" />
    
        </FrameLayout>
    </RelativeLayout>
    

    And this is the result as seen in an emulator:

    enter image description here

    It would probably be better to place all the view manipulation into the custom view instead of splitting it between the code and the XML. I assume that you will physically rotate the TV so the web page shows as you want.