繁体   English   中英

找不到片段ID的视图(在listView中)

[英]No view found for id for fragment (in listView)

我是一个长期的stackOverflow潜行者,并且是第一次海报,所以如果我错过任何步骤或要求,我深表歉意。 我已经在此bug上停留了2个星期,并且已经在网上广泛搜索了相关的bug,但是没有任何解决方案能够解决我的问题,所以我希望你们中的一个可以帮助您对此有所了解! 奇怪的是,它曾经可以正常工作,并且我没有对代码进行任何更改,因此它要么是我只是没赶上的过时API,要么就是其他。

我有一个ListView,其中一个列表项包含一个带有地图的片段。 加载ListView时,出现此崩溃:

> FATAL EXCEPTION: main
Process: com.example.dev , PID: 10386
java.lang.IllegalArgumentException: No view found for id 0x7f0d00a4 (com.example.dev:id/map_container) for fragment LocationMapFragment{4266c870 #1 id=0x7f0d00a4}
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:939)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1126)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:739)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1489)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:454)
at android.os.Handler.handleCallback(Handler.java:733
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5872)
at java.lang.reflect.Method.invokeNative(Native Method
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1069)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:885)
at dalvik.system.NativeStart.main(Native Method)

这是保存带有地图片段的列表项:

package com.csf.ui.form;

import android.content.Context;
import android.content.Intent;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;

import com.csf.R;
import com.csf.model.CSFormElement;
import com.csf.ui.form.location.FormLocationMapActivity;
import com.csf.ui.fragment.FormFragment;
import com.csf.ui.form.location.LocationMapFragment;
import com.csf.utils.Constants;

public class LocationFormCell extends FormCell {

    private LocationMapFragment locationFrag;

    public LocationFormCell(Context ctx, CSFormElement elem, FormFragment frag, boolean editable) {
        super(ctx, elem, frag, editable);
        View view  = LayoutInflater.from(ctx).inflate(R.layout.form_element_location, this);
        Button overlayButton;

        overlayButton = (Button) view.findViewById(R.id.overlayButton);
        setupOnClickListener(overlayButton);
        if (ctx instanceof FragmentActivity) {
            FragmentActivity act = (FragmentActivity) ctx;
            locationFrag = LocationMapFragment.newInstance(formElement.disp_name,false);
            FragmentTransaction ft = act.getSupportFragmentManager().beginTransaction();
            ft.add(R.id.map_container, locationFrag);
            ft.commitAllowingStateLoss();
            locationFrag.setValue(value);
        }
    }

    public void setupOnClickListener(Button overlayButton) {
        overlayButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent;
                formFragment.currentCell = LocationFormCell.this;
                intent = new Intent(formFragment.getActivity(),FormLocationMapActivity.class);
                intent.putExtra(FormLocationMapActivity.EXTRA_FORM_ELEMENT_ID,formElement.element_id);
                intent.putExtra(FormLocationMapActivity.EXTRA_LOCATION_VALUE,value);
                formFragment.startActivityForResult(intent,Constants.REQ_CODE_LOCATION);
            }
        });
    }

    @Override
    public void setValue(String value) {
        this.value = value;
        locationFrag.setValue(value);
        setInvalid(false);
    }

    @Override
    public void clearValue() {
        value = "";
        locationFrag.clearValue();
    }

    @Override
    public void setInvalid(boolean invalid) {
        // TODO Auto-generated method stub  
    }
}

这是列表项的xml布局:form_element_location.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/containerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/map_container">
    </FrameLayout>

    <Button
        android:id="@+id/overlayButton"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent"/>

    </FrameLayout>

这是LocationMapFragment.java

package com.csf.ui.form.location;

import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.ZoomControls;

import com.csf.R;
import com.csf.model.CSGlobalSetting;
import com.csf.provider.DatabaseManager;
import com.csf.utils.GeoUtils;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
import com.google.android.gms.maps.GoogleMap.OnMarkerClickListener;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.MapsInitializer;
import com.google.android.gms.maps.model.BitmapDescriptor;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.Circle;
import com.google.android.gms.maps.model.CircleOptions;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;
import com.kaciula.utils.LogUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;

