我是一个很长时间的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 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>
这是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>
知道发生了什么事吗?欢迎任何建议!谢谢。
答案 0 :(得分:0)
您将错误的上下文指向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);
}