Android Studio3.0对于百度地图SDK的开发(自定义标点)



前言

Android Studio3.0对于百度地图SDK的开发(前置准备)
Android Studio3.0对于百度地图SDK的开发(显示地图以及定位实现)
Android Studio3.0对于百度地图SDK的开发(基于方向传感器实现手机朝向显示)
往期文章我们已经实现了对于百度地图的定位功能,这一篇文章我们主要实现边读地图的自定义标点以及一些相关的功能。


一、图片导入

百度自带的SDK似乎没有自带标点的图片资源,这里我用的是这个标点,当然,可以自己替换。
右键另存为png文件即可
右键另存为png文件即可,注意,文件的名字只能有小写字母数字以及下划线
将图片直接粘贴到res下的drawable中即可。
在这里插入图片描述

二、标点实现

1.创建标点

在初始化地图时加入地图长按事件监听接口,来实现长按创建标点。其他地图事件可以查询百度开发文档
事件交互

//地图长按事件监听接口
        BaiduMap.OnMapLongClickListener longClickListener = new BaiduMap.OnMapLongClickListener() {
            //point 长按的地理坐标
            @Override
            public void onMapLongClick(LatLng point) {
                //弹出确认框
                AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this)
                        .setTitle("创建标点")
                        .setMessage("是否创建标点?")
                        .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                //构建Marker图标
                                BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.drawable.icon_marka);
                                //构建MarkerOption,用于在地图上添加Marker
                                OverlayOptions overlayOptions = new MarkerOptions()
                                        .position(point)
                                        .icon(bitmapDescriptor);
                                //在地图上添加Marker,并显示
                                mBaiduMap.addOverlay(overlayOptions);
                            }
                        })
                        .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                return;
                            }
                        }).create();
                alertDialog.show();
            }
        };
        //设置地图长按事件监听
        mBaiduMap.setOnMapLongClickListener(longClickListener);

实现事件监听后就可以在地图上长按来创建标点了。
在这里插入图片描述

2.删除标点

光能创建标点还不行,对于不需要的标点我们要能够删除它们。因此在初始化地图时添加点击标点的监听接口。

mBaiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
            //marker被点击时回调的方法
            //若响应点击事件,返回true,否则返回false
            //默认返回false
            @Override
            public boolean onMarkerClick(Marker marker) {
                //弹出确认框
                AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this)
                        .setTitle("创建标点")
                        .setMessage("是否删除标点?")
                        .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                marker.remove();
                            }
                        })
                        .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                return;
                            }
                        }).create();
                alertDialog.show();
                return true;
            }
        });

这样点击标点就能够删除它了。
在这里插入图片描述
这里有一个bug,当标点离定位点太近时,由于定位点的层级在标点之上,标点会被定位点的精度圈覆盖,导致无法点击。

3.优化

在这里感谢感谢hua-sky大佬的回答。
在这里插入图片描述
既然定位点的图层自带点击事件,而且无法被取消,那么我们就不再使用这个图层,而是改用自定义标点来实现。
添加以下对象

//定位点
    private Marker loc_marker;
    private String loc_id;

首先在初始化地图的时候不再开启定位图层,即删除这句话

mBaiduMap.setMyLocationEnabled(true);

然后在MyLocationListener类中,修改OnReceiveLocation方法,使其不再更新定位点,而是通过创建一个自定义标点loc_maker,并通过不断改变其位置和旋转方向来实现定位点。

