IllegalStateException: View size is too small after padding

徘徊边缘 提交于 2019-12-12 08:31:24

问题


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:


For Android, I have also tried various solutions and finally found the main reason behind the crash.

The Main Reason behind the crash is Split Screen Support/Multi-Window support in Android 7 - 7.1.2 (API: 24 – 25).

LatLngBounds with padding set based on the percentage of the device width so that it works on small devices. This works even on small devices with 4inch displays, however, it fails in multi-window mode in Android 7.0 and devices that support multi-window mode before that, eg. Galaxy S7.

The solution is to choose the minimum metric between width and height since in Multi-window mode the height can be smaller than the width:

final int width = getResources().getDisplayMetrics().widthPixels;
final int height = getResources().getDisplayMetrics().heightPixels;
final int minMetric = Math.min(width, height);
final int padding = (int) (minMetric * paddingPercentage);

You can choose the padding percentage based on your requirements.

For Move Camera,

googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds.build(), width, height, padding));

For Animate Camera,

googleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds.build(), width, height, padding));



回答4:


Set padding 300 to 150. it working for me.

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



回答5:


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.




回答6:


My solution below , works on a map which is roughly 60% of a screen with smaller resolution (1280x720) (code is Kotlin)

 val builder = LatLngBounds.Builder()
            //storing the MarkerOptions in a hashmap
            builder.include(markers[MarkerType.START]?.position)
            builder.include(markers[MarkerType.END]?.position)
            val bounds = builder.build()
            val width = resources.displayMetrics.widthPixels
            val  height = resources.displayMetrics.heightPixels
            val  minMetric = min(width, height)
            //divide the smallest screen value by 10 , to get a value around 100
            val  padding = minMetric.div(10) 
            val cu = CameraUpdateFactory.newLatLngBounds(bounds, padding)
            googleMap?.animateCamera(cu)


来源:https://stackoverflow.com/questions/33046704/illegalstateexception-view-size-is-too-small-after-padding

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!