如何在导航抽屉活动片段中正确使用谷歌地图片段。

4

我正在尝试在我的应用程序中放置Google Maps片段,但是当我尝试在Locations类中填充视图时,我一直收到此错误:

android.view.InflateException: Binary XML file line #37: Binary XML file line #37: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #37: Error inflating class fragment
Caused by: android.app.Fragment$InstantiationException: Trying to instantiate a class com.google.android.gms.maps.SupportMapFragment that is not a Fragment

我希望将地图片段放入另一个片段中,该片段在具有导航抽屉的主活动中加载。
这是我的代码,加载位置片段应该进入其中:
@Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

        Fragment fragment = new Race();
        toolbar.setTitle(R.string.nav_name_race);
        FragmentManager fragmentManager = getFragmentManager();

        if (id == R.id.nav_race) {
            toolbar.setTitle(R.string.nav_name_race);
            fragment = new Race();
        } else if (id == R.id.nav_pilot) {
            toolbar.setTitle(R.string.nav_name_pilot);
            fragment = new Pilot();
        } else if (id == R.id.nav_locations) {
            toolbar.setTitle(R.string.nav_name_locations);
            fragment = new Locations();
        } else if (id == R.id.nav_channelpicker) {
            toolbar.setTitle(R.string.nav_name_channelpicker);
            fragment = new Channelpicker();
        } else if (id == R.id.nav_band_overview) {
            toolbar.setTitle(R.string.nav_name_band_overview);
            fragment = new BandOverview();
        }

        fragmentManager.beginTransaction()
                .replace(R.id.mainframelayout, fragment)
                .commit();


        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

Locations类:

public class Locations extends Fragment implements OnMapReadyCallback {

    private View view;
    private GoogleMap map;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        this.view = inflater.inflate(R.layout.content_locations, container, false);
        SupportMapFragment mapFragment = (SupportMapFragment) (((FragmentActivity) getActivity()).getSupportFragmentManager().findFragmentById(R.id.map));
        mapFragment.getMapAsync(this);


        //set fab onClickListener
        FloatingActionButton fabtop = (FloatingActionButton) view.findViewById(R.id.fabtop);
        assert fabtop != null;
        fabtop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(view.getContext(), "top", Toast.LENGTH_SHORT).show();
            }
        });

        FloatingActionButton fabbottom = (FloatingActionButton) view.findViewById(R.id.fabbottom);
        assert fabbottom != null;
        fabbottom.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(view.getContext(), "bottom", Toast.LENGTH_SHORT).show();
            }
        });

        return this.view;
    }

    @Override
    public void onMapReady(GoogleMap googleMap)
    {
        map = googleMap;

        // Add a marker in Sydney and move the camera
        LatLng sydney = new LatLng(-34, 151);
        map.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
        map.moveCamera(CameraUpdateFactory.newLatLng(sydney));
    }
}

以下是布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="?android:attr/actionBarSize"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".MainActivity">

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fabtop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right|bottom"
        android:src="@drawable/ic_menu_mylocation"
        app:backgroundTint="#FFFFFF"
        android:layout_above="@+id/fabbottom"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_marginRight="@dimen/fab_margin" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fabbottom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right|bottom"
        android:src="@mipmap/ic_add_white_48dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_margin="@dimen/fab_margin" />
    
    <fragment 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"
        android:id="@+id/map"
        tools:context=".MapsActivity"
        android:name="com.google.android.gms.maps.SupportMapFragment" />

</RelativeLayout>

我认为问题出在一个fragment内部还有另一个fragment,因为如果我为地图创建一个新的Activity,一切都运行正常。我还是一个初学者,在处理fragments方面并不知道如何正确地将地图fragment插入到我的应用程序中。
欢迎提供任何建议。
1个回答

2
您不需要在片段中调用(SupportMapFragment) (((FragmentActivity) getActivity()).getSupportFragmentManager(),因为您在Fragment中已经有了getFragmentManager()。但是,在使用嵌套片段时,您应该使用getChildFragmentManager()而不是getFragmentManager()(请参阅文档)。
回到您的问题,您可以简单地将代码更新为以下内容:
SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
if (mapFragment != null) {
    mapFragment.getMapAsync(this);
}

如果你遇到了类似于“com.google.android.gms.maps.MapFragment的重复ID、标签为空或父ID与另一个片段相同”等问题,你可以尝试以下任一解决方案(点此)。或者尝试这个:

private View mContentView;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    if (mContentView == null) {
        mContentView = inflater.inflate(R.layout.content_locations, container, false);
    }
    return mContentView;
}

它不会每次都充填布局,因此您将不会遇到与com.google.android.gms.maps.MapFragment的重复ID、标签为空或父ID与另一个片段的问题。 但请确保在inflater.inflate的attachToRoot参数(最后一个参数)中传递false,否则您可能会遇到诸如“指定的子项已经有一个父项”的异常。


我尝试了你的解决方案,但是我无法编译,因为它不允许我将getChildFragmentManager()返回的片段转换为SupportMapFragment。 - lexlix
@Felix,你能否告诉我你的Locations类是继承自android.support.v4.app.Fragment还是android.app.Fragment - Rehan
它是从android.app.Fragment扩展的。 - lexlix
@Felix 那么你需要将它从android.support.v4.app.Fragment扩展到使用SupportMapFragment,并在您的Activity中更改Adapter,或者如果您直接使用android.app.Fragment,则必须在所有地方使用MapFragment代替SupportMapFragment,例如在您的xml中将com.google.android.gms.maps.SupportMapFragment更改为com.google.android.gms.maps.MapFragment,并相应地在您的Fragment中进行更改。你明白了吗? - Rehan
我将所有的Fragment更改为android.support.v4.app.Fragment,现在一切都运行得非常完美。非常感谢! - lexlix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接