public class MyLocationListener extends BDAbstractLocationListener {
        @Override
        public void onReceiveLocation(BDLocation location) {
            //mapView 销毁后不在处理新接收的位置
            if (location == null || mMapView == null){
                return;
            }
            Latitude=location.getLatitude();
            Longitude=location.getLongitude();
            Radius=location.getRadius();
            LatLng latLng = new LatLng(Latitude, Longitude);
            if(isFirst)
            {
                MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(latLng);
                mBaiduMap.animateMapStatus(update);
                MyLocationConfiguration configuration = new MyLocationConfiguration(MyLocationConfiguration.LocationMode.NORMAL,
                        true, null );
                mBaiduMap.setMyLocationConfiguration(configuration);

                BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.drawable.icon_marka);
                OverlayOptions overlayOptions = new MarkerOptions()
                        .position(latLng)
                        .icon(bitmapDescriptor)
                        .rotate(mCurrentX)
                        .clickable(false);
                loc_marker=(Marker) mBaiduMap.addOverlay(overlayOptions);
                loc_id=loc_marker.getId();
                isFirst=false;
            }
            loc_marker.setPosition(latLng);
            loc_marker.setRotate(mCurrentX);
        }
    }

最后更改运动传感器的方法,这里有一点要注意,设置百度SDK自带定位点的旋转时,它是顺时针旋转的,而自定义标点是逆时针旋转,因此我们要对获取到的方向进行换算。此外,在定位点创建前可能会触发传感器方法,此时loc_marker为空对象,会导致应用崩溃。因此在修改loc_marker旋转方向前,先判断应用时候进行过定位。

private void initOrientation() {
        //传感器
        mMyOrientationListener = new MyOrientationListener(getApplicationContext());
        mMyOrientationListener.setOnOrientationListener(new MyOrientationListener.OnOrientationListener() {
            @Override
            public void onOrientationChanged(float x) {
                mCurrentX = 360-x;
                if(mCurrentX<180)
                    mCurrentX+=180;
                else
                    mCurrentX-=180;
                if(isFirst==false)
                    loc_marker.setRotate(Math.abs(mCurrentX));
            }
        });
    }

三、本地存储

既然是自己设置的标点,我们当然要将其保存下来,便于以后再次查找。因此,我们需要将自己设置的标点存储下来,防止标点随着应用的关闭而被删除。

1.数据库类

新建一个java类

public class point extends SQLiteOpenHelper {
    public point(Context context, String name, SQLiteDatabase.CursorFactory factory,int version)
    {
        super(context,name,factory,version);
    }
    @Override
    //创建数据库
    public void onCreate(SQLiteDatabase db){
        db.execSQL("create table if not exists " +
                "point(_id integer primary key autoincrement," +
                "name varchar(100)," +
                "longitude decimal(40,20)," +
                "latitude decimal(40,20)," +
                "type varchar(20)," +
                "visable tinyint(1)," +
                "others varchar(100));");
    }
    @Override
    //升级数据库
    public void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion)
    {

    }

2.定义数据存储结构

这部分主要是读取数据库数据所用,因为在实现的时候需要用到,所以先写出来

