Android 自定义视图和嵌套片段

Android custom view and nested fragments

我的视图中有一个父片段,其中以编程方式添加了 2 个子片段以显示地图。这是子片段的布局,地图在 FrameLayout 中呈现。

location_field_view.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    style="@style/settings_action_item_row_style"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="256dp"
        android:id="@+id/map_fragment_container"
        android:layout_marginTop="2dp">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="This is where map loads."/>
    </FrameLayout>
</LinearLayout>

相应的FrameLayouts中有地图加载的点击事件。我的问题是,即使 FrameLayout 视图已成功膨胀(因为我可以看到两个子片段的调试文本 "The map loads here"),但是第二个子片段的映射在第一个子片段本身中呈现(我看到它在刷新时第二个地图点击监听器被触发)。这里可能出了什么问题?

Class 在布局上方膨胀,然后将其添加到父片段:

LocationField.java

public class LocationField extends LinearLayout
{
    private MyMapFragment mMapFragment;
    public LocationField()
    {
        LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.location_field_view, this, true);
        addMapFragment();
        //mMapFragment.loadMap() method gets triggered based on a click event.
    }

    private void addMapFragment()
    {
        mMapFragment = MyMapFragment.newInstance(lat, long, marker);
        FragmentTransaction transaction = mParentFragment.getChildFragmentManager().beginTransaction();
        transaction.add(R.id.map_fragment_container, mMapFragment);
        transaction.addToBackStack(null);
        transaction.commit();
    }
}

MyMapFragment.java

public class MyMapFragment extends MapFragment implements OnMapReadyCallback
{
    private static final String KEY_MARKER = "marker";
    private static final String KEY_LATITUDE = "latitude";
    private static final String KEY_LONGITUDE = "longitude";
    private LatLng mLatLng;
    private String mMarker;

    public static MyMapFragment newInstance(Double latitude, Double longitude, String marker){

        MyMapFragment myMapFragment = new MyMapFragment();
        Bundle arguments = new Bundle();
        arguments.putDouble(KEY_LATITUDE, latitude);
        arguments.putDouble(KEY_LONGITUDE, longitude);
        arguments.putString(KEY_MARKER, marker);
        myMapFragment.setArguments(arguments);
        return myMapFragment;
    }

    public void onCreate(Bundle savedInstance)
    {
        super.onCreate(savedInstance);
        Bundle arguments = getArguments();
        mLatLng = new LatLng(arguments.getDouble(KEY_LATITUDE), arguments.getDouble(KEY_LONGITUDE));
        mMarker = arguments.getString(KEY_MARKER);
    }

    public void loadMap()
    {
        getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        if (googleMap == null) {
            return;
        }
        googleMap.addMarker(new MarkerOptions().position(mLatLng).title(mMarker));
        googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mLatLng, 10f));
    }
}

通过使用方法 generateViewId() 为地图动态设置 FrameLayouts 的 ID 解决了这个问题。

看起来 FragmentManager 正在覆盖之前添加的帧的帧 ID。 (因为他们都有相同的ID??)

共享解决问题所需的代码更改(以防其他人遇到此问题):

  1. 动态生成框架布局的 ID。一开始会有 您视图中框架布局的一个 ID。获取视图对象并 分配新生成的视图 ID。

    mMapFrameId = View.generateViewId();

  2. 在片段交易中使用相同的 ID,同时添加新的片段。

    mMapFragment = new MapFragment();
    FragmentTransaction transaction = mFragmentManager.beginTransaction();
    transaction.add(mMapFrameId, mMapFragment);
    transaction.addToBackStack(null);
    transaction.commit();