简体   繁体   English

GLSurfaceView没有出现在MapView上

[英]GLSurfaceView not appearing over MapView

My goal is to use OpenGL ES 2.0 with Google Maps. 我的目标是将OpenGL ES 2.0与Google Maps结合使用。 I would like to create an app that follows the user as they are traveling from point A to point B. I realize that this can be done using Google Maps addPolyline to draw a line, but I want to use OpenGL instead in order to show overlap of paths. 我想创建一个跟随用户从A点到B点的应用程序。我意识到可以使用Google Maps addPolyline画一条线来完成此操作,但是我想使用OpenGL来显示重叠的路径。 I'm currently receiving an error which is due to incorrectly setting up the GLSurfaceView. 我目前收到错误消息,这是由于错误地设置了GLSurfaceView而引起的。

My code in the GoogleMapsTracker class is as follows: 我在GoogleMapsTracker类中的代码如下:

private MapView mapView;
private GoogleMap map;
private GLSurfaceView mGLSurfaceView;

/**
 * Use this factory method to create a new instance of
 * this fragment using the provided parameters.
 */
public static GoogleMapsTracker newInstance() {
    GoogleMapsTracker fragment = new GoogleMapsTracker();
    fragment.setRetainInstance(true);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mapView = (MapView) getActivity().findViewById(R.id.map);
    mGLSurfaceView = new GLSurfaceView(getActivity());

    // Check if the system supports OpenGL ES 2.0
    final ActivityManager am = (ActivityManager) getActivity().getSystemService(Context.ACTIVITY_SERVICE);
    final ConfigurationInfo cInfo = am.getDeviceConfigurationInfo();
    final boolean supportsEs2 = cInfo.reqGlEsVersion >= 0x20000;

    if(supportsEs2){
        // Request an OpenGL ES 2.0 compatible context
        mGLSurfaceView.setEGLContextClientVersion(2);

        // Set the renderer to out demo renderer, defined below
        mGLSurfaceView.setRenderer(new GoogleMapsRenderer(getActivity()));
    } else {
        // This is where you could create an OpenGL ES1.x compatible
        // renderer if you wanted to support both ES 1 and ES 2
        Log.d("Does Not Support ES 2.0", "Does NOT Support ES 2.0");
    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v;

    if(SettingsActivity.mUnits){
        v = inflater.inflate(R.layout.google_maps_tracker_metric, container, false);
    } else {
        v = inflater.inflate(R.layout.google_maps_tracker, container, false);
    }

    // Gets the MapView from the XML layout and creates it
    mapView = (MapView) v.findViewById(R.id.map);
    mapView.onCreate(savedInstanceState);

    // Gets to GoogleMap from the MapView and does initialization stuff
    map = mapView.getMap();

    map.getUiSettings().setMyLocationButtonEnabled(true);
    map.getUiSettings().setZoomControlsEnabled(true);
    map.getUiSettings().setRotateGesturesEnabled(true);

    map.setMyLocationEnabled(true);

    map.setMapType(GoogleMap.MAP_TYPE_SATELLITE);

    // Needs to call MapsInitializer before doing any CameraUpdateFactory calls
    MapsInitializer.initialize(this.getActivity());

    // Updates the location and zoom of the MapView
    CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(new LatLng(45.669656, -111.067373), 18);
    map.animateCamera(cameraUpdate);

    mGLSurfaceView = (GLSurfaceView) v.findViewById(R.id.gl);
    mGLSurfaceView.setEGLContextClientVersion(2);
    GoogleMapsRenderer renderer = new GoogleMapsRenderer(getActivity());
    mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
    mGLSurfaceView.setRenderer(renderer);
    mGLSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
    mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);

    mGLSurfaceView.setZOrderOnTop(true);

    return v;
}

My XML code: 我的XML代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >

<!--fragment
    android:name="com.google.android.gms.maps.MapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/map"
    tools:context=".MainActivity" /-->

<com.google.android.gms.maps.MapView android:id="@+id/map"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"/>

<android.opengl.GLSurfaceView
    android:id="@+id/gl"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    class="com.example.tracker.GoogleMapsRenderer"/>

</RelativeLayout>

The error I'm receiving is as follows: 我收到的错误如下:

    05-22 11:02:34.854  22996-22996/com.example.tracker E/AndroidRuntime﹕ FATAL     EXCEPTION: main
    Process: com.example.tracker, PID: 22996
    java.lang.NullPointerException: Attempt to invoke virtual method 'void android.opengl.GLSurfaceView$GLThread.surfaceCreated()' on a null object reference
            at android.opengl.GLSurfaceView.surfaceCreated(GLSurfaceView.java:523)
            at android.view.SurfaceView.updateWindow(SurfaceView.java:580)
            at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:176)
            at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:944)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1970)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5885)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
            at android.view.Choreographer.doCallbacks(Choreographer.java:580)
            at android.view.Choreographer.doFrame(Choreographer.java:550)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

I'm quite certain that I'm not adding my views together properly. 我敢肯定我没有正确地添加我的观点。 If anyone can point out my mistakes and a better way of implementing this idea that would be much appreciated. 如果有人能指出我的错误以及实现此想法的更好方法,将不胜感激。

I have found a solution to my problem. 我已经找到解决问题的办法。 Just not sure if there is a better way of doing it. 只是不确定是否有更好的方法。

