【问题标题】:IllegalStateException: View size is too small after paddingIllegalStateException:填充后视图尺寸太小
【发布时间】:2016-01-07 21:36:38
【问题描述】:

我正在开发一个安卓应用程序。在这个应用程序中,我在片段中显示了一个 MapView。如果我的设备旋转并且我尝试使用以下方法之一移动相机:

mapa.animateCamera(cameraUpdate);

mapa.moveCamera(cameraUpdate);

然后我的应用程序崩溃并显示以下错误:

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)

我用谷歌搜索了它,但没有成功。我刚刚发现这是谷歌报告的问题,但我不知道是否有任何解决方法可以“解决”这个问题。谁能帮帮我?

编辑:我正在添加更多代码

<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>

点击MyLocationButton的时间如下:

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

这里是MapUtils.centrarCamara() 方法:

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;
}

调用mapa.moveCamera()mapa.animateCamera()时发生异常;

【问题讨论】:

  • 你能发布你用来创建cameraUpdate对象的代码吗?
  • 感谢您的回答,@antonio。我已经发布了更多代码

标签: android google-maps illegalstateexception


【解决方案1】:

来自the documentation

在地图更新之前,请勿使用此相机更新更改相机 经历了布局(为了使这种方法能够正确地确定 适当的边界框和缩放级别,地图必须有大小)。 否则将抛出 IllegalStateException。它不是 足以使地图可用(即 getMap() 返回一个 非空对象);包含地图的视图也必须经过 布局,使其尺寸已确定。如果你不能 确保发生这种情况,请使用 newLatLngBounds(LatLngBounds, int, int, int) 并手动提供地图的尺寸​​。

因此,您的问题可能是当您调用mapa.animateCamera(cameraUpdate)mapa.moveCamera(cameraUpdate) 时地图没有大小。

无论如何,正如您所说,当您旋转设备时会引发异常,我想说真正的问题是您在调用 newLatLngBounds (ViewUtils.dpAPixeles(MARKERS_DP_OFFSET, contexto)) 时使用的填充导致问题(也许填充大于视图的高度/ 2?)。有一个与 Google 地图相关的已注册问题 (4773) 可以帮助您解决问题。如那里所述,一种可能的解决方法是根据方向设置 cameraUpdate:

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】:

    将填充 300 设置为 150。它对我有用。

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

    【讨论】:

    • 如果将地图放在小容器中将无法使用。
    【解决方案3】:

    我尝试了很多解决方案,但没有一个能真正解决我的问题,即填充超出了地图的实际大小。

    我的解决方案是只填充一个小填充,然后缩小以给出相同的结果。

    这段代码来自我的应用程序,对我来说很好用。

        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));
    }
    

    【讨论】:

      【解决方案4】:

      react-native-maps 出现错误

      解决方案是为地图视图组件提供最小宽度和高度,因为它在其父视图之前布局。

      【讨论】:

      • 你能提供一个关于如何为 react-native-maps 设置 最小宽度和高度的 sn-p 吗?只需设置 minHeight 和 minWidth?
      【解决方案5】:

      对于Android,我也尝试了各种解决方案,终于找到了崩溃的主要原因。

      崩溃的主要原因是 Android 7 - 7.1.2 (API: 24 - 25) 中的分屏支持/多窗口支持。

      LatLngBounds 具有基于设备宽度百分比设置的填充,以便它适用于小型设备。 这甚至适用于具有 4 英寸显示屏的小型设备,但是,它在 Android 7.0 中的多窗口模式和之前支持多窗口模式的设备中失败,例如。银河 S7。

      解决方案是选择宽度和高度之间的最小度量,因为在多窗口模式下,高度可以小于宽度:

      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);
      

      您可以根据需要选择填充百分比。

      对于移动相机,

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

      对于动画相机,

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

      【讨论】:

      • 感谢您的回答,但您没有解释如何计算 paddingPercentage
      • 在我的研究中,我发现大于 100 的填充会触发该异常。因此,我们将尝试解决该值。所以上面的代码变成了 val width = resources.displayMetrics.widthPixels val height = resources.displayMetrics.heightPixels val minMetric = min(width, height) val padding = minMetric.div(10) // 除以 10 最小的属性是 720或现在大多数手机的 640 - 它就像一个魅力
      • @StevenTB 您可以自行决定要提供多少填充。在我看来,您可以将偏移设置为从地图边缘到屏幕的 10%。
      【解决方案6】:

      我下面的解决方案适用于大约占屏幕 60% 且分辨率较小 (1280x720) 的地图(代码是 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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-11-09
        • 2018-12-28
        • 2012-10-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-05
        相关资源
        最近更新 更多