双片段显示

时间:2016-07-09 15:17:43

标签: google-maps android-fragments

我正在编写一个有两种显示效果的应用: 1."电话模式"在正常大小的显示器上,一次显示一个片段(搜索片段,地图片段等)。这里的碎片加载没有特别的问题。 2。"平板电脑模式"在较大的显示器上,并排显示两个片段 - 一个与#34;电话模式相同",第二个是地图片段的永久显示。尝试在平板电脑模拟器上加载应用时会引发异常:

FATAL EXCEPTION: main
Process: il.co.sredizemnomorie.myapiplaces, PID: 7808
java.lang.RuntimeException: Unable to start activity ComponentInfo{il.co.sredizemnomorie.myapiplaces/il.co.sredizemnomorie.myapiplaces.MainActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
at android.app.ActivityThread.access$800(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
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:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at maps.f.g.a(Unknown Source)
at maps.ag.g$a.<init>(Unknown Source)
at maps.ag.g.a(Unknown Source)
at maps.ag.R.<init>(Unknown Source)
at maps.ag.t.a(Unknown Source)
at uz.onTransact(:com.google.android.gms.DynamiteModulesB:167)
at android.os.Binder.transact(Binder.java:361)
at com.google.android.gms.maps.internal.IGoogleMapDelegate$zza$zza.addMarker(Unknown Source)
at com.google.android.gms.maps.GoogleMap.addMarker(Unknown Source)
at il.co.sredizemnomorie.myapiplaces.FragmentWithMap.setUpMap(FragmentWithMap.java:165)
at il.co.sredizemnomorie.myapiplaces.FragmentWithMap.setUpMapIfNeeded(FragmentWithMap.java:141)
at il.co.sredizemnomorie.myapiplaces.FragmentWithMap.onCreateView(FragmentWithMap.java:72)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:742)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)
at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:339)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:602)
at il.co.sredizemnomorie.myapiplaces.MainActivity.onStart(MainActivity.java:270)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171)
at android.app.Activity.performStart(Activity.java:5241)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2168)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245) 
at android.app.ActivityThread.access$800(ActivityThread.java:135) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:136) 
at android.app.ActivityThread.main(ActivityThread.java:5017) 
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:779) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595) 
at dalvik.system.NativeStart.main(Native Method) 

以下是代码:

  

MainActivity.java

public class MainActivity extends ActionBarActivity implements FragmentWithDetails.OnFragmentInteractionListener, FragmentWithMap.OnFragmentInteractionListener,
    FragmentWithDetails.ListFragmentListener, TextView.OnEditorActionListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
    SettingsFragment.OnFragmentInteractionListener {

private static final String TAG = "PlaceFounder";
public static final String TAG_FAVORITES = "frag_favorites";
private static final String TAG_MAP = "map";
private static final String TAG_DETAILS = "details";


protected GoogleApiClient mGoogleApiClient;
protected Location mLastLocation;

private Bundle currentLocationBundle = new Bundle();
FragmentTransaction fragmentTransaction;
private android.support.v4.app.FragmentManager fragmentManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    buildGoogleApiClient();

    fragmentManager = getSupportFragmentManager();

    FragmentWithDetails fragmentDetails;
    if (isSingleFragment()) {
        if (savedInstanceState == null) {
            fragmentDetails = FragmentWithDetails.newInstance();
            fragmentDetails.setArguments(currentLocationBundle);
            fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.add(R.id.fragmnet_container, fragmentDetails, TAG_DETAILS);
            fragmentTransaction.commit();
        }
    }//end if we at small screen
    else {
        if (savedInstanceState == null) {
            fragmentDetails = FragmentWithDetails.newInstance();
            FragmentWithMap fragmentWithMap = FragmentWithMap.newInstance(null);
            fragmentDetails.setArguments(currentLocationBundle);

            fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.add(R.id.fragmnet_container_details, fragmentDetails, TAG_DETAILS);
            fragmentTransaction.add(R.id.fragmnet_container_map, fragmentWithMap, TAG_MAP);
            fragmentTransaction.commit();
        }
    }//end if big screen
}


