5

I recently struggled with an apparently simple Android layout: I wanted a WebView above a Button. It worked fine with the following parameters:

WebView:
  Height: wrap-content
  Weight: unset (by the way, what is the default?)

Button:
  Height: wrap-content
  Weight: unset

However if the web page became too big it spilled out over the button. I tried various combinations of weights and heights, and all except one either completely hide the button, or partially cover it. This is the one that works (copied from http://code.google.com/p/apps-for-android/source/browse/trunk/Samples/WebViewDemo/res/layout/main.xml):

WebView:
  Height: 0
  Weight: 1

Button:
  Height: wrap-content
  Weight: unset

If you change any of those, e.g. give button a weight or change the WebView height to wrap-content then it doesn't work. My question is: Why? Can someone please explain what on Earth the android layout system is thinking?

Timmmm
  • 88,195
  • 71
  • 364
  • 509

5 Answers5

3

Something like the following should give you what you want. The key is the layout_height="fill_parent" and layout_weight="1" for the WebView.

<LinearLayout android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
        <WebView android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1" />

        <Button android:layout_width="fill_parent"
                android:layout_height="wrap_content" />
</LinearLayout>  


Edit: Whoops, I misunderstood your question. It's the layout_weight that makes it not spill over the button (or textview in your example). I'm not sure why it happens, but if there's one "fill_parent" item in your LinearLayout, in addition to one or more "wrap_content" items, you need to specify a layout_weight for the "fill_parent" item, or it'll take over the space for the rest of the widgets.

synic
  • 26,359
  • 20
  • 111
  • 149
  • 3
    `fill_parent` will take up all remaining space in a `LinearLayout`, so you cannot have widgets after it. On the whole, for layouts like this, I recommend a `RelativeLayout`, as the rules are more explicit and therefore easier to maintain (you don't have to remember magic `layout_weight` tricks). Just have the `Button` be `alignParentBottom` and have the `WebView` be `alignParentTop and above the `Button`. – CommonsWare Mar 26 '10 at 00:02
  • What about cases where you have 4 or 5 widgets, the first two are "wrap_content", the third is "fill_parent", and the last two are "Wrap_content". This would be a pain to maintain with a RelativeLayout - especially if you add another widget between two of the other widgets. With a LinearLayout, you already have to remember to give the one "growable" widget "fill_parent". You just have to remember to also give it the "layout_weight" "trick". – synic Mar 26 '10 at 00:56
  • `RelativeLayout` won't be difficult for that case either. The top widget would be `alignParentTop`, second would `layout_below` the first and the bottom two would be done similarly but aligned to the bottom. The middle "growable" widget would just have to `layout_below` the lower widget in the top group and `layout_above` the widget in the bottom group. – jqpubliq Mar 26 '10 at 05:17
  • Thanks for the responses, but I still don't understand why you have to have height: 0. I guess I'll have to look at the source! – Timmmm Mar 29 '10 at 10:21
  • According to docs and this answer: http://stackoverflow.com/a/12392771/2048266, if settings a `layout_weight`, should set `layout_height` to `0dp` for better performance – nommer Apr 14 '14 at 23:18
1

Well I since have understood this. The way the android layout system works is:

  1. All the things are laid out according to their specified height/width.
  2. Any remaining weight is distributed among the views according to their weights.

(Obviously this is never explained.)

Therefore to get it to work you want the button to be wrap-content, which makes it just as big as it needs to be, and the webview to be zero height (since it can shrink to zero). After step 1 you will have the button correct, and then webview zero-height.

Then you set the button weight to 0, and the webview weight to 1, so that any remaining space is given to the webview - i.e. it expands to fill the screen.

Makes perfect sense when you know the algorithm.

Timmmm
  • 88,195
  • 71
  • 364
  • 509
-1

You can try something like this:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
    android:layout_height="match_parent" >

        <WebView
                android:id="@+id/wv"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_above="@+id/btn" />

        <Button
            android:id="@+id/btn"
            android:layout_alignParentBottom="true" />
</RelativeLayout>
STT
  • 274
  • 5
  • 11
-1

Ok, here’s the code to make this:

WebView with Options Menu on Top and Bottom

The above picture has 2 rows of buttons: one on top and one on the bottom. In the middle is the WebView. Here is my GitHub account where u can download the source code: https://github.com/GeneChuang1/Android/tree/Android

Otherwise, here is the App breakdown:

The Java Code (AndroidMobileAppSampleActivity.java):

package com.gene;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.gene.R;

public class AndroidMobileAppSampleActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.app_page);

        WebView mainWebView = (WebView) findViewById(R.id.webcontent);

        WebSettings webSettings = mainWebView.getSettings();
        webSettings.setJavaScriptEnabled(true);

        mainWebView.setWebViewClient(new MyCustomWebViewClient());
        mainWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);

        mainWebView.loadUrl("http://www.google.com");
    }

    private class MyCustomWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }
    }
}