public class LocationMapFragment extends Fragment implements OnMapClickListener,  OnMarkerClickListener, GoogleMap.OnMyLocationChangeListener {

    public static final String ARG_TITLE = "TITLE";
    public static final String ARG_FULLSCREEN = "FULLSCREEN";
    private String value;
    private Location currentLocation;
    private Location mItemLocation;
    private Marker mItemMarker;
    private Circle mItemRadiusCircle;
    private Polyline mPolyline;
    private double mLocationRadius;
    boolean mMapLayoutOccurred = false;
    boolean mGooglePlayServicesAvailable = false;
    private Date mGPSCheckDate;
    private boolean mUserInteracted = false;
    ImageView gpsIndicatorImageView;
    TextView titleLabel;
    TextView distanceLabel;
    TextView gpsWarningLabel;
    LinearLayout mapWrapperView;
    MapView mapView;
    LocationMapFragmentListener listener;

    public static LocationMapFragment newInstance(String title, boolean fullScreen) {
        Bundle bundle;
        LocationMapFragment locationMapFragment;
        bundle = new Bundle();
        bundle.putString(ARG_TITLE,title);
        bundle.putBoolean(ARG_FULLSCREEN, fullScreen);
        locationMapFragment = new LocationMapFragment();
        locationMapFragment.setArguments(bundle);

        return locationMapFragment;
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MapsInitializer.initialize(getActivity());
        if ( GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity()) == ConnectionResult.SERVICE_MISSING) {
            mGooglePlayServicesAvailable = false;
        } else {
            mGooglePlayServicesAvailable = true;
        }
    }



    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if ( activity instanceof LocationMapFragmentListener ) {
            listener = (LocationMapFragmentListener)activity;
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        listener = null;
    }

    public String getTitle() {
        return getArguments().getString(ARG_TITLE, "");
    }

    public boolean getFullscreen() {
        return getArguments().getBoolean(ARG_FULLSCREEN);
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.widget_location_map, container, false);
        gpsIndicatorImageView = (ImageView) view.findViewById(R.id.gpsIndicatorImageView);
        titleLabel = (TextView)view.findViewById(R.id.titleLabel);
        distanceLabel = (TextView)view.findViewById(R.id.distanceLabel);
        gpsWarningLabel = (TextView)view.findViewById(R.id.gpsWarningLabel);
        mapWrapperView = (LinearLayout)view.findViewById(R.id.mapWrapperView);
        mapView = (MapView)view.findViewById(R.id.mapView);
        mapView.onCreate(savedInstanceState);
        mGPSCheckDate = new Date();
        titleLabel.setText(getTitle());
        mMapLayoutOccurred = false;
        setupMap();
        LogUtils.d("LocationMapFragment", "Creating LocationMapFragment " + LocationMapFragment.this);
        return view;
    }

    private void setupMap() {
        Handler handler = new Handler();
        GoogleMap map;

        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                updateGPSIndicator();
            }
        },5000);
        try {
            if (mapView != null && mapView.getMap() != null) {
                map = mapView.getMap();
                map.getUiSettings().setZoomControlsEnabled(getFullscreen());
                map.setOnMapClickListener(this);
                map.setOnMarkerClickListener(this);
                map.getUiSettings().setScrollGesturesEnabled(true);
                map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(39.095963, -98.275452), 4));
                if ( !getFullscreen() ) {
                    map.getUiSettings().setMyLocationButtonEnabled(false);
                    map.getUiSettings().setScrollGesturesEnabled(false);

                } else {
                    mapWrapperView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT));
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            updateAnnotations();
            updateZoom();
            updateLineBetweenAnnotations();
            showDistance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        mapView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (!mMapLayoutOccurred && mapView.getMap() != null) {
                    if (mapView.getWidth() > 0 && mapView.getHeight() > 0) {
                        mapView.getMap().setMyLocationEnabled(true);
                        mapView.getMap().setOnMyLocationChangeListener(LocationMapFragment.this);
                        updateGPSIndicator();
                        showDistance();
                        updateZoom();
                        updateAnnotations();
                        updateLineBetweenAnnotations();
                        LogUtils.d("LocationMapFragment", "Layout occurred " + LocationMapFragment.this);
                        mMapLayoutOccurred = true;
                    }
                }
            }
        });
    }

    @Override
    public void onResume() {
        super.onResume();
        mapView.onResume();
    }

    @Override
    public void onPause() {
        mapView.onPause();
        super.onPause();
    }

    @Override
    public void onDestroy() {
        mapView.onDestroy();
        super.onDestroy();
    }

    @Override
    public void onLowMemory() {
        mapView.onLowMemory();
        super.onLowMemory();
    }

    @Override
    public void onMapClick(LatLng location) {
        if ( listener != null ) {
            listener.onLocationSelected(location);
        }
    }

    @Override
    public boolean onMarkerClick(Marker arg0) {
        return false;
    }

    public void resetZoom() {
        mUserInteracted = false;
        updateZoom();
    }

    private void updateLineBetweenAnnotations() {
        List<LatLng> points;

        if ( mItemLocation != null && currentLocation != null) {
            points = new ArrayList<LatLng>(2);
            points.add(GeoUtils.LatLngFromLocation(mItemLocation));
            points.add(GeoUtils.LatLngFromLocation(currentLocation));
            if ( mPolyline != null ) {
                mPolyline.setPoints(points);
            } else {
                mPolyline = mapView.getMap().addPolyline(new PolylineOptions().add(points.get(0)).add(points.get(1)).color(0xffff0000).width(2));
            }
        }
    }

    private void updateZoom() {
        LatLngBounds.Builder rangeBuilder;
        int buffer = getFullscreen() ? 40 : 10;

        if ( !mMapLayoutOccurred || !mGooglePlayServicesAvailable || mUserInteracted ) {
            return;
        }

        rangeBuilder = new LatLngBounds.Builder();

        if ( mItemLocation != null && currentLocation != null ) {
            rangeBuilder.include(GeoUtils.LatLngFromLocation(mItemLocation));
            rangeBuilder.include(GeoUtils.LatLngFromLocation(currentLocation));
            mapView.getMap().animateCamera(CameraUpdateFactory.newLatLngBounds(rangeBuilder.build(), buffer));
        } else if ( mItemLocation != null ) {
            mapView.getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(GeoUtils.LatLngFromLocation(mItemLocation), buffer));
        } else if ( currentLocation != null ) {
            mapView.getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(GeoUtils.LatLngFromLocation(currentLocation), buffer));
        }
    }

    private void updateAnnotations() {
        if ( mItemLocation != null ) {
            if ( mItemMarker == null ) {
                BitmapDescriptor icon = BitmapDescriptorFactory.fromResource(R.drawable.map_pin);
                mItemMarker = mapView.getMap().addMarker(new MarkerOptions().position(GeoUtils.LatLngFromLocation(mItemLocation)).icon(icon));
            } else {
                mItemMarker.setPosition(GeoUtils.LatLngFromLocation(mItemLocation));
            }
            if ( mLocationRadius != 0 ) {
                if ( mItemRadiusCircle == null ) {
                    mItemRadiusCircle = mapView.getMap().addCircle(new CircleOptions().center(mItemMarker.getPosition()).radius(mLocationRadius).strokeColor(0xff00ff00).strokeWidth(1).fillColor(0x7700ff00));
                } else {
                    mItemRadiusCircle.setCenter(mItemMarker.getPosition());
                    mItemRadiusCircle.setRadius(mLocationRadius);
                }
            } else {
                if ( mItemRadiusCircle != null ) {
                    mItemRadiusCircle.remove();
                    mItemRadiusCircle = null;
                }
            }
        } else {
            if ( mItemMarker != null ) {
                mItemMarker.remove();
                mItemMarker = null;
            }
        }
    }

    private void updateGPSIndicator() {
        float accuracy = 0;
        int badAccuracyThreshold;
        CSGlobalSetting thresholdSetting;


        if ( getView() == null ) {
            return;
        }
        if ( Math.abs(mGPSCheckDate.getTime() - new Date().getTime()) < 5000 ) {
            return;//Give the GPS time to get going
        }
            thresholdSetting = DatabaseManager.getInstance().getGlobalSettingName(CSGlobalSetting.CSGlobalSettingGPSAccuracyWarningLevel);
        if ( thresholdSetting != null  ) {
            badAccuracyThreshold = thresholdSetting.getIntValue();
            if ( badAccuracyThreshold == 0 ) {
                badAccuracyThreshold = 200;
            }
        } else {
            badAccuracyThreshold = 200;
        }
        if ( this.currentLocation != null ) {
            accuracy = this.currentLocation.getAccuracy();
            if (accuracy <= 0) {
                gpsIndicatorImageView.setImageResource(R.drawable.icon_gps_indicator_none);
            } else if (accuracy > 163) {
                gpsIndicatorImageView.setImageResource(R.drawable.icon_gps_indicator_poor);
            } else if (accuracy > 48) {
                gpsIndicatorImageView.setImageResource(R.drawable.icon_gps_indicator_fair);
            } else {
                gpsIndicatorImageView.setImageResource(R.drawable.icon_gps_indicator_good);
            }
            if ( badAccuracyThreshold > 0 && accuracy > badAccuracyThreshold ) {
                gpsWarningLabel.setText("Device has poor GPS signal. Some GPS functions may not be accurate.");
                gpsWarningLabel.setVisibility(View.VISIBLE);
            } else {
                gpsWarningLabel.setVisibility(View.GONE);
            }
        } else {
            gpsWarningLabel.setText("Current location not yet available.");
            gpsWarningLabel.setVisibility(View.VISIBLE);
        }
    }

    @Override
    public void onMyLocationChange(Location location) {
        Location oldLocation = currentLocation;
        currentLocation = location;
        if ( !mMapLayoutOccurred ) {
            return;
        }
        updateGPSIndicator();
        showDistance();
        updateLineBetweenAnnotations();
        if ( oldLocation == null || !getFullscreen() ) {
            updateZoom();
        }
    }

    public void acceptLocation(Location l) {
        mItemLocation = l;
        updateAnnotations();
        updateZoom();
        updateLineBetweenAnnotations();
    }

    public void setValue(String value) {

        this.value = value;
        mItemLocation = getLocationFromValue(value);
        if ( mapView != null && mMapLayoutOccurred ) {
            updateAnnotations();
            updateZoom();
            updateLineBetweenAnnotations();
        }
    }


    public void clearValue() {
        value = "";
    }

    public void setLocationRadius(double locationRadius) {
        mLocationRadius = locationRadius;
    }

    public String getValue() {
        return value;
    }

    private void showDistance() {
        if (currentLocation != null && mItemLocation != null) {

            int distance = GeoUtils.measure(mItemLocation.getLatitude(), mItemLocation.getLongitude(), currentLocation.getLatitude(),currentLocation.getLongitude());
            String distanceString, unitString;

            if (Locale.US.equals(Locale.getDefault())) {
                // imperial
                double feetDistance = distance * 3.2808399;
                double yardDistance = distance * 1.0936133;
                double milesDistance = distance / 1609.344;

                if (feetDistance < 300) {
                    distanceString = "" + feetDistance;
                    unitString = "ft";
                } else if (yardDistance < 500) {
                    distanceString = "" + yardDistance;
                    unitString = "yds";
                } else {
                    distanceString = "" + milesDistance;
                    unitString = (milesDistance > 1.0 && milesDistance < 1.1) ? "mile" : "miles";
                }
            } else {
                // metric
                double meterDistance = distance;
                double kilometerDistance = distance / 1000;

                if (kilometerDistance >= 1) {
                    distanceString = "" + kilometerDistance;
                    unitString = "km";
                } else {
                    distanceString = "" + meterDistance;
                    unitString = "m";
                }
            }
            if (distanceString != null) {
                int comma = distanceString.indexOf('.');
                if (distanceString.length() > comma + 2) {
                    distanceString = distanceString.substring(0, comma + 3);
                }
            }
            distanceLabel.setText(distanceString + " " + unitString + " away");
        }
    }

    public Location getLocationFromValue(String value) {
        double lat = -1;
        double lng = -1;
        Location location = null;
        if (!TextUtils.isEmpty(value)) {
            StringTokenizer tok = new StringTokenizer(value, ",");
            if (tok.hasMoreTokens()) {
                lat = Double.parseDouble(tok.nextToken());
                if (tok.hasMoreTokens()) {
                    lng = Double.parseDouble(tok.nextToken());
                }
            }
        }
        if ( lat != -1 && lng != -1 ) {
            location = new Location(LocationManager.PASSIVE_PROVIDER);
            location.setLatitude(lat);
            location.setLongitude(lng);
        }
        return location;
    }

    public Location getCurrentLocation() {
        return currentLocation;
    }


    private class TouchableWrapper extends FrameLayout {
        public TouchableWrapper(Context context) {
            super(context);
        }

        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            switch (ev.getAction()) {
                case MotionEvent.ACTION_MOVE:
                    mUserInteracted = true;
                    break;
            }

            return super.dispatchTouchEvent(ev);
        }
    }

    public interface LocationMapFragmentListener {
        public void onLocationSelected(LatLng location);
    }


}