public class PointBean {
    public String ID;
    public String name;
    public double longitude;
    public double latitude;
    public String type;
    public int visable;
    public String others;
    public PointBean()
    {super();}
    public PointBean(String ID,String name,double longitude,double latitude,String type,int visable,String others){
        super();
        this.ID=ID;
        this.name=name;
        this.longitude=longitude;
        this.latitude=latitude;
        this.type=type;
        this.visable=visable;
        this.others=others;
    }
    @Override
    public String toString()
    {
        return "PointBean [ID=" +ID
                +"name="+name
                +",longitude="+longitude
                +",latitude="+latitude
                +",type="+type
                +",visable="+visable
                +",others="+others+"]";
    }
    public String returnID(){return ID;}
    public String returnname()
    {
        return name;
    }
    public double returnlongitude()
    {
        return longitude;
    }
    public double returnlatitude()
    {
        return latitude;
    }
    public String returntype()
    {
        return type;
    }
    public int returnvisable()
    {
        return visable;
    }
    public String returnothers() { return others; }

3.数据库操作

这个类中将包含数据库的基本操作。

ublic class OpPoint {
    //创建数据库
    private point dbHelper;
    //数据库的表名
    private String p_name = "point";

    private OpPoint(Context ctx) {
        dbHelper = new point(ctx, "point.db", null, 1);
    }
    private static OpPoint instance;
    public static synchronized OpPoint getInstance(Context ctx)
    {
        //如果实例为空,创建一个新的,否则用原来的
        if(instance==null){
            instance=new OpPoint(ctx);
        }
        return instance;
    }
    //增
    public void addpoint(String name,double longitude,double latitude,String type,int visable,String others)
    {
        //获得一个可写的数据库的引用
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        ContentValues values=new ContentValues();
        values.put("name",name);
        values.put("longitude",longitude);
        values.put("latitude",latitude);
        values.put("type",type);
        values.put("visable",visable);
        values.put("others",others);
        db.insertOrThrow(p_name,null,values);
    }
    //删
    public void deletepoint(String ID)
    {
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        db.delete(p_name,"_id = ?",new String[]{ID});
    }
    //改
    public void updatepoint(String ID,String name,double longitude,double latitude,String type,int visable,String others){
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        ContentValues values=new ContentValues();
        values.put("name",name);
        values.put("longitude",longitude);
        values.put("latitude",latitude);
        values.put("type",type);
        values.put("visable",visable);
        values.put("others",others);
        db.update(p_name,values,"_id = ?",new String[]{ID});
    }
    //查
    public List<PointBean>getPoint(){
        List<PointBean> allpoint = new ArrayList<PointBean>();
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        Cursor cursor = db.query(p_name, null, null, null, null, null, null);
        // 返回的 cursor 默认是在第一行的上一行
        //遍历
        while(cursor.moveToNext()){// cursor.moveToNext() 向下移动一行,如果有内容,返回true
            String ID = cursor.getString(0);
            String name = cursor.getString(1);
            double longitude = cursor.getDouble(2);
            double latitude = cursor.getDouble(3);
            String type = cursor.getString(4);
            int visable = cursor.getInt(5);
            String others = cursor.getString(6);
            //将number mode 封装到bean中
            PointBean bean = new PointBean(ID,name,longitude,latitude,type,visable,others);
            //封装的对象添加到集合中
            allpoint.add(bean);
        }
        //关闭cursor
        cursor.close();
        return allpoint;
    }
    //获取坐标数量
    public int getPointCount(){
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        Cursor cursor = db.query(p_name,new String[]{"count(*)"},null, null, null, null, null);
        cursor.moveToNext();
        int count = cursor.getInt(0);
        cursor.close();
        return count;
    }
    public List<PointBean>getPoint(String TYPE){
        List<PointBean> allpoint = new ArrayList<PointBean>();
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        Cursor cursor = db.query(p_name, null, "type=?", new String[]{TYPE}, null, null, null);
        // 返回的 cursor 默认是在第一行的上一行
        //遍历
        while(cursor.moveToNext()){// cursor.moveToNext() 向下移动一行,如果有内容,返回true
            String ID = cursor.getString(0);
            String name = cursor.getString(1);
            double longitude = cursor.getDouble(2);
            double latitude = cursor.getDouble(3);
            String type = cursor.getString(4);
            int visable = cursor.getInt(5);
            String others = cursor.getString(6);
            //将number mode 封装到bean中
            PointBean bean = new PointBean(ID,name,longitude,latitude,type,visable,others);
            //封装的对象添加到集合中
            allpoint.add(bean);
        }
        //关闭cursor
        cursor.close();
        return allpoint;
    }
    public int getPointCount(String type){
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        Cursor cursor = db.query(p_name,new String[]{"count(*)"},"type=?", new String[]{type}, null, null, null);
        cursor.moveToNext();
        int count = cursor.getInt(0);
        cursor.close();
        return count;
    }
    public void deleteDatabase(Context context, String databaseName)
    {
        context.deleteDatabase(databaseName);
    }
    public List<PointBean>SearchPoint(String _id){
        List<PointBean> targetpoint = new ArrayList<PointBean>();
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        Cursor cursor = db.query(p_name, null, "_id=?", new String[]{_id}, null, null, null);
        cursor.moveToNext();
        String ID = cursor.getString(0);
        String name = cursor.getString(1);
        double longitude = cursor.getDouble(2);
        double latitude = cursor.getDouble(3);
        String type = cursor.getString(4);
        int visable = cursor.getInt(5);
        String others = cursor.getString(6);
        PointBean bean = new PointBean(ID,name,longitude,latitude,type,visable,others);
        //封装的对象添加到集合中
        targetpoint.add(bean);
        //关闭cursor
        cursor.close();
        return targetpoint;
    }

4.初始化数据库

在MainActivity.java中添加以下对象

    //本地数据库相关
    private OpPoint point;
    //坐标点集合
    private List<PointBean> allpoint;

在onCreate中添加以下语句

point=OpPoint.getInstance(this);

这样数据库的初始化就完成了,接下来我将展示一些基础的操作。

四、基于本地数据库的标点操作

我们已经创建了存储标点信息的本地数据库,那么我们有必要修改之前关于标点的创建和删除,将其和数据库联系起来。

1.创建标点

设置输入对话框

现在创建标点不能和上面一样单纯的点一个确定就完成了,我们需要输入一些信息来存入数据库。
在layout文件夹下创建一个create_point_dialog.xml文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/create_user_dialog_view"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="#ffffff"
    android:minWidth="200dp"
    android:orientation="vertical"
    android:padding="10dp"
    android:paddingBottom="30dp"
    android:paddingTop="30dp">

    <EditText
        android:id="@+id/text_name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#aaaaaa"
        android:hint="名称"
        android:minHeight="45dp"
        android:textColor="#000000"
        android:textSize="18sp" />

    <RadioGroup
        android:id="@+id/point_type"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal"
        android:layout_marginTop="5dp"
        android:background="#aaaaaa">
        <RadioButton
            android:id="@+id/eat"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#000000"
            android:text="餐饮" />
        <RadioButton
            android:id="@+id/play"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#000000"
            android:text="娱乐" />

        <RadioButton
            android:id="@+id/work"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#000000"
            android:text="工作" />
    </RadioGroup>

    <EditText
        android:id="@+id/text_others"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:background="#aaaaaa"
        android:gravity="top|left"
        android:hint="备注"
        android:minHeight="145dp"
        android:textSize="18sp" />

    <Button
        android:id="@+id/btn_save_pop"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:text="保存" />
    <Button
        android:id="@+id/btn_cancel_pop"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:text="取消" />
</LinearLayout>

类文件

建立CreatePointDialog.java文件

public class CreatePointDialog extends Dialog {
    Activity context;
    private Button btn_save;
    private Button btn_cancel;
    public EditText text_name=null;
    public EditText text_others=null;
    private RadioGroup point_type;
    public String type=null;
    private View.OnClickListener mClickListener;
    public LatLng loc;

    public CreatePointDialog(Activity context) {
        super(context);
        this.context = context;
    }

    public CreatePointDialog(Activity context, View.OnClickListener clickListener,LatLng loc) {
        super(context);
        this.context = context;
        this.mClickListener = clickListener;
        this.loc = loc;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 指定布局
        this.setContentView(R.layout.create_point_dialog);
        text_name = (EditText) findViewById(R.id.text_name);
        text_others = (EditText) findViewById(R.id.text_others);
        Window dialogWindow = this.getWindow();

        WindowManager m = context.getWindowManager();
        Display d = m.getDefaultDisplay(); // 获取屏幕宽、高用
        WindowManager.LayoutParams p = dialogWindow.getAttributes(); // 获取对话框当前的参数值
        Point size =new Point();
        d.getSize(size);
        // p.height = (int) (d.getHeight() * 0.6); // 高度设置为屏幕的0.6
        p.width = (int) (size.x * 0.8); // 宽度设置为屏幕的0.8
        dialogWindow.setAttributes(p);

        // 根据id在布局中找到控件对象
        btn_save = (Button) findViewById(R.id.btn_save_pop);
        btn_cancel = (Button) findViewById(R.id.btn_cancel_pop);
        // 为按钮绑定点击事件监听器
        btn_save.setOnClickListener(mClickListener);
        btn_cancel.setOnClickListener(mClickListener);

        this.setCancelable(true);
        initRadioGroup();
    }
    public void initRadioGroup() {
        //获取radiongroup对象
        point_type = (RadioGroup) findViewById(R.id.point_type);
        //通过radiogroup的setoncheckedlistener方法注册监听事件
        //在监听事件中创建oncheckedlistener 在重写oncheckedchanged方法
        point_type.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                //获取被选中的radiobutton的id
                RadioButton rcheck = (RadioButton) findViewById(checkedId);
                //获取
                type = rcheck.getText().toString();
            }
        });
    }
    public LatLng returnLoc()
    {
        return loc;
    }
}