Basically, all I did was split up the two views (MapView and GLSurfaceView) into two different Fragments. 基本上,我所做的只是将两个视图(MapView和GLSurfaceView)分成两个不同的片段。 Then used an Activity class to call the two fragments. 然后使用一个Activity类来调用这两个片段。 The XML file had the fragments cover the same area. XML文件的片段覆盖了相同的区域。 Below is my updated code. 下面是我的更新代码。

GoogleMapsActivity: GoogleMapsActivity:

public class GoogleMapsActivity extends FragmentActivity {

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu items for use in the action bar
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu_main, menu);
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    final Context context = this;

    return super.onOptionsItemSelected(item);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setTheme(R.style.DarkTheme);

    if(SettingsActivity.mUnits){
        setContentView(R.layout.google_maps_tracker_metric);
    } else {
        setContentView(R.layout.google_maps_tracker);
    }
}

@Override
protected void onResume(){
    super.onResume();

    // Get both fragments shown on the same screen
    FragmentManager fragmentManager = getFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

    GoogleMapsTracker fragment;
    fragment = GoogleMapsTracker.newInstance();

    GoogleMapsOGLES fragmentOGL;
    fragmentOGL = GoogleMapsOGLES.newInstance();

    fragmentTransaction.add(R.id.map, fragment);
    fragmentTransaction.add(R.id.gl, fragmentOGL);
    fragmentTransaction.commit();
}

@Override
protected void onPause(){
    super.onPause();
}

@Override
protected void onDestroy() { 
    super.onDestroy(); 
}

} }

GoogleMapsTracker: GoogleMapsTracker:

public class GoogleMapsTracker extends Fragment implements OnMapReadyCallback {

@Override
public void onMapReady(GoogleMap map){

}

MapView mapView;
GoogleMap map;

/**
 * Use this factory method to create a new instance of
 * this fragment using the provided parameters.
 */
public static GoogleMapsTracker newInstance() {
    GoogleMapsTracker fragment = new GoogleMapsTracker();
    fragment.setRetainInstance(true);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mapView = (MapView) getActivity().findViewById(R.id.maps);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v;

    v = inflater.inflate(R.layout.fragment_google_maps, container, false);

    // Gets the MapView from the XML layout and creates it
    mapView = (MapView) v.findViewById(R.id.maps);
    mapView.onCreate(savedInstanceState);

    // Gets to GoogleMap from the MapView and does initialization stuff
    map = mapView.getMap();

    map.getUiSettings().setMyLocationButtonEnabled(true);
    map.getUiSettings().setZoomControlsEnabled(true);
    map.getUiSettings().setRotateGesturesEnabled(true);

    map.setMyLocationEnabled(true);

    map.setMapType(GoogleMap.MAP_TYPE_SATELLITE);

    // Needs to call MapsInitializer before doing any CameraUpdateFactory calls
    MapsInitializer.initialize(this.getActivity());

    // Updates the location and zoom of the MapView
    CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(new LatLng(49.025656, -125.035473), 18);
    map.animateCamera(cameraUpdate);

    return v;
}

GoogleMapsOGLES: GoogleMapsOGLES:

public class GoogleMapsOGLES extends Fragment {
GLSurfaceView mGLSurfaceView;

private boolean rendererSet = false;

/**
 * Use this factory method to create a new instance of
 * this fragment using the provided parameters.
 */
public static GoogleMapsOGLES newInstance() {
    GoogleMapsOGLES fragment = new GoogleMapsOGLES();
    fragment.setRetainInstance(true);
    return fragment;
}

public GoogleMapsOGLES() {
    // Do nothing
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mGLSurfaceView = new GLSurfaceView(getActivity());

    // Check if the system supports OpenGL ES 2.0
    final ActivityManager am = (ActivityManager) getActivity().getSystemService(Context.ACTIVITY_SERVICE);
    final ConfigurationInfo cInfo = am.getDeviceConfigurationInfo();
    final boolean supportsEs2 = cInfo.reqGlEsVersion >= 0x20000;

    if(supportsEs2){
        // Request an OpenGL ES 2.0 compatible context
        mGLSurfaceView.setEGLContextClientVersion(2);

        // Set the renderer to our demo renderer, defined below
        mGLSurfaceView.setRenderer(new GoogleMapsRenderer(getActivity()));
        rendererSet = true;
    } else {
        // This is where you could create an OpenGL ES1.x compatible
        // renderer if you wanted to support both ES 1 and ES 2
        Log.d("Does Not Support ES 2.0", "Does NOT Support ES 2.0");
    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v;

    v = inflater.inflate(R.layout.fragment_maps_ogl, container, false);

    mGLSurfaceView = (GLSurfaceView) v.findViewById(R.id.ogl);
    mGLSurfaceView.setEGLContextClientVersion(2);
    GoogleMapsRenderer renderer = new GoogleMapsRenderer(getActivity());

    mGLSurfaceView.setZOrderOnTop(true);
    mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
    mGLSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
    mGLSurfaceView.setRenderer(renderer);
    rendererSet = true;
    mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);

    return v;
}

google_maps_tracker.xml google_maps_tracker.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >

<fragment
    android:id="@+id/map"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="com.example.tracker.GoogleMapsTracker"
    class="com.example.tracker.GoogleMapsTracker"/>

<fragment
    android:id="@+id/gl"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="com.example.tracker.GoogleMapsOGLES"
    class="com.example.tracker.GoogleMapsOGLES"/>

</RelativeLayout>

The fragments within the xml file had their own xml files that just initialized the MapView and GLSurfaceView. xml文件中的片段具有自己的xml文件,这些文件只是初始化了MapView和GLSurfaceView。

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

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