【问题标题】:GLSurfaceView not appearing over MapViewGLSurfaceView 没有出现在 MapView 上
【发布时间】:2015-08-04 19:49:45
【问题描述】:

我的目标是将 OpenGL ES 2.0 与 Google 地图一起使用。我想创建一个应用程序,跟随用户从 A 点到 B 点旅行。我意识到这可以使用 Google Maps addPolyline 来绘制一条线,但我想使用 OpenGL 来显示重叠的路径。我目前收到一个错误,这是由于 GLSurfaceView 设置不正确造成的。

我在 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;
}

我的 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>

我收到的错误如下:

    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)

我很确定我没有正确地将我的观点加在一起。如果有人能指出我的错误以及实现这个想法的更好方法,将不胜感激。

【问题讨论】:

    标签: android android-layout opengl-es opengl-es-2.0 glsurfaceview


    【解决方案1】:

    我找到了解决问题的方法。只是不确定是否有更好的方法。

    基本上,我所做的只是将两个视图(MapView 和 GLSurfaceView)分成两个不同的片段。然后用一个Activity类来调用这两个Fragment。 XML 文件的片段覆盖相同的区域。下面是我更新的代码。

    谷歌地图活动:

    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(); 
    }
    

    }

    谷歌地图追踪器:

    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:

    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

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

    xml 文件中的片段有自己的 xml 文件,它们只是初始化了 MapView 和 GLSurfaceView。

    【讨论】:

      猜你喜欢
      • 2015-10-19
      • 1970-01-01
      • 1970-01-01
      • 2018-04-23
      • 1970-01-01
      • 1970-01-01
      • 2016-12-14
      • 2018-01-08
      • 2021-02-02
      相关资源
      最近更新 更多