修改地图长按事件

 //地图长按事件监听接口
        BaiduMap.OnMapLongClickListener longClickListener = new BaiduMap.OnMapLongClickListener() {
            //location 长按的地理坐标
            @Override
            public void onMapLongClick(LatLng location) {
                createPointDialog = new CreatePointDialog(MainActivity.this, MainActivity.this,location);
                createPointDialog.show();
            }
        };
        //设置地图长按事件监听
        mBaiduMap.setOnMapLongClickListener(longClickListener);

增加按钮点击事件

 @Override
    public void onClick(View v) {
        SDKInitializer.initialize(getApplicationContext());
        switch (v.getId()) {
            case R.id.but_Loc: {
                centerToMyLocation();
                break;
            }
            case R.id.showpoint:{
                startActivityForResult(new Intent(MainActivity.this,showpointPopupWindow.class),1);
                break;
            }
            case R.id.btn_save_pop:{
                String name = createPointDialog.text_name.getText().toString().trim();
                String type = createPointDialog.type;
                String others = createPointDialog.text_others.getText().toString().trim();
                if(name.equals(""))
                    Toast.makeText(this, "请输入名字!", Toast.LENGTH_LONG).show();
                else if(type==null)
                    Toast.makeText(this, "请选择坐标类型!", Toast.LENGTH_LONG).show();
                else
                {
                    LatLng location = createPointDialog.returnLoc();
                    point.addpoint(name,location.longitude,location.latitude,type,1,others);
                    refreshpoint();
                    createPointDialog.dismiss();
                }
                break;
            }
            case R.id.btn_cancel_pop:{
                createPointDialog.dismiss();
                break;
            }
        }
    }

