IllegalStateException: View size is too small afte

2019-04-05 05:43发布

问题:

I am developing an android app. In this app I am showing a MapView in a fragment. If my device is rotated and I try to move the camera using one of the following methods:

mapa.animateCamera(cameraUpdate);

or

mapa.moveCamera(cameraUpdate);

Then my app crashes and shows the following error:

java.lang.IllegalStateException: View size is too small after padding
 at com.google.a.a.ab.b(Unknown Source)
 at com.google.maps.api.android.lib6.gmm6.c.a.a(Unknown Source)
 at com.google.maps.api.android.lib6.gmm6.c.a.a(Unknown Source)
 at com.google.maps.api.android.lib6.d.dw.a(Unknown Source)
 at com.google.maps.api.android.lib6.gmm6.c.a.a(Unknown Source)
 at com.google.maps.api.android.lib6.d.et.a(Unknown Source)
 at com.google.android.gms.maps.internal.j.onTransact(SourceFile:83)
 at android.os.Binder.transact(Binder.java:380)
 at com.google.android.gms.maps.internal.IGoogleMapDelegate$zza$zza.moveCamera(Unknown Source)
 at com.google.android.gms.maps.GoogleMap.moveCamera(Unknown Source)
 at com.accionplus.dbdplus.utils.MapUtils.centrarCamara(MapUtils.java:88)
 at com.accionplus.dbdplus.utils.MapUtils.centrarCamara(MapUtils.java:52)
 at com.accionplus.dbdplus.controladores.pdv.RutaProgramadaFragment$4.onMyLocationButtonClick(RutaProgramadaFragment.java:274)
 at com.google.android.gms.maps.GoogleMap$3.onMyLocationButtonClick(Unknown Source)
 at com.google.android.gms.maps.internal.zzo$zza.onTransact(Unknown Source)
 at android.os.Binder.transact(Binder.java:380)
 at com.google.android.gms.maps.internal.be.a(SourceFile:81)
 at com.google.maps.api.android.lib6.d.ak.onClick(Unknown Source)
 at android.view.View.performClick(View.java:5156)
 at android.view.View$PerformClick.run(View.java:20755)
 at android.os.Handler.handleCallback(Handler.java:739)
 at android.os.Handler.dispatchMessage(Handler.java:95)
 at android.os.Looper.loop(Looper.java:145)
 at android.app.ActivityThread.main(ActivityThread.java:5832)
 at java.lang.reflect.Method.invoke(Native Method)
 at java.lang.reflect.Method.invoke(Method.java:372)
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)

I have googled it but with no success. I just have found that it was a reported issue for google but I do not know if there is any workaround to "solve" this issue. Any one can help me?

EDIT: I am adding more code

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                tools:context="com.accionplus.dbdplus.controladores.pdv.RutaProgramadaActivity">

    <LinearLayout
        android:id="@+id/card_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#15000000"
        android:orientation="vertical"/>

    <LinearLayout
        android:id="@+id/filtro_ll"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/card_container"
        android:layout_margin="10dp"
        android:gravity="left|top"
        android:orientation="horizontal"
        android:weightSum="1">

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.7"
            android:gravity="left|top"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="left"
                android:orientation="horizontal"
                android:weightSum="1">

                <ImageButton
                    android:id="@+id/seleccionar_fecha_btn"
                    android:layout_width="wrap_content"
                    android:layout_height="35dp"
                    android:background="@drawable/button"
                    android:src="@drawable/ic_date"
                    android:text="@string/buscar"
                    android:textColor="@color/color_text_primary"/>

                <TextView
                    android:id="@+id/fecha_consulta_tv"
                    android:layout_width="match_parent"
                    android:layout_height="35dp"
                    android:layout_alignParentTop="true"
                    android:layout_marginLeft="5dp"
                    android:background="@drawable/rectangle"
                    android:gravity="center"/>
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                android:background="@drawable/rectangle">

                <Spinner
                    android:id="@+id/tipo_ruta_sp"
                    android:layout_width="fill_parent"
                    android:layout_height="35dp"
                    android:layout_gravity="center"
                    />
            </LinearLayout>

        </LinearLayout>
    </LinearLayout>

    <com.google.android.gms.maps.MapView
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/filtro_ll"/>

    <ProgressBar
        android:id="@+id/progress_bar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:foregroundGravity="center|top"
        android:visibility="gone"/>