// Show favorites fragment
private void showFavorites() {
    currentLocationBundle.putInt("isShowFav", 1);

    FragmentWithDetails fragmentFavorites = (FragmentWithDetails) fragmentManager.findFragmentByTag(TAG_FAVORITES);
    if (fragmentFavorites == null) {
        fragmentFavorites = FragmentWithDetails.newInstance();
        fragmentFavorites.setArguments(currentLocationBundle);
    }

    fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.replace(R.id.fragmnet_container, fragmentFavorites, TAG_FAVORITES);
    fragmentTransaction.addToBackStack(null);
    fragmentTransaction.show(fragmentFavorites);

    handleLargeLayout();

    fragmentTransaction.commit();
}


//Hide details and map only on large screen
//On small screen we reuse the same container

private void handleLargeLayout() {
    if (!isSingleFragment()) {
        fragmentTransaction.hide(getDetailsFragment());
        fragmentTransaction.hide(getMapFragment());
    }
}

private FragmentWithMap getMapFragment() {
    return (FragmentWithMap) fragmentManager.findFragmentByTag(TAG_MAP);
}

private FragmentWithDetails getDetailsFragment() {
    return (FragmentWithDetails) fragmentManager.findFragmentByTag(TAG_DETAILS);
}

private FragmentWithDetails getFavoritesFragment() {
    return (FragmentWithDetails) fragmentManager.findFragmentByTag(TAG_FAVORITES);
}


// Show settings fragment

private void showSettings() {
    SettingsFragment settingsFragment = SettingsFragment.newInstance();

    fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.replace(R.id.fragmnet_container, settingsFragment, "frag_settings");
    fragmentTransaction.addToBackStack(null);
    fragmentTransaction.show(settingsFragment);
    handleLargeLayout();
    fragmentTransaction.commit();
}


// Display current location on map

private void getCurrentLocation() {
    String currentLat = null;
    String currentLong = null;
    if (mLastLocation != null) {
        currentLat = String.valueOf(mLastLocation.getLatitude());
        currentLong = String.valueOf(mLastLocation.getLongitude());
        if (getMapFragment() != null) {
            getMapFragment().setPlace(new Place(0, "Current location", "", (float) mLastLocation.getLatitude(), (float) mLastLocation.getLongitude()));
        }

    }
    currentLocationBundle.putString("currentLat", currentLat);
    currentLocationBundle.putString("currentLong", currentLong);
}


//Builds a GoogleApiClient.