2.删除标点

只需要更改标点的点击事件即可

        mBaiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
            //marker被点击时回调的方法
            //若响应点击事件,返回true,否则返回false
            //默认返回false
            @Override
            public boolean onMarkerClick(Marker marker) {
                //弹出确认框
                AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this)
                        .setTitle("删除标点")
                        .setMessage("是否删除标点?")
                        .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                //marker.remove();
                                String id = marker.getExtraInfo().getString("_id");
                                point.deletepoint(id);
                                refreshpoint();
                            }
                        })
                        .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                return;
                            }
                        }).create();
                alertDialog.show();
                return true;
            }
        });

3.更新标点

创建一个refreshpoint方法。

//刷新坐标点
    public void refreshpoint()
    {
        cleanpoint();
        int pointcount=point.getPointCount();
        allpoint = point.getPoint();
        Object id[]=allpoint.stream().map(PointBean::returnID).collect(Collectors.toList()).toArray();
        Object longitude[] = allpoint.stream().map(PointBean::returnlongitude).collect(Collectors.toList()).toArray();
        Object latitude[] = allpoint.stream().map(PointBean::returnlatitude).collect(Collectors.toList()).toArray();
        Object type[] = allpoint.stream().map(PointBean::returntype).collect(Collectors.toList()).toArray();
        Object visable[] = allpoint.stream().map(PointBean::returnvisable).collect(Collectors.toList()).toArray();
        for(int i=0;i<pointcount;i++)
        {
            if(visable[i].toString().equals("1")){
                LatLng location = new LatLng(new Double(latitude[i].toString()),new Double(longitude[i].toString()));
                BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.drawable.icon_marka);
            /*switch (type[i].toString()){
                case "餐饮":
                    bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.drawable.icon_restruant);
                    break;
                case "娱乐":
                    bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.drawable.icon_play);
                    break;
                case "工作":
                    bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.drawable.icon_work);
                    break;
            }*/
                Bundle info = new Bundle();
                info.putString("_id",id[i].toString());
                OverlayOptions overlayOptions = new MarkerOptions()
                        .position(location)
                        .icon(bitmapDescriptor)
                        .extraInfo(info);
                mBaiduMap.addOverlay(overlayOptions);

            }
        }
    }