I have 2 XML layouts. One for the main webpage, the other is a pre-made menu that I in the main webpage. The XML Layout “app_page.xml”:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <LinearLayout
        android:id="@+id/page_weekly_items_options_menu"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#d4dbe1"
        android:gravity="center"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/share"
            android:layout_width="60dp"
            android:layout_height="50dp"
            android:background="@drawable/icon"
            android:clickable="true"
            android:onClick="userClickedShare"></ImageView>

        <ImageView
            android:id="@+id/left_arrow"
            android:layout_width="60dp"
            android:layout_height="50dp"
            android:background="@drawable/icon"
            android:clickable="true"
            android:onClick="userClickedLeftArrow"></ImageView>

        <ImageView
            android:id="@+id/right_arrow"
            android:layout_width="60dp"
            android:layout_height="50dp"
            android:background="@drawable/icon"
            android:clickable="true"
            android:onClick="userClickedRightArrow"></ImageView>

        <ImageView
            android:id="@+id/notifications_pageweeklyitem"
            android:layout_width="60dp"
            android:layout_height="50dp"
            android:background="@drawable/icon"
            android:clickable="true"
            android:onClick="userClickedNotificationsPageWeeklyItem"></ImageView>

        <ImageView
            android:id="@+id/favorites_pageweeklyitem"
            android:layout_width="60dp"
            android:layout_height="50dp"
            android:background="@drawable/icon"
            android:clickable="true"
            android:onClick="userClickedFavoritesPageWeeklyItem"></ImageView>

    </LinearLayout>

    <RelativeLayout
        android:id="@+id/webcontent_container"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_below="@id/page_weekly_items_options_menu">

        <WebView
            android:id="@+id/webcontent"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_above="@+id/menu"
            ></WebView>
        <include
            android:id="@+id/menu"
            layout="@layout/bottom_menu"
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:layout_alignParentBottom="true"
            android:gravity="bottom"
            android:layout_weight="1"
            />


    </RelativeLayout>

</RelativeLayout>

The other XML layout is “bottom_menu.xml”:

<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/bottom_scroll_menu"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom" >
    <!-- This layout is used by activity_main.xml.
    It is part of the main home page -->
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#17528c"
        android:orientation="horizontal" >

        <ImageView
            android:id="@+id/Weekly"
            android:layout_width="60dp"
            android:layout_height="50dp"
            android:background="@drawable/icon"
            android:clickable="true"
            android:onClick="userClickedWeekly" >
        </ImageView>

        <ImageView
            android:id="@+id/Search"
            android:layout_width="60dp"
            android:layout_height="50dp"
            android:background="@drawable/icon"
            android:clickable="true"
            android:onClick="userClickedSearch" >
        </ImageView>

        <ImageView
            android:id="@+id/Favorites"
            android:layout_width="60dp"
            android:layout_height="50dp"
            android:background="@drawable/icon"
            android:clickable="true"
            android:onClick="userClickedFavorites" >
        </ImageView>

        <ImageView
            android:id="@+id/Notifications"
            android:layout_width="60dp"
            android:layout_height="50dp"
            android:background="@drawable/icon"
            android:clickable="true"
            android:onClick="userClickedNotifications" >
        </ImageView>

        <ImageView
            android:id="@+id/Profile"
            android:layout_width="60dp"
            android:layout_height="50dp"
            android:background="@drawable/icon"
            android:clickable="true"
            android:onClick="userClickedProfile" >
        </ImageView>

        <ImageView
            android:id="@+id/About"
            android:layout_width="60dp"
            android:layout_height="50dp"
            android:background="@drawable/icon"
            android:clickable="true"
            android:onClick="userClickedAbout" >
        </ImageView>
    </LinearLayout>

</HorizontalScrollView>

The Android Manifest (just incase someone forgets the internet permission):

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="tscolari.mobile_sample"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="10" />

    <uses-permission android:name="android.permission.INTERNET"/>

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".AndroidMobileAppSampleActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
</manifest>

Again, here is my GitHub account where u can download the source code: https://github.com/GeneChuang1/Android/tree/Android

-Gene Chuang

Gene
  • 10,819
  • 1
  • 66
  • 58
-1

you can specify the heigth of your webView in pixels

android:layout_heigth = " 70px"

for example

hope it helps

Lucifer
  • 29,392
  • 25
  • 90
  • 143
hocinao
  • 9
  • 2