Friday, 20 November 2015

XML : No view found for id for fragment (in listView)

I'm a long time stackOverflow lurker and a first time poster so I apologize if I miss any steps or requirements. I have been stuck on this bug for 2 weeks now and have extensively searched for related bugs online but nothing has solved my problem so I'm hoping one of you guys can help shed some light on this! The weird thing about this is, it used to work and I've made no code changes so it's either an outdated API that I'm just not catching or something else.

I've got a ListView, and one of the list items holds a fragment with a map. When the ListView is loading, I get this crash:

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

Here is the list item that holds the fragment with the map:

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

here is the list item xml layout: 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>    

Here is the 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);      }      }    

and here is the widget_location_map.xml layout for the LocationMapFragment

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

Any idea what is going on?? Any advice is welcome! Thank you.

No comments:

Post a Comment