刷新标点的第一步是要清除原有标点,百度SDK提供的批量删除标点的方法只有mBaiduMap.clear(),这个方法会清除所有的自定义标点,但是由于我们的定位点也是一个自定义标点,会跟着被清除,如果采用clear()再重新显示定位点,定位点会闪一下,看起来不够流畅。因此我自定义了一个清除标点的方法 cleanpoint(),在清除标点时能留下定位点。

 //清除坐标点
    public void cleanpoint()
    {
        if(isFirst==false)
        {
            LatLngBounds Bounds= mBaiduMap.getMapStatusLimit();
            List<Marker> markers = mBaiduMap.getMarkersInBounds(Bounds);
            for(int i=0;i<markers.size();i++)
            {
                if(!loc_id.equals(markers.get(i).getId()))  markers.get(i).remove();
            }
        }
    }

如果想要在地图启动的时候自动显示之前添加的标点,就可以在初始化地图的时候调用一次这个方法,这样,就能在应用启动的时候,自动地在地图上显示以前创建的标点。

五、标点列表

如果自己创建的标点过多的话,单从地图上可能无法认出哪个是自己想要的标点,而且,被隐藏的标点也无法再被点击,因此我们可以为标点做一个列表,来统一管理我们的标点。
我打算设计一个可折叠的列表,点击“自定义坐标”按钮就从屏幕下面出现该列表。

1.设计窗口布局

弹出窗口布局

在layout文件夹中新建一个alert_dialog.xml文件。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    >
    <LinearLayout
        android:id="@+id/pop_layout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:orientation="vertical"
        android:layout_alignParentBottom="true"
        android:background="#00000000"
        >
        <ExpandableListView
            android:id="@+id/list"
            android:layout_marginLeft="20dip"
            android:layout_marginRight="20dip"
            android:layout_marginTop="15dip"
            android:layout_marginBottom="15dip"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#00aaff">
        </ExpandableListView>
    </LinearLayout>
</RelativeLayout>

ExpandableListView父布局

在layout文件夹中新建一个group.xml文件。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">
    <TextView
        android:id="@+id/parent_textview_id"
        android:layout_width="wrap_content"
        android:text="测试"
        android:textColor="@color/black"
        android:gravity="center_vertical"
        android:paddingLeft="10dp"
        android:textSize="18sp"
        android:layout_height="match_parent"
        />
</LinearLayout>

ExpandableListView子布局

在layout文件夹中新建一个child.xml文件。

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

    <TextView
        android:id="@+id/chidren_name"
        android:layout_width="match_parent"
        android:text="子项目"
        android:gravity="center_vertical"
        android:paddingLeft="10dp"
        android:textColor="@color/black"
        android:layout_height="40dp" />

</LinearLayout>

添加按钮

在activity_main.xml中加入按钮

    <Button
        android:id="@+id/showpoint"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="127dp"
        android:text="自定义坐标"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@id/but_Loc" />

2.创建Activity类

创建showpointPopupWindow.java文件