这是LocationMapFragment的widget_location_map.xml布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/gray" android:layout_alignParentTop="true" android:padding="5dp" >

        <ImageView
                android:id="@+id/gpsIndicatorImageView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/icon_gps_indicator_none" android:maxHeight="20dp"/>
        <View
            android:layout_width="0dip"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <TextView
            android:id="@+id/titleLabel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:textColor="@color/white"
            style="@style/CustomLayoutFont" />

        <TextView
            android:id="@+id/distanceLabel"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="right|center_vertical"
            android:textColor="@color/white"
            android:textSize="@dimen/text_micro"
            style="@style/CustomLayoutFont" />
    </LinearLayout>
    <TextView
            android:id="@+id/gpsWarningLabel"
            android:visibility="gone"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Weak GPS signal. Some GPS functions may not behave correctly."
            android:layout_alignParentBottom="true"
            android:background="@color/red"
            android:textColor="@color/white"
        style="@style/CustomLayoutFont"/>

    <LinearLayout
            android:id="@+id/mapWrapperView"
            android:layout_width="match_parent"
            android:layout_height="@dimen/form_elem_map_height">
        <com.google.android.gms.maps.MapView
                android:id="@+id/mapView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:clickable="true"
                />
            </LinearLayout>

</LinearLayout>

知道发生了什么吗? 欢迎任何建议! 谢谢。

您将错误的上下文指向fragmentTransaction 尝试以下方法。 您可以使用view.getContext()获得视图的上下文。

如下所示更新LocationFormCell构造函数。

public LocationFormCell(Context ctx, CSFormElement elem, FormFragment frag, boolean editable) {
    super(ctx, elem, frag, editable);
    View view  = LayoutInflater.from(ctx).inflate(R.layout.form_element_location, this);
        Button overlayButton;

        overlayButton = (Button) view.findViewById(R.id.overlayButton);
        setupOnClickListener(overlayButton);
        locationFrag = LocationMapFragment.newInstance(formElement.disp_name,false);
        FragmentTransaction ft = ((FragmentActivity)view.getContext()).getSupportFragmentManager().beginTransaction();
        ft.add(R.id.map_container, locationFrag);
        ft.commitAllowingStateLoss();
        locationFrag.setValue(value);
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM