Android高德地图开发(三)地图简单操作

一、概述

上一节中我们了解到地图的定位,图层切换,离线地图等基础操作,接下来学习地图的基本操作。

二、本章内容

--- 地图交互设置
--- 地图绘制

1.地图交互设置
在使用地图的时候,不可避免的会涉及到与地图交互问题,如滑动手势,地图缩放,地图旋转,地图logo位置等。我们可以根据需要来决定是否开启某些交互功能。主要用到的就是高德地图API中的 UiSettings 类。通过AMap实例可以获取到UiSettings的实例 uiSettings = aMap.getUiSettings();
①手势设置

        //开启放缩手势
        uiSettings.setZoomGesturesEnabled(true);
        //开启滑动手势
        uiSettings.setScrollGesturesEnabled(true);
        //开启旋转手势
        uiSettings.setRotateGesturesEnabled(true);
        //开启双指倾斜手势
        uiSettings.setTiltGesturesEnabled(true);
        //开启全部手势
        uiSettings.setAllGesturesEnabled(true);
        //指定手势中心点
        //aMap.setPointToCenter(100,100);
        //开启中心为手势中心
        uiSettings.setGestureScaleByMapCenter(true);

上面这些功能在一般情况下,默认是开启的。当我们有特殊的需求时可以适当的关闭某些手势。
②地图缩放

        //是否允许显示地图缩放按钮
        uiSettings.setZoomControlsEnabled(true);
        //是否允许收拾手势缩放地图
        uiSettings.setZoomGesturesEnabled(true);
        //设置双击地图放大在地图中心位置放大,false则是在点击位置放大
        uiSettings.setZoomInByScreenCenter(true);
        //地图缩放按钮的位置
        uiSettings.setZoomPosition(AMapOptions.ZOOM_POSITION_RIGHT_BUTTOM);
        //AMapOptions.ZOOM_POSITION_RIGHT_CENTER
       //AMapOptions.ZOOM_POSITION_RIGHT_BUTTOM
       //获取地图缩放按钮位置
        Log.e(TAG, "settingZoom: " + uiSettings.getZoomPosition());

③将屏幕中心移动到指定经纬度

      //这个类就是设置地图移动的参数,CameraPosition,参数1---要移动到的经纬度,
      //参数2---地图的放缩级别zoom,参数3---地图倾斜度,参数4---地图的旋转角度
        CameraUpdate mCameraUpdate = CameraUpdateFactory.newCameraPosition(
                new CameraPosition(new LatLng(30.67, 104.07), 10, 0, 0));
        //带动画的移动,aMap添加动画监听时,会有动画效果。不添加不会开启动画
        aMap.animateCamera(mCameraUpdate, 5000, new AMap.CancelableCallback() {
            @Override
            public void onFinish() {
            }

            @Override
            public void onCancel() {
            }
        });

        //不带动画的移动
        aMap.moveCamera(mCameraUpdate);

④其他设置

        //是否显示指南针
        uiSettings.setCompassEnabled(true);
        //开启比例尺
        uiSettings.setScaleControlsEnabled(true);
        //  设置logo位置
        uiSettings.setLogoPosition(AMapOptions.LOGO_POSITION_BOTTOM_CENTER);
        //AMapOptions.LOGO_POSITION_BOTTOM_LEFTLOGO(左边)
        //AMapOptions.LOGO_MARGIN_BOTTOMLOGO(底部)
        //AMapOptions.LOGO_MARGIN_RIGHTLOGO(右边)
        //AMapOptions.LOGO_POSITION_BOTTOM_CENTER(地图底部居中)
        //AMapOptions.LOGO_POSITION_BOTTOM_LEFT(地图左下角)
        //AMapOptions.LOGO_POSITION_BOTTOM_RIGHT (地图右下角)
        //显示默认的定位按钮
        uiSettings.setMyLocationButtonEnabled(true);

        // 可触发定位并显示当前位置
        aMap.setMyLocationEnabled(true);

        //这里设置定位为了在点击定位按钮后,显示地图定位的位置方便查看
        //注意这里有个坑,在点击定位后发现定位到了默认的位置(海里面),造成这种情况并不是权限和代码的问题,
        //遇到这种情况时,需要手动将GPS定位打开就OK了
        MyLocationStyle mls = new MyLocationStyle();
        mls.myLocationType(MyLocationStyle.LOCATION_TYPE_SHOW);
        aMap.setMyLocationEnabled(true);
        aMap.setMyLocationStyle(mls);

代码

public class InteractiveMapActivity extends BaseActivity {
    @BindView(R.id.a_map_view)
    MapView aMapView;
    @BindView(R.id.button)
    Button button;
    @BindView(R.id.button2)
    Button button2;
    @BindView(R.id.button3)
    Button button3;
    @BindView(R.id.button4)
    Button button4;
    private Unbinder binder;

    private UiSettings uiSettings;
    private AMap aMap;

    private static final String TAG = "CF";

    @Override
    public void setContentView(@Nullable Bundle savedInstanceState) {
        setContentView(R.layout.acticity_interactive);
        binder = ButterKnife.bind(this);

        aMapView.onCreate(savedInstanceState);
    }

    @Override
    public void initData() {
        aMap = aMapView.getMap();
        uiSettings = aMap.getUiSettings();

        //设置地图缩放
        settingZoom();

        //是否显示指南针
        uiSettings.setCompassEnabled(true);
        //开启比例尺
        uiSettings.setScaleControlsEnabled(true);
        //  设置logo位置
        uiSettings.setLogoPosition(AMapOptions.LOGO_POSITION_BOTTOM_CENTER);
        //AMapOptions.LOGO_POSITION_BOTTOM_LEFTLOGO(左边)
        //AMapOptions.LOGO_MARGIN_BOTTOMLOGO(底部)
        //AMapOptions.LOGO_MARGIN_RIGHTLOGO(右边)
        //AMapOptions.LOGO_POSITION_BOTTOM_CENTER(地图底部居中)
        //AMapOptions.LOGO_POSITION_BOTTOM_LEFT(地图左下角)
        //AMapOptions.LOGO_POSITION_BOTTOM_RIGHT (地图右下角)
        //显示默认的定位按钮
        uiSettings.setMyLocationButtonEnabled(true);

        // 可触发定位并显示当前位置
        aMap.setMyLocationEnabled(true);

        //这里设置定位为了在点击定位按钮后,显示地图定位的位置方便查看
        //注意这里有个坑,在点击定位后发现定位到了默认的位置(海里面),造成这种情况并不是权限和代码的问题,
        //遇到这种情况时,需要手动将GPS定位打开就OK了
        MyLocationStyle mls = new MyLocationStyle();
        mls.myLocationType(MyLocationStyle.LOCATION_TYPE_SHOW);
        aMap.setMyLocationEnabled(true);
        aMap.setMyLocationStyle(mls);


        setGestures();
    }

    private void setGestures() {

        //开启放缩手势
        uiSettings.setZoomGesturesEnabled(true);
        //开启滑动手势
        uiSettings.setScrollGesturesEnabled(true);
        //开启旋转手势
        uiSettings.setRotateGesturesEnabled(true);
        //开启双指倾斜手势
        uiSettings.setTiltGesturesEnabled(true);
        //开启全部手势
        uiSettings.setAllGesturesEnabled(true);


        //指定手势中心点
//        aMap.setPointToCenter(100,100);

        //开启中心为手势中心
        uiSettings.setGestureScaleByMapCenter(true);
    }


    private void settingZoom() {

        //是否允许显示地图缩放按钮
        uiSettings.setZoomControlsEnabled(true);
        //是否允许收拾手势缩放地图
        uiSettings.setZoomGesturesEnabled(true);
        //设置双击地图放大在地图中心位置放大,false则是在点击位置放大
        uiSettings.setZoomInByScreenCenter(true);
        //地图缩放按钮的位置
        uiSettings.setZoomPosition(AMapOptions.ZOOM_POSITION_RIGHT_BUTTOM);
//        AMapOptions.ZOOM_POSITION_RIGHT_CENTER
//        AMapOptions.ZOOM_POSITION_RIGHT_BUTTOM
        //获取地图缩放按钮位置
        Log.e(TAG, "settingZoom: " + uiSettings.getZoomPosition());
    }

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

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

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

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

    @Override
    protected void onDestroy() {

        aMapView.onDestroy();
        binder.unbind();
        super.onDestroy();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        aMapView.onSaveInstanceState(outState);
    }

    private void moveToTargetPosition() {

        //这个类就是设置地图移动的参数,CameraPosition,参数1---要移动到的经纬度,参数2---地图的放缩级别zoom,参数3---地图倾斜度,参数4---地图的旋转角度
        CameraUpdate mCameraUpdate = CameraUpdateFactory.newCameraPosition(
                new CameraPosition(new LatLng(30.67, 104.07), 10, 0, 0));
        //带动画的移动
        aMap.animateCamera(mCameraUpdate, 5000, new AMap.CancelableCallback() {
            @Override
            public void onFinish() {

            }

            @Override
            public void onCancel() {

            }
        });

        //不带动画的移动
        aMap.moveCamera(mCameraUpdate);

    }

    @OnClick({R.id.button, R.id.button2, R.id.button3, R.id.button4})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.button:
                moveToTargetPosition();
                break;
            case R.id.button2:
                showCustomMapBounds(true);
                break;
            case R.id.button3:
                showCustomMapBounds(false);
                break;
            case R.id.button4:
                screenCapture();
                break;
        }
    }

    private void showCustomMapBounds(boolean enable) {

        if (enable) {
            LatLng southwestLatLng = new LatLng(30.67, 104.07);
            LatLng northeastLatLng = new LatLng(30.77, 104.17);
            LatLngBounds latLngBounds = new LatLngBounds(southwestLatLng, northeastLatLng);

            aMap.setMapStatusLimits(latLngBounds);
        } else {
            aMap.setMapStatusLimits(null);
        }

    }
    /** 地图截屏 */
    private void screenCapture() {
        aMap.getMapScreenShot(new AMap.OnMapScreenShotListener() {
            @Override
            public void onMapScreenShot(Bitmap bitmap) {

            }

            @Override
            public void onMapScreenShot(Bitmap bitmap, int i) {
                if (null == bitmap) {
                    return;
                }
                try {
                    FileOutputStream fos = new FileOutputStream(
                            Environment.getExternalStorageDirectory() + "/MyMap/"
                                    + "test" + ".png");
                    boolean b = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
                    try {
                        fos.flush();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    StringBuffer buffer = new StringBuffer();
                    if (b)
                        buffer.append("截屏成功 ");
                    else {
                        buffer.append("截屏失败 ");
                    }
                    if (i != 0)
                        buffer.append("地图渲染完成,截屏无网格");
                    else {
                        buffer.append("地图未渲染完成,截屏有网格");
                    }
                    Toast.makeText(InteractiveMapActivity.this, buffer.toString(), Toast.LENGTH_SHORT).show();

                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }

            }
        });
    }
}

2.地图绘制
①绘制marker

       //添加一个默认的marker
        LatLng latLng = new LatLng(30.67, 104.07);
        MarkerOptions markerOptions = new MarkerOptions()
                //必须,设置经纬度
                .position(latLng)
                //设置title
                .title("成都")
                //设置内容
                .snippet("marker内容");

        aMap.addMarker(markerOptions);

        //添加一个自定义的marker
        LatLng latLng1 = new LatLng(30.67, 104.07);
        MarkerOptions mo = new MarkerOptions();
        mo.position(latLng1)
                //设置透明度
                .alpha(0.6f)
                //设置title
                .title("自定义标题")
                //设置内容
                .snippet("自定义内容")
                //设置锚点,锚点是marker图标的位置,(0,0)-(1,1)
                .anchor(0.5f, 1.0f)
                //是否可见
                .visible(true)
                //是否可拖动,注意这里需要长按marker后,才可以拖动
                .draggable(true)
                //添加自定义marker图标
                .icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(
                      getResources(), R.drawable.location)))
                //是否平贴地图,倾斜地图,感觉marker不是竖直而是粘贴在地面上
                .setFlat(false)
                //是否允许显示infoWindow
                .infoWindowEnable(true)
                //z轴方向的值,重叠
                .zIndex(10)
                //设置marker图片旋转角度,正北开始逆时针方向计算
                .rotateAngle(30.0f)
                //设置infoWindow的偏移位置
                .setInfoWindowOffset(0, 0);
        aMap.addMarker(mo);


        //添加一个动画marker
        LatLng latLng2 = new LatLng(30.68, 104.07);
        MarkerOptions mo1 = new MarkerOptions().icon(BitmapDescriptorFactory.fromBitmap(
          BitmapFactory.decodeResource(getResources(), R.drawable.location)))
                .title("动画").snippet("生长动画").position(latLng2);
        Marker m = aMap.addMarker(mo1);

        final Animation animation = new ScaleAnimation(0, 1, 0, 1);
        animation.setDuration(2000);
        animation.setInterpolator(new AccelerateInterpolator());

        m.setAnimation(animation);
        m.startAnimation();

        //添加一个marker的点击事件
        aMap.setOnMarkerClickListener(new AMap.OnMarkerClickListener() {
            @Override
            public boolean onMarkerClick(Marker marker) {

                //当点击的时候添加生长动画
                marker.setAnimation(animation);
                marker.startAnimation();

                //这里在添加点击监听事件后,原来的InfoWindow被取消了,可以在回调方法中手动实现
                if (marker.isInfoWindowShown()) {
                    marker.hideInfoWindow();
                } else {
                    marker.showInfoWindow();
                }

                return true;
            }
        });

        //添加拖拽事件,注意此回调方法只对设置了可拖拽的marker生效
        aMap.setOnMarkerDragListener(new AMap.OnMarkerDragListener() {
            @Override
            public void onMarkerDragStart(Marker marker) {
                Log.e(TAG, "onMarkerDragStart: 被拖拽的Marker标题为->" + marker.getTitle());
            }

            @Override
            public void onMarkerDrag(Marker marker) {

            }

            @Override
            public void onMarkerDragEnd(Marker marker) {

                Log.e(TAG, "onMarkerDragEnd: 拖拽完后Maker的经纬度-> lat=" 
                +marker.getPosition().latitude + " lng=" + marker.getPosition().longitude);


            }
        });

        //自定义infoWindow
        aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() {

            View view;

            @Override
            public View getInfoWindow(Marker marker) {

                if (view == null) {
                    view = LayoutInflater.from(DrawActivity.this).inflate(R.layout.custom_info_window, null);
                }

                findViews(marker, view);
                return view;
            }

            @Override
            public View getInfoContents(Marker marker) {
                return null;
            }
        });

        aMap.setOnInfoWindowClickListener(new AMap.OnInfoWindowClickListener() {
            @Override
            public void onInfoWindowClick(Marker marker) {

                Log.e(TAG, "onInfoWindowClick: 标题为:" + marker.getTitle() + "  的InfoWindow被点击了");
            }
        });

    /**
     * 在点击marker显示infoWindow是,找到相应的控件,修改显示
     */
    private void findViews(Marker marker, View view) {

        TextView name = view.findViewById(R.id.name);
        TextView address = view.findViewById(R.id.address);

        name.setText(marker.getTitle());
        address.setText(marker.getSnippet());
    }

②绘制线

        ArrayList<LatLng> points = new ArrayList<>();
        points.add(new LatLng(30.66, 104.06));
        points.add(new LatLng(30.66, 104.07));
        points.add(new LatLng(30.67, 104.07));
        points.add(new LatLng(30.67, 104.06));
        points.add(new LatLng(30.66, 104.06));
        aMap.addPolyline(new PolylineOptions().addAll(points).width(10).color(Color.argb(255, 1, 1, 1)));

        ArrayList<LatLng> latlngs = new ArrayList<>();
        latlngs.add(new LatLng(30.6595, 104.0595));
        latlngs.add(new LatLng(30.6595, 104.0705));
        latlngs.add(new LatLng(30.6705, 104.0705));
        latlngs.add(new LatLng(30.6705, 104.0595));
        latlngs.add(new LatLng(30.6595, 104.0595));


        ArrayList<Integer> a = new ArrayList<>();
        a.add(0);
        a.add(1);
        a.add(2);
        a.add(3);
        //为每条线段添加纹理
        ArrayList<BitmapDescriptor> b = new ArrayList<>();
        b.add(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.bb)));
        b.add(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.aa)));
        b.add(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.bb)));
        b.add(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.aa)));

        aMap.addPolyline(new PolylineOptions()
                //添加多有的经纬度点
                .addAll(latlngs)
                //绘制线宽
                .width(20)
                //是否开启纹理贴图
                .setUseTexture(true)
                //纹理贴图段的index数组
                .setCustomTextureIndex(a)
                //纹理贴图每段对应的纹理资源图
                .setCustomTextureList(b)
                //是否虚线,纹理贴图时无效
                .setDottedLine(false)
                //绘制成大地线
                .geodesic(false)
                //设置纹理样式
                .setCustomTexture(BitmapDescriptorFactory.fromBitmap(
                      BitmapFactory.decodeResource(getResources(), R.drawable.aa)))
                //设置画线的颜色
                .color(Color.argb(255, 1, 1, 1))
        );