protected synchronized void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {
        case R.id.action_settings:
            showSettings();
            return true;
        case R.id.action_favorites:
            showFavorites();
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

protected boolean isSingleFragment() {
    return findViewById(R.id.layout_single_fragment) != null;
}

@Override
public void onFragmentInteraction(Uri uri) {

}

@Override
public void onPlaceSelected(long placeId) {
    fragmentManager = getSupportFragmentManager();
    Place place = getPlace(placeId);

    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    if (isSingleFragment()) {

        FragmentWithMap fragmentWithMap = FragmentWithMap.newInstance(place);

        fragmentTransaction.replace(R.id.fragmnet_container, fragmentWithMap, TAG_MAP).addToBackStack(null);
    } else {
        if (getMapFragment() == null) {
            android.support.v4.app.Fragment fragmentWithMap = FragmentWithMap.newInstance(place);
            fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.add(R.id.fragmnet_container_map, fragmentWithMap, TAG_MAP);
            fragmentTransaction.show(fragmentWithMap);
            fragmentTransaction.show(getDetailsFragment());

        } else {

            FragmentWithMap fragmentWithMap = getMapFragment();
            fragmentTransaction.show(fragmentWithMap);
            fragmentTransaction.show(getDetailsFragment());
            if (getFavoritesFragment() != null) {
                fragmentTransaction.hide(getFavoritesFragment());
            }

            fragmentWithMap.showPlace(place);
        }

    }
    fragmentTransaction.commit();
}


private Place getPlace(long placeId) {
    Cursor cursor = null;
    Place place = null;
    try {
        cursor = getContentResolver().query(PlacesContract.Places.CONTENT_URI, null, "_id=" + placeId, null, "name DESC");
        cursor.moveToNext();
        place = new Place(cursor.getInt(0), cursor.getString(1), cursor.getString(2), cursor.getFloat(3), cursor.getFloat(4));
    } finally {
        if (cursor != null && !cursor.isClosed()) {
            cursor.close();
        }
    }
    return place;
}

@Override
public void onBackPressed() {
    if (isSingleFragment() && getMapFragment() != null) {
        fragmentManager.popBackStack(null,
                FragmentManager.POP_BACK_STACK_INCLUSIVE);
    } else if (fragmentManager.findFragmentByTag("frag_favorites") != null) {
        fragmentManager.popBackStack(null,
                FragmentManager.POP_BACK_STACK_INCLUSIVE);
    } else if (fragmentManager.findFragmentByTag("frag_settings") != null) {
        fragmentManager.popBackStack(null,
                FragmentManager.POP_BACK_STACK_INCLUSIVE);
    } else {
        super.onBackPressed();
    }

}


@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
    return true;
}

@Override
protected void onStart() {
    super.onStart();
    mGoogleApiClient.connect();

    //start google analytics
    EasyTracker.getInstance(this).activityStart(this);  // Add this method.
}

@Override
protected void onStop() {
    super.onStop();
    if (mGoogleApiClient.isConnected()) {
        mGoogleApiClient.disconnect();
    }

    //stop google analytics
    EasyTracker.getInstance(this).activityStop(this);  // Add this method.
}

/**
 * Runs when a GoogleApiClient object successfully connects.
 */
@Override
public void onConnected(Bundle connectionHint) {

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
    if (mLastLocation == null) {
        Toast.makeText(this, "Location not found", Toast.LENGTH_LONG).show();
    }
    getCurrentLocation();
}

@Override
public void onConnectionFailed(ConnectionResult result) {

    toast("No Google Service");
    Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode());
}


private void toast(String message) {
    Toast.makeText(this, message,
            Toast.LENGTH_LONG).show();
}

@Override
public void onConnectionSuspended(int cause) {
    // The connection to Google Play services was lost for some reason
      Log.i(TAG, "Connection suspended");
    mGoogleApiClient.connect();
}

}

地图片段:

  

FragmentWithMap.java

public class FragmentWithMap extends android.support.v4.app.Fragment {
private OnFragmentInteractionListener mListener;
private static final double LAT = 32.084;
private static final double LON = 34.8878;
Place place;
private GoogleMap mMap;
private View view;
private Marker marker;
int userIcon = FragmentWithDetails.userIcon;

public static FragmentWithMap newInstance(Place place) {
    Bundle args = new Bundle();
    if (place != null) {
        args.putInt("id", place.getId());
        args.putString("name", place.getName());
        args.putString("address", place.getAddress());
        args.putFloat("lat", place.getLat());
        args.putFloat("lng", place.getLng());
    }
    FragmentWithMap fragment = new FragmentWithMap();
    fragment.setArguments(args);
    return fragment;
}

public FragmentWithMap() {
    //empty public constructor
}


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null && getArguments().getString("name") != null) {
        place = new Place(getArguments().getInt("id"), getArguments().getString("name"),
                getArguments().getString("address"), getArguments().getFloat("lat"),
                getArguments().getFloat("lng"));
    }
}

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