</RelativeLayout>

Here's when MyLocationButton is clicked:

mMap.setOnMyLocationButtonClickListener(new GoogleMap.OnMyLocationButtonClickListener() {
            @Override
            public boolean onMyLocationButtonClick() {
                MapUtils.centrarCamara(getActivity(), mMap, mPuntosFinales);
                return true;
            }
        });

Here's MapUtils.centrarCamara() method:

public static void centrarCamara(Context contexto, GoogleMap mapa, LatLng... posiciones) {
        centrarCamara(contexto, mapa, Boolean.TRUE, posiciones);
    }

    public static void centrarCamara(Context contexto, GoogleMap mapa, boolean animado,
                                     LatLng... posiciones) {
        if (mapa == null) {
            return;
        }

        LatLngBounds.Builder builder = new LatLngBounds.Builder();
        for (LatLng posicion : posiciones) {
            builder.include(posicion);
        }

        LatLngBounds bounds = builder.build();

        CameraUpdate cu = CameraUpdateFactory
                .newLatLngBounds(bounds, ViewUtils.dpAPixeles(MARKERS_DP_OFFSET, contexto));

        if (animado) {
            mapa.animateCamera(cu);
        } else {
            mapa.moveCamera(cu);
        }
    }

ViewUtils.dpAPixeles:

public static int dpAPixeles(int dp, Context contexto) {
    Resources r = contexto.getResources();
    int px = (int) TypedValue
            .applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics());

    return px;
}

The exception occurrs when mapa.moveCamera() or mapa.animateCamera() are called;

回答1:

From the documentation

Do not change the camera with this camera update until the map has undergone layout (in order for this method to correctly determine the appropriate bounding box and zoom level, the map must have a size). Otherwise an IllegalStateException will be thrown. It is NOT sufficient for the map to be available (i.e. getMap() returns a non-null object); the view containing the map must have also undergone layout such that its dimensions have been determined. If you cannot be sure that this has occured, use newLatLngBounds(LatLngBounds, int, int, int) instead and provide the dimensions of the map manually.

Thus, your problem may be that the map doesn't have a size when you are calling mapa.animateCamera(cameraUpdate) or mapa.moveCamera(cameraUpdate).

Anyway, as you say that the exception is being thrown when you rotate your device, I would say that the real issue is that the padding that you are using when calling newLatLngBounds (ViewUtils.dpAPixeles(MARKERS_DP_OFFSET, contexto)) is causing problems (maybe the padding is bigger than the View's height / 2?). There is a registered issue (4773) related to Google Maps that may help you solve your problem. As stated there, one possible workaround is to set the cameraUpdate depending on the orientation:

if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
    cu = CameraUpdateFactory.newLatLngBounds(bounds, ViewUtils.dpAPixeles(MARKERS_DP_OFFSET, contexto));
} else {
    // Use another method to get your camera update, for example CameraUpdateFactory.newLatLng(latLng);
}


回答2:

I have tried a lot of the solution but none of them really solve my problem which was the padding exceeds the actual size of the map.

my solution is to but a small padding and then zoom out to give the same result.

this code is from my app and it works fine for me.

    public static void fitThePoints(GoogleMap map, ArrayList<LatLng> points) {
    //Calculate the markers to get their position
    LatLngBounds.Builder b = new LatLngBounds.Builder();
    for (LatLng point : points) b.include(point);

    //Change the padding as per needed
    map.moveCamera(CameraUpdateFactory.newLatLngBounds(b.build(), ConvertUtils.dp2px(30)));
    map.moveCamera(CameraUpdateFactory.zoomTo(map.getCameraPosition().zoom - 0.5f));
}


回答3:

Set padding 300 to 150. it working for me.

  map.animateCamera(
                CameraUpdateFactory.newLatLngBounds(boundsLatLongs, 150),
                1000, null);


回答4:

Had the error with react-native-maps

Solution was to give the map view component a minimum width and height, as it was being laid out before its parent view was.