③绘制面

        LatLng latLng = new LatLng(30.665, 104.065);

        //绘制一个圆
        Circle circle = aMap.addCircle(new CircleOptions()
                .center(latLng)
                .radius(500)
                .fillColor(Color.argb(30, 1, 1, 1))
                .strokeColor(Color.argb(255, 1, 1, 1))
                .strokeWidth(10)
        );

        circle.setStrokeDottedLineType(0);


//        //绘制一个矩形,多边形跟这个一样的
//        aMap.addPolygon(new PolygonOptions()
//                .addAll(createRectangle(new LatLng(30.665, 104.065), 0.01, 0.01))
//                .fillColor(Color.LTGRAY).strokeColor(Color.RED).strokeWidth(5));
//
//        // 绘制一个椭圆
//        PolygonOptions options = new PolygonOptions();
//        int numPoints = 400;
//        float semiHorizontalAxis = 2f;
//        float semiVerticalAxis = 0.5f;
//        double phase = 2 * Math.PI / numPoints;
//        for (int i = 0; i <= numPoints; i++) {
//            options.add(new LatLng(
//                    30.665 + semiVerticalAxis * Math.sin(i * phase),
//                    104.065 + semiHorizontalAxis * Math.cos(i * phase)
//            ));
//        }
//
//        Polygon polygon = aMap.addPolygon(options
//                .strokeWidth(25)
//                .strokeColor(Color.argb(50, 1, 1, 1))
//                .fillColor(Color.argb(50, 1, 1, 1))
//        );



    /**
     * 生成一个长方形的四个坐标点
     */
    private List<LatLng> createRectangle(LatLng center, double halfWidth,
                                         double halfHeight) {
        List<LatLng> latLngs = new ArrayList<LatLng>();
        latLngs.add(new LatLng(center.latitude - halfHeight, center.longitude - halfWidth));
        latLngs.add(new LatLng(center.latitude - halfHeight, center.longitude + halfWidth));
        latLngs.add(new LatLng(center.latitude + halfHeight, center.longitude + halfWidth));
        latLngs.add(new LatLng(center.latitude + halfHeight, center.longitude - halfWidth));
        return latLngs;
    }

④绘制热力图

 LatLng center = new LatLng(30.665, 104.065);

        //第一步准备数据
        LatLng[] data = new LatLng[100];

        for (int i = 0; i < data.length; i++) {

            double offsetLat = Math.random();
            offsetLat /= 10;

            double offsetLng = Math.random();
            offsetLng /= 10;
            LatLng one = new LatLng(center.latitude + offsetLat, center.longitude + offsetLng);
            data[i] = one;
        }

        int[] colors = {Color.rgb(0, 255, 0), Color.rgb(255, 0, 0)};
        float[] startPoints = {0.0f, 1.0f};

        Gradient gradient = new Gradient(colors, startPoints);

        //初始化热力图
        HeatmapTileProvider.Builder builder = new HeatmapTileProvider.Builder();
        builder.data(Arrays.asList(data))
//                .gradient(gradient)
        ;

        HeatmapTileProvider provider = builder.build();


        // 初始化 TileOverlayOptions
        TileOverlayOptions tileOverlayOptions = new TileOverlayOptions();
        // 设置瓦片图层的提供者
        tileOverlayOptions.tileProvider(provider);
        // 向地图上添加 TileOverlayOptions 类对象
        aMap.addTileOverlay(tileOverlayOptions);

⑤绘制长方体

/**------------------------------------地图上绘制3D图形------------------------------*/
        aMap.showMapText(false);
        aMap.showBuildings(false);
        aMap.setCustomRenderer(new CubeMapRender(aMap));
/**------------------------------------地图上绘制3D图形-----------------------------*/

public class CubeMapRender implements CustomRenderer {

    private float[] translate_vector = new float[4];
    public static float SCALE = 0.005F;// 缩放暂时使用这个

    private LatLng center = new LatLng(30.665, 104.065);// 北京市经纬度

    private Cube cube ;

    private AMap aMap;

    float width, height;

    public CubeMapRender(AMap aMap) {
        this.aMap = aMap;

        aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(center,15));
    }

    float[] mvp = new float[16];

    @Override
    public void onDrawFrame(GL10 gl) {

        if(cube != null) {
            Matrix.setIdentityM(mvp, 0);

            //偏移
            PointF pointF = aMap.getProjection().toOpenGLLocation(center);

            Matrix.multiplyMM(mvp,0, aMap.getProjectionMatrix(),0,aMap.getViewMatrix(),0);

            Matrix.translateM(mvp, 0 , pointF.x , pointF.y  , 0);
            int scale = 1;
            Matrix.scaleM(mvp, 0 , scale, scale, scale);

            cube.drawES20(mvp);
        }

    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        //创建cube
        cube = new Cube(0.2f,0.2f,0.2f);
        cube.initShader();
    }

    @Override
    public void OnMapReferencechanged() {

    }

}

class Cube {
    ArrayList<Float> verticesList = new ArrayList<Float>();

    short indices[] = {
            0, 4, 5,
            0, 5, 1,
            1, 5, 6,
            1, 6, 2,
            2, 6, 7,
            2, 7, 3,
            3, 7, 4,
            3, 4, 0,
            4, 7, 6,
            4, 6, 5,
            3, 0, 1,
            3, 1, 2,
    };

    //
    float[] colors = {
            1f, 0f, 0f, 1f, // vertex 0 red
            0f, 1f, 0f, 1f, // vertex 1 green
            0f, 0f, 1f, 1f, // vertex 2 blue
            1f, 1f, 0f, 1f, // vertex 3
            0f, 1f, 1f, 1f, // vertex 4
            1f, 0f, 1f, 1f, // vertex 5
            0f, 0f, 0f, 1f, // vertex 6
            1f, 1f, 1f, 1f, // vertex 7
    };

    public Cube(float width, float height, float depth) {

        // 地图坐标系比较大,将值放大以免太小看不见
        width *= 10000;
        height *= 10000;
        depth *= 10000;


        width /= 2;
        height /= 2;
        depth /= 2;

        //尽量不要让z轴有负数出现
        float vertices1[] = {
                -width, -height, -0,
                width, -height, -0,
                width, height, -0,
                -width, height, -0,
                -width, -height, depth,
                width, -height, depth,
                width, height, depth,
                -width, height, depth,
        };

        for (int i = 0; i < vertices1.length; i++) {
            verticesList.add(vertices1[i]);
        }

        //index
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(indices.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());
        indexBuffer = byteBuffer.asShortBuffer();
        indexBuffer.put(indices);
        indexBuffer.position(0);


        //color
        ByteBuffer byteBuffer1 = ByteBuffer.allocateDirect(colors.length * 4);
        byteBuffer1.order(ByteOrder.nativeOrder());
        colorBuffer = byteBuffer1.asFloatBuffer();
        colorBuffer.put(colors);
        colorBuffer.position(0);

        init();

    }


    private FloatBuffer vertextBuffer;
    private ShortBuffer indexBuffer;
    private FloatBuffer colorBuffer;

    private void init() {
        if (vertextBuffer == null) {
            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(verticesList.size() * 4);
            byteBuffer.order(ByteOrder.nativeOrder());
            vertextBuffer = byteBuffer.asFloatBuffer();
        }
        vertextBuffer.clear();
        for (Float f : verticesList) {
            vertextBuffer.put(f);
        }
        vertextBuffer.position(0);
    }


    class MyShader {
        String vertexShader = "precision highp float;\n" +
                "        attribute vec3 aVertex;//顶点数组,三维坐标\n" +
                "        attribute vec4 aColor;//颜色数组,三维坐标\n" +
                "        uniform mat4 aMVPMatrix;//mvp矩阵\n" +
                "        varying vec4 color;//\n" +
                "        void main(){\n" +
                "            gl_Position = aMVPMatrix * vec4(aVertex, 1.0);\n" +
                "            color = aColor;\n" +
                "        }";

        String fragmentShader = "//有颜色 没有纹理\n" +
                "        precision highp float;\n" +
                "        varying vec4 color;//\n" +
                "        void main(){\n" +
                "            gl_FragColor = color;\n" +
                "        }";

        int aVertex,aMVPMatrix,aColor;
        int program;

        public void create() {
            int vertexLocation = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
            int fragmentLocation = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);

            GLES20.glShaderSource(vertexLocation,vertexShader);
            GLES20.glCompileShader(vertexLocation);

            GLES20.glShaderSource(fragmentLocation,fragmentShader);
            GLES20.glCompileShader(fragmentLocation);

            program = GLES20.glCreateProgram();
            GLES20.glAttachShader(program,vertexLocation);
            GLES20.glAttachShader(program,fragmentLocation);
            GLES20.glLinkProgram(program);


            aVertex  = GLES20.glGetAttribLocation(program, "aVertex");
            aMVPMatrix = GLES20.glGetUniformLocation(program,"aMVPMatrix");
            aColor = GLES20.glGetAttribLocation(program,"aColor");

        }
    }

    MyShader shader;

    public void initShader() {
        shader = new MyShader();
        shader.create();
    }

    public void drawES20(float[] mvp) {

        GLES20.glUseProgram(shader.program);

        GLES20.glEnable(GLES20.GL_DEPTH_TEST);
        GLES20.glEnableVertexAttribArray(shader.aVertex);

        //顶点指针
        GLES20.glVertexAttribPointer(shader.aVertex, 3, GLES20.GL_FLOAT, false, 0, vertextBuffer);

        //颜色指针
        GLES20.glEnableVertexAttribArray(shader.aColor);
        GLES20.glVertexAttribPointer(shader.aColor,4, GLES20.GL_FLOAT,false,0,colorBuffer);

        GLES20.glUniformMatrix4fv(shader.aMVPMatrix,1,false,mvp,0);

        //开始画
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_SHORT, indexBuffer);
        GLES20.glDisableVertexAttribArray(shader.aVertex);

        GLES20.glDisable(GLES20.GL_DEPTH_TEST);


    }

}

⑥绘制平滑移动的物体

      //这里选择一个公交站,获取经过改公交站的一路公交车的路线
        //让小车再这个路线上移动
        
        BusStationQuery bsq;
        BusStationSearch bss;
        bsq = new BusStationQuery("天华一路", "成都");

        bss = new BusStationSearch(this, bsq);
        bss.setOnBusStationSearchListener(new BusStationSearch.OnBusStationSearchListener() {
            @Override
            public void onBusStationSearched(BusStationResult busStationResult, int i) {

                List<BusStationItem> data = busStationResult.getBusStations();
                if (data != null && data.size() > 0) {

                    final LatLonPoint busStationPoint = data.get(0).getLatLonPoint();
                    List<BusLineItem> dataBus = data.get(0).getBusLineItems();
                    if (dataBus != null && dataBus.size() > 0) {

                        BusLineItem bli = dataBus.get(0);

                        BusLineQuery blq = new BusLineQuery(
                        bli.getBusLineId(), BusLineQuery.SearchType.BY_LINE_ID, bli.getCityCode());
                        blq.setPageSize(10);
                        blq.setPageNumber(1);

                        BusLineSearch busLineSearch = new BusLineSearch(getApplicationContext(), blq);
                        busLineSearch.setOnBusLineSearchListener(new BusLineSearch.OnBusLineSearchListener() {
                            @Override
                            public void onBusLineSearched(BusLineResult busLineResult, int i) {

                                List<LatLonPoint> d = busLineResult.getBusLines().get(0).getDirectionsCoordinates();
                                List<LatLng> driverPath = new ArrayList<>();
                                for (LatLonPoint one : d) {
                                    driverPath.add(new LatLng(one.getLatitude(), one.getLongitude()));
                                }

                                moveToPosition(busStationPoint.getLatitude(), busStationPoint.getLongitude());

                                aMap.addPolyline(new PolylineOptions()
                                        .addAll(driverPath)
                                        .width(20)
                                        //是否开启纹理贴图
                                        .setUseTexture(true)
                                        //绘制成大地线
                                        .geodesic(false)
                                        //设置纹理样式
                                        .setCustomTexture(BitmapDescriptorFactory.fromBitmap(
                                                  BitmapFactory.decodeResource(getResources(), 
                                        R.drawable.custtexture)))
                                        //设置画线的颜色
                                        .color(Color.argb(200, 0, 0, 0)));

                                final SmoothMoveMarker smoothMarker = new SmoothMoveMarker(aMap);
                                // 设置滑动的图标
                                smoothMarker.setDescriptor(BitmapDescriptorFactory.fromResource(
                                                  R.mipmap.icon_car));
                                // 设置滑动的轨迹左边点
                                smoothMarker.setPoints(driverPath);
                                // 设置滑动的总时间
                                smoothMarker.setTotalDuration(30);
                                // 开始滑动
                                smoothMarker.startSmoothMove();
                            }
                        });

                        busLineSearch.searchBusLineAsyn();
                    }

                } else {
                    Log.e(TAG, "onBusStationSearched: no data");
                }
                Log.e(TAG, "onBusStationSearched: " + i);
            }
        });
        bss.searchBusStationAsyn();