@Override
public void onDestroyView() {
    super.onDestroyView();
    android.support.v4.app.Fragment f = getFragmentManager()
            .findFragmentById(R.id.fragmnet_container_map);
    if (f != null) {
        try {
            getFragmentManager().beginTransaction().remove(f).commit();
        } catch (IllegalStateException ise) {
            Log.d("FragmentWithMap", "Already closed");
        }
    }

    ViewGroup parentViewGroup = (ViewGroup) view.getParent();
    if (parentViewGroup != null) {
        parentViewGroup.removeAllViews();
    }
}

public void onButtonPressed(Uri uri) {
    if (mListener != null) {
        mListener.onFragmentInteraction(uri);
    }
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
        mListener = (OnFragmentInteractionListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement OnFragmentInteractionListener");
    }
}

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

public void showPlace(Place place) {
    setPlace(place);
    setUpMap();
}

public void setPlace(Place place) {
    this.place = place;
}


public interface OnFragmentInteractionListener {
    public void onFragmentInteraction(Uri uri);
}

private void setUpMapIfNeeded() {
    // Do a null check
    if (mMap == null) {
        // Try to obtain the map from the SupportMapFragment.
        Fragment mmm = getChildFragmentManager().findFragmentById(R.id.fragment_map2);
        mMap = ((SupportMapFragment) mmm).getMap();

        // Check if we were successful
        if (mMap != null) {
            setUpMap();
        }
    }
}

private void setUpMap() {
    double lat = LAT;
    double lng = LON;
    String name = "You are here";
    if (place != null) {
        lat = place.getLat();
        lng = place.getLng();
        name = place.getName();
    }
    if (marker != null) {
        marker.remove();
    }
    LatLng position = new LatLng(lat, lng);
    MarkerOptions markerOptions = new MarkerOptions().
            position(position).
            title(name).
            icon(BitmapDescriptorFactory.fromResource(userIcon)).
            snippet("Your last recorded location");

    marker = mMap.addMarker(markerOptions);
    if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    mMap.setMyLocationEnabled(true);
    CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(position, 15);
    mMap.animateCamera(cameraUpdate);
}

}

XML:

  

activity_main.xml中

&#34;电话模式&#34;:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout_single_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/darker_gray"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
tools:context=".MainActivity">

<FrameLayout
    android:id="@+id/fragmnet_container"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"></FrameLayout>

和&#34;平板电脑模式&#34;

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout_two_fragments"
android:layout_width="match_parent"

android:layout_height="match_parent"
android:background="@android:color/darker_gray"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
tools:context=".MainActivity"

>

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

<FrameLayout
    android:id="@+id/fragmnet_container_details"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1.31"></FrameLayout>

<FrameLayout
    android:id="@+id/fragmnet_container_map"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="2"></FrameLayout>

我非常感谢您提供的任何帮助......

更新 崩溃点位于marker = mMap.addMarker(markerOptions);行的mapfragment末尾。我想我一定不能正确处理标记......仍然不清楚为什么它在单片段模式下工作正常,而不是双重片段。

2 个答案:

答案 0 :(得分:0)

您正试图在onCreate()access UI elementsonCreate()为时过早,无法调用getView(),它将返回null。将需要触及片段视图层次结构的代码推迟到片段生命周期中的onCreateView()或更高版本。因为片段视图可以在onCreateView()方法中创建。

尝试包含onActivityCreated(),当创建片段的活动并实例化此片段视图层次结构时调用它们。

答案 1 :(得分:0)

更新:已解决

问题最终出现在userIcon上(表示地图上显示的标记的美化类型)。当应用程序首次加载时,由于某种原因它返回0而不是null。因为它只是一个化妆品特征我只是删除,这解决了问题。不是最漂亮的解决方案,但它是我得到的解决方案,因为当应用程序的更关键部分仍然需要管理时,时间限制阻止我专注于更多时间。我希望它有所帮助。我希望一位经验丰富的程序员可能对标记系统非常熟悉,为那些希望包含自定义标记的人提供替代解决方案/解决方法。