public class showpointPopupWindow extends Activity implements View.OnClickListener, Serializable {
    //列表相关
    private ExpandableListView expand_list_id;
    private OpPoint point;
    private String[] groups = {"餐饮", "娱乐", "工作"};
    private String[][] childs_id=null;
    private String[][] childs_name=null;
    private showpointinfoWindow showpointinfoWindow;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.alert_dialog);
        initView();
    }
    //实现onTouchEvent触屏函数但点击屏幕时销毁本Activity
    @Override
    public boolean onTouchEvent(MotionEvent event){
        setResult(0,null);
        finish();
        return true;
    }
    private void initView(){
        point=OpPoint.getInstance(this);
        childs_id = new String[3][];
        childs_id[0] = new String[point.getPointCount("餐饮")];
        childs_id[1] = new String[point.getPointCount("娱乐")];
        childs_id[2] = new String[point.getPointCount("工作")];
        childs_name = new String[3][];
        childs_name[0] = new String[point.getPointCount("餐饮")];
        childs_name[1] = new String[point.getPointCount("娱乐")];
        childs_name[2] = new String[point.getPointCount("工作")];
        List<PointBean> allpoint = point.getPoint("餐饮");
        Object id[] = allpoint.stream().map(PointBean::returnID).collect(Collectors.toList()).toArray();
        Object name[] = allpoint.stream().map(PointBean::returnname).collect(Collectors.toList()).toArray();
        for(int i=0;i<point.getPointCount("餐饮");i++)
        {
            childs_id[0][i]=id[i].toString();
            childs_name[0][i]=name[i].toString();
        }
        allpoint = point.getPoint("娱乐");
        id = allpoint.stream().map(PointBean::returnID).collect(Collectors.toList()).toArray();
        name = allpoint.stream().map(PointBean::returnname).collect(Collectors.toList()).toArray();
        for(int i=0;i<point.getPointCount("娱乐");i++)
        {
            childs_id[1][i]=id[i].toString();
            childs_name[1][i]=name[i].toString();
        }
        allpoint = point.getPoint("工作");
        id = allpoint.stream().map(PointBean::returnID).collect(Collectors.toList()).toArray();
        name = allpoint.stream().map(PointBean::returnname).collect(Collectors.toList()).toArray();
        for(int i=0;i<point.getPointCount("工作");i++)
        {
            childs_id[2][i]=id[i].toString();
            childs_name[2][i]=name[i].toString();
        }
        expand_list_id=findViewById(R.id.list);
        ExpandableListviewAdapter adapter=new ExpandableListviewAdapter(this,groups,childs_id,childs_name);
        expand_list_id.setAdapter(adapter);
        expand_list_id.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView expandableListView, View view, int groupPosition, int childPosition, long l) {
                showpointinfoWindow = new showpointinfoWindow(showpointPopupWindow.this,showpointPopupWindow.this,childs_id[groupPosition][childPosition]);
                showpointinfoWindow.show();
                return true;
            }
        });
    }
    public void showToastShort(String msg){
        Toast.makeText(this,msg, Toast.LENGTH_SHORT).show();
    }
    @Override
    public void onClick(View v)
    {
        SDKInitializer.initialize(getApplicationContext());
        switch (v.getId()) {
            case R.id.btn_set_pop: {
                String Latitude = showpointinfoWindow.point_latitude.getText().toString();
                String Longitude= showpointinfoWindow.point_longitude.getText().toString();
                Intent intent = new Intent();
                intent.putExtra("Latitude",Latitude);
                intent.putExtra("Longitude",Longitude);
                setResult(1,intent);
                showpointinfoWindow.dismiss();
                finish();
                break;
            }
            case R.id.btn_update_pop:{
                //弹出确认框
                AlertDialog alertDialog = new AlertDialog.Builder(this)
                        .setTitle("修改标点")
                        .setMessage("是否修改标点信息?")
                        .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                String _id = showpointinfoWindow.point_id.getText().toString();
                                String name = showpointinfoWindow.point_name.getText().toString();
                                if(name.equals(""))
                                {
                                    Toast.makeText(showpointPopupWindow.this, "请输入名字!", Toast.LENGTH_LONG).show();
                                    return;
                                }
                                String Latitude = showpointinfoWindow.point_latitude.getText().toString();
                                String Longitude = showpointinfoWindow.point_longitude.getText().toString();
                                String type=null;
                                if(showpointinfoWindow.eat.isChecked())
                                    type="餐饮";
                                else if(showpointinfoWindow.play.isChecked())
                                    type="娱乐";
                                else if(showpointinfoWindow.work.isChecked())
                                    type="工作";
                                String visable;
                                if(showpointinfoWindow.point_visable.isChecked())
                                    visable="1";
                                else
                                    visable="0";
                                String others = showpointinfoWindow.point_others.getText().toString();
                                Intent intent = new Intent();
                                intent.putExtra("_id",_id);
                                intent.putExtra("name",name);
                                intent.putExtra("Latitude",Latitude);
                                intent.putExtra("Longitude",Longitude);
                                intent.putExtra("type",type);
                                intent.putExtra("visable",visable);
                                intent.putExtra("others",others);
                                setResult(2,intent);
                                showpointinfoWindow.dismiss();
                                finish();
                            }
                        })
                        .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                return;
                            }
                        }).create();
                alertDialog.show();
                break;
            }
            case R.id.btn_delete_pop:{
                //弹出确认框
                AlertDialog alertDialog = new AlertDialog.Builder(this)
                        .setTitle("删除标点")
                        .setMessage("是否删除标点?")
                        .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                String _id = showpointinfoWindow.point_id.getText().toString();
                                Intent intent = new Intent();
                                intent.putExtra("_id",_id);
                                setResult(3,intent);
                                showpointinfoWindow.dismiss();
                                finish();
                            }
                        })
                        .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                return;
                            }
                        }).create();
                alertDialog.show();
                break;
            }
            case R.id.btn_cancel_pop:{
                showpointinfoWindow.dismiss();
                break;
            }
        }
    }
}

3.修改MainActivity类

添加按钮

Button mshowpoint = (Button) findViewById(R.id.showpoint);
mshowpoint.setOnClickListener(this);

添加点击事件

case R.id.showpoint:{
                startActivityForResult(new Intent(MainActivity.this,showpointPopupWindow.class),1);
                break;
            }

4.设置弹出动画

右键res文件夹,新建Android Resource File。
在这里插入图片描述
选择Resource type为Animation
在这里插入图片描述
输入名字后在res下会出现一个anim文件夹,新建的.xml文件就在里面,如果没有就先新建文件夹再新建文件。
我给弹出文件起的名字为push_bottom_in
代码如下

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="200"
        android:fromYDelta="100%p"
        android:toYDelta="0"
        />
</set>

5.设置销毁动画

和4一样,新建一个push_bottom_out.xml文件。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="200"
        android:fromYDelta="0"
        android:toYDelta="50%p"
        />
</set>

6.添加自定义android:theme

在res下values文件夹下的themes.xml添加以下代码

<style name="MyDialogStyleBottom" parent="android:Theme.Dialog">
        <item name="android:windowAnimationStyle">@style/AnimBottom</item>
        <item name="android:windowFrame">@null</item>
        ;!-- 边框 -->
        <item name="android:windowIsFloating">true</item>
        ;!-- 是否浮现在activity之上 -->
        <item name="android:windowIsTranslucent">true</item>
        ;!-- 半透明 -->
        <item name="android:windowNoTitle">true</item>
        ;!-- 无标题 -->
        <item name="android:windowBackground">@android:color/transparent</item>
        ;!-- 背景透明 -->
        <item name="android:backgroundDimEnabled">true</item>
        ;!-- 模糊 -->
    </style>

7.修改AndroidManifest.xml

添加以下代码

        <activity
            android:name=".showpointPopupWindow"
            android:theme="@style/MyDialogStyleBottom" />

这样就实现了列表的创建以及相关操作的实现。

总结

这一篇的文章前前后后大概写了一周,有些细节我可能会忘记写了,如果在阅读的过程中请在评论区中留言,我有时间的话会试着去解答的。

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值