绘制的代码

public class DrawActivity extends BaseActivity {

    private static final String TAG = "CF";
    @BindView(R.id.draw_map_view)
    MapView drawMapView;
    private Unbinder binder;

    private AMap aMap;

    @Override
    public void setContentView(@Nullable Bundle savedInstanceState) {

        setContentView(R.layout.activity_draw_map);

        binder = ButterKnife.bind(this);

        drawMapView.onCreate(savedInstanceState);
        aMap = drawMapView.getMap();
    }

    @Override
    public void initData() {

        //绘制Marker
//        drawMarker();

        //绘制线段
//        drawLine();

        //绘制面
//        drawSurface();

        //绘制热力图
        drawThermodynamic();


        //绘制3D模型
        draw3DModel();

//        drawSmoothMove();
    }

    //绘制平滑移动
    private void drawSmoothMove() {

        //这里选择一个公交站,获取经过改公交站的一路公交车的路线
        //让小车再这个路线上移动

        BusStationQuery bsq;
        BusStationSearch bss;
        bsq = new BusStationQuery("天华一路", "成都");

        bss = new BusStationSearch(this, bsq);
        bss.setOnBusStationSearchListener(new BusStationSearch.OnBusStationSearchListener() {
            @Override
            public void onBusStationSearched(BusStationResult busStationResult, int i) {

                List<BusStationItem> data = busStationResult.getBusStations();
                if (data != null && data.size() > 0) {

                    final LatLonPoint busStationPoint = data.get(0).getLatLonPoint();
                    List<BusLineItem> dataBus = data.get(0).getBusLineItems();
                    if (dataBus != null && dataBus.size() > 0) {

                        BusLineItem bli = dataBus.get(0);

                        BusLineQuery blq = new BusLineQuery(bli.getBusLineId(), BusLineQuery.SearchType.BY_LINE_ID, bli.getCityCode());
                        blq.setPageSize(10);
                        blq.setPageNumber(1);

                        BusLineSearch busLineSearch = new BusLineSearch(getApplicationContext(), blq);
                        busLineSearch.setOnBusLineSearchListener(new BusLineSearch.OnBusLineSearchListener() {
                            @Override
                            public void onBusLineSearched(BusLineResult busLineResult, int i) {

                                List<LatLonPoint> d = busLineResult.getBusLines().get(0).getDirectionsCoordinates();
                                List<LatLng> driverPath = new ArrayList<>();
                                for (LatLonPoint one : d) {
                                    driverPath.add(new LatLng(one.getLatitude(), one.getLongitude()));
                                }

                                moveToPosition(busStationPoint.getLatitude(), busStationPoint.getLongitude());

                                aMap.addPolyline(new PolylineOptions()
                                        .addAll(driverPath)
                                        .width(20)
                                        //是否开启纹理贴图
                                        .setUseTexture(true)
                                        //绘制成大地线
                                        .geodesic(false)
                                        //设置纹理样式
                                        .setCustomTexture(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.custtexture)))
                                        //设置画线的颜色
                                        .color(Color.argb(200, 0, 0, 0)));

                                final SmoothMoveMarker smoothMarker = new SmoothMoveMarker(aMap);
                                // 设置滑动的图标
                                smoothMarker.setDescriptor(BitmapDescriptorFactory.fromResource(R.mipmap.icon_car));
                                // 设置滑动的轨迹左边点
                                smoothMarker.setPoints(driverPath);
                                // 设置滑动的总时间
                                smoothMarker.setTotalDuration(30);
                                // 开始滑动
                                smoothMarker.startSmoothMove();
                            }
                        });

                        busLineSearch.searchBusLineAsyn();
                    }

                } else {
                    Log.e(TAG, "onBusStationSearched: no data");
                }
                Log.e(TAG, "onBusStationSearched: " + i);
            }
        });
        bss.searchBusStationAsyn();
    }

    private void draw3DModel() {

        moveToDefaultPosition();

        aMap.showMapText(false);
        aMap.showBuildings(false);
        aMap.setCustomRenderer(new CubeMapRender(aMap));
    }


    /**
     * ----------------------------------------热力图---------------------------------------------------------
     */
    private void drawThermodynamic() {


        moveToDefaultPosition();

        LatLng center = new LatLng(30.665, 104.065);

        //第一步准备数据
        LatLng[] data = new LatLng[100];

        for (int i = 0; i < data.length; i++) {

            double offsetLat = Math.random();
            offsetLat /= 10;

            double offsetLng = Math.random();
            offsetLng /= 10;
            LatLng one = new LatLng(center.latitude + offsetLat, center.longitude + offsetLng);
            data[i] = one;
        }

        int[] colors = {Color.rgb(0, 255, 0), Color.rgb(255, 0, 0)};
        float[] startPoints = {0.0f, 1.0f};

        Gradient gradient = new Gradient(colors, startPoints);

        //初始化热力图
        HeatmapTileProvider.Builder builder = new HeatmapTileProvider.Builder();
        builder.data(Arrays.asList(data))
//                .gradient(gradient)
        ;

        HeatmapTileProvider provider = builder.build();


        // 初始化 TileOverlayOptions
        TileOverlayOptions tileOverlayOptions = new TileOverlayOptions();
        // 设置瓦片图层的提供者
        tileOverlayOptions.tileProvider(provider);
        // 向地图上添加 TileOverlayOptions 类对象
        aMap.addTileOverlay(tileOverlayOptions);

    }
    /**
     * ----------------------------------------热力图---------------------------------------------------------
     * */


    /**
     * -----------------------------------------Marker相关----------------------------------------------------
     * */
    /**
     * 地图上marker相关
     */
    private void drawMarker() {

        //添加一个默认的marker
        LatLng latLng = new LatLng(30.67, 104.07);
        MarkerOptions markerOptions = new MarkerOptions()
                //必须,设置经纬度
                .position(latLng)
                //设置title
                .title("成都")
                //设置内容
                .snippet("marker内容");

        aMap.addMarker(markerOptions);


        //添加一个自定义的marker
        LatLng latLng1 = new LatLng(30.67, 104.07);
        MarkerOptions mo = new MarkerOptions();
        mo.position(latLng1)
                //设置透明度
                .alpha(0.6f)
                //设置title
                .title("自定义标题")
                //设置内容
                .snippet("自定义内容")
                //设置锚点,锚点是marker图标的位置,(0,0)-(1,1)
                .anchor(0.5f, 1.0f)
                //是否可见
                .visible(true)
                //是否可拖动,注意这里需要长按marker后,才可以拖动
                .draggable(true)
                //添加自定义marker图标
                .icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.location)))
                //是否平贴地图,倾斜地图,感觉marker不是竖直而是粘贴在地面上
                .setFlat(false)
                //是否允许显示infoWindow
                .infoWindowEnable(true)
                //z轴方向的值,重叠
                .zIndex(10)
                //设置marker图片旋转角度,正北开始逆时针方向计算
                .rotateAngle(30.0f)
                //设置infoWindow的偏移位置
                .setInfoWindowOffset(0, 0);
        aMap.addMarker(mo);


        //添加一个动画marker
        LatLng latLng2 = new LatLng(30.68, 104.07);
        MarkerOptions mo1 = new MarkerOptions().icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.location)))
                .title("动画").snippet("生长动画").position(latLng2);
        Marker m = aMap.addMarker(mo1);

        final Animation animation = new ScaleAnimation(0, 1, 0, 1);
        animation.setDuration(2000);
        animation.setInterpolator(new AccelerateInterpolator());

        m.setAnimation(animation);
        m.startAnimation();

        //添加一个marker的点击事件
        aMap.setOnMarkerClickListener(new AMap.OnMarkerClickListener() {
            @Override
            public boolean onMarkerClick(Marker marker) {

                //当点击的时候添加生长动画
                marker.setAnimation(animation);
                marker.startAnimation();

                //这里在添加点击监听事件后,原来的InfoWindow被取消了,可以在回调方法中手动实现
                if (marker.isInfoWindowShown()) {
                    marker.hideInfoWindow();
                } else {
                    marker.showInfoWindow();
                }

                return true;
            }
        });

        //添加拖拽事件,注意此回调方法只对设置了可拖拽的marker生效
        aMap.setOnMarkerDragListener(new AMap.OnMarkerDragListener() {
            @Override
            public void onMarkerDragStart(Marker marker) {
                Log.e(TAG, "onMarkerDragStart: 被拖拽的Marker标题为->" + marker.getTitle());
            }

            @Override
            public void onMarkerDrag(Marker marker) {

            }

            @Override
            public void onMarkerDragEnd(Marker marker) {

                Log.e(TAG, "onMarkerDragEnd: 拖拽完后Maker的经纬度-> lat=" + marker.getPosition().latitude + " lng=" + marker.getPosition().longitude);


            }
        });

        //自定义infoWindow
        aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() {

            View view;

            @Override
            public View getInfoWindow(Marker marker) {

                if (view == null) {
                    view = LayoutInflater.from(DrawActivity.this).inflate(R.layout.custom_info_window, null);
                }

                findViews(marker, view);
                return view;
            }

            @Override
            public View getInfoContents(Marker marker) {
                return null;
            }
        });

        aMap.setOnInfoWindowClickListener(new AMap.OnInfoWindowClickListener() {
            @Override
            public void onInfoWindowClick(Marker marker) {

                Log.e(TAG, "onInfoWindowClick: 标题为:" + marker.getTitle() + "  的InfoWindow被点击了");
            }
        });


        moveToDefaultPosition();
    }

    private void moveToDefaultPosition() {
        //移动到marker位置
        CameraUpdate mCameraUpdate = CameraUpdateFactory.newCameraPosition(
                new CameraPosition(
                        new LatLng(30.665, 104.065),
                        15,
                        0,
                        0
                )
        );
        aMap.moveCamera(mCameraUpdate);
    }

    private void moveToPosition(double lat, double lng) {
        //移动到marker位置
        CameraUpdate mCameraUpdate = CameraUpdateFactory.newCameraPosition(
                new CameraPosition(
                        new LatLng(lat, lng),
                        13,
                        0,
                        0
                )
        );
        aMap.moveCamera(mCameraUpdate);
    }

    /**
     * 在点击marker显示infoWindow是,找到相应的控件,修改显示
     */
    private void findViews(Marker marker, View view) {

        TextView name = view.findViewById(R.id.name);
        TextView address = view.findViewById(R.id.address);

        name.setText(marker.getTitle());
        address.setText(marker.getSnippet());
    }

    /**
     * -----------------------------------------Marker相关----------------------------------------------------
     */


    /**
     * -----------------------------------------Line相关------------------------------------------------------
     */
    private void drawLine() {


        moveToDefaultPosition();

        ArrayList<LatLng> points = new ArrayList<>();
        points.add(new LatLng(30.66, 104.06));
        points.add(new LatLng(30.66, 104.07));
        points.add(new LatLng(30.67, 104.07));
        points.add(new LatLng(30.67, 104.06));
        points.add(new LatLng(30.66, 104.06));

        aMap.addPolyline(new PolylineOptions().addAll(points).width(10).color(Color.argb(255, 1, 1, 1)));


        ArrayList<LatLng> latlngs = new ArrayList<>();
        latlngs.add(new LatLng(30.6595, 104.0595));
        latlngs.add(new LatLng(30.6595, 104.0705));
        latlngs.add(new LatLng(30.6705, 104.0705));
        latlngs.add(new LatLng(30.6705, 104.0595));
        latlngs.add(new LatLng(30.6595, 104.0595));


        ArrayList<Integer> a = new ArrayList<>();
        a.add(0);
        a.add(1);
        a.add(2);
        a.add(3);
        ArrayList<BitmapDescriptor> b = new ArrayList<>();
        b.add(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.bb)));
        b.add(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.aa)));
        b.add(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.bb)));
        b.add(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.aa)));

        aMap.addPolyline(new PolylineOptions()
                //添加多有的经纬度点
                .addAll(latlngs)
                //绘制线宽
                .width(20)
                //是否开启纹理贴图
                .setUseTexture(true)
                //纹理贴图段的index数组
                .setCustomTextureIndex(a)
                //纹理贴图每段对应的纹理资源图
                .setCustomTextureList(b)
                //是否虚线,纹理贴图时无效
                .setDottedLine(false)
                //绘制成大地线
                .geodesic(false)
                //设置纹理样式
                .setCustomTexture(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.aa)))
                //设置画线的颜色
                .color(Color.argb(255, 1, 1, 1))
        );


    }
    /**
     * -----------------------------------------Line相关------------------------------------------------------
     */


    /**
     * -----------------------------------------绘制几何图形相关------------------------------------------------------
     */
    private void drawSurface() {

        moveToDefaultPosition();

        LatLng latLng = new LatLng(30.665, 104.065);

        //绘制一个圆
        Circle circle = aMap.addCircle(new CircleOptions()
                .center(latLng)
                .radius(500)
                .fillColor(Color.argb(30, 1, 1, 1))
                .strokeColor(Color.argb(255, 1, 1, 1))
                .strokeWidth(10)
        );

        circle.setStrokeDottedLineType(0);


//        //绘制一个矩形,多边形跟这个一样的
//        aMap.addPolygon(new PolygonOptions()
//                .addAll(createRectangle(new LatLng(30.665, 104.065), 0.01, 0.01))
//                .fillColor(Color.LTGRAY).strokeColor(Color.RED).strokeWidth(5));
//
//        // 绘制一个椭圆
//        PolygonOptions options = new PolygonOptions();
//        int numPoints = 400;
//        float semiHorizontalAxis = 2f;
//        float semiVerticalAxis = 0.5f;
//        double phase = 2 * Math.PI / numPoints;
//        for (int i = 0; i <= numPoints; i++) {
//            options.add(new LatLng(
//                    30.665 + semiVerticalAxis * Math.sin(i * phase),
//                    104.065 + semiHorizontalAxis * Math.cos(i * phase)
//            ));
//        }
//
//        Polygon polygon = aMap.addPolygon(options
//                .strokeWidth(25)
//                .strokeColor(Color.argb(50, 1, 1, 1))
//                .fillColor(Color.argb(50, 1, 1, 1))
//        );

    }

    /**
     * 生成一个长方形的四个坐标点
     */
    private List<LatLng> createRectangle(LatLng center, double halfWidth,
                                         double halfHeight) {
        List<LatLng> latLngs = new ArrayList<LatLng>();
        latLngs.add(new LatLng(center.latitude - halfHeight, center.longitude - halfWidth));
        latLngs.add(new LatLng(center.latitude - halfHeight, center.longitude + halfWidth));
        latLngs.add(new LatLng(center.latitude + halfHeight, center.longitude + halfWidth));
        latLngs.add(new LatLng(center.latitude + halfHeight, center.longitude - halfWidth));
        return latLngs;
    }

    /**
     * -----------------------------------------绘制几何图形相关------------------------------------------------------
     */

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

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

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

    @Override
    protected void onDestroy() {

        List<Marker> list = aMap.getMapScreenMarkers();
        if (list != null && list.size() > 0) {
            for (Marker one : list) {
                one.destroy();
            }
        }

        drawMapView.onDestroy();
        //这里注意,butterknife注销一定要在所有销毁的最后,否则会出现空指针异常
        binder.unbind();
        super.onDestroy();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {

        super.onSaveInstanceState(outState);
        drawMapView.onSaveInstanceState(outState);
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容

  • 一、简历准备 1、个人技能 (1)自定义控件、UI设计、常用动画特效 自定义控件 ①为什么要自定义控件? Andr...
    lucas777阅读 5,121评论 2 54
  • 地图的显示 添加依赖: 1.在布局文件中添加如下代码,并在onCreate() 中findViewById() 2...
    3c2cf1f7612e阅读 2,931评论 1 0
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,034评论 1 32
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,595评论 4 59
  • 第一章:Activity生命周期和启动模式 Activity关闭时会调用onPause()和onStop(),如果...
    loneyzhou阅读 830评论 0 2