面向GIS的Android studio移动开发(二)--在地图上绘制电子围栏

发布于:2025-05-19 ⋅ 阅读:(14) ⋅ 点赞:(0)

电子围栏,校园跑的常客,也是定位打卡必不可少的东西

主要代码:

创建电子围栏代码

// 添加多边形地理围栏(兼容2023版SDK)
    private void addPolygon(String fenceName, List<LatLng> points) {
        if (points == null || points.size() < 3) {
            Toast.makeText(this, "多边形至少需要3个点", Toast.LENGTH_SHORT).show();
            return;
        }

        // 生成唯一围栏ID
        String fenceId = "polygon_" + mCustomID++;

        // 转换坐标点格式
        List<DPoint> dPoints = new ArrayList<>();
        for (LatLng point : points) {
            dPoints.add(new DPoint(point.latitude, point.longitude));
        }

        // 正确调用方式(关键修改点)
        mClientInAndStayAction.addGeoFence(
                dPoints,               // 参数1: 多边形顶点坐标(必须闭合)
                fenceId                // 参数2: 自定义围栏ID
        );

        // 绘制多边形到地图
        PolygonOptions options = new PolygonOptions()
                .addAll(points)
                .fillColor(0x5566CCFF)    // 填充色(带透明度)
                .strokeColor(Color.BLUE)  // 边框色
                .strokeWidth(5);         // 边框宽度(px)

        Polygon polygon = aMap.addPolygon(options);
        mCustomEntitys.put(fenceId, polygon);

        // 设置围栏监听(新增)
        mClientInAndStayAction.setGeoFenceListener(new GeoFenceListener() {
            @Override
            public void onGeoFenceCreateFinished(List<GeoFence> geoFences, int errorCode, String msg) {
                if (errorCode == GeoFence.ADDGEOFENCE_SUCCESS) {
                    runOnUiThread(() ->
                            Toast.makeText(MapActivity.this, fenceName + "围栏创建成功", Toast.LENGTH_SHORT).show()
                    );
                }
            }
        });

        // 移动视角到围栏中心
        aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(points.get(0), 15));
    }

    //这里通过数据库进行添加电子围栏的多边形
    private void addTiananmenFence() {
        List<LatLng> tiananmenArea = new ArrayList<>();
        // 添加闭合坐标点(示例数据)
        tiananmenArea.add(new LatLng(39.908722, 116.397499)); // 天安门中心
        tiananmenArea.add(new LatLng(39.910000, 116.395000)); // 西北角
        tiananmenArea.add(new LatLng(39.909500, 116.400000));  // 东北角
        tiananmenArea.add(tiananmenArea.get(0)); // 闭合多边形

        addPolygon("天安门核心区", tiananmenArea);
    }

创建广播(当定位在定位外时触发)

// 修改onStart方法中的注册逻辑
    @Override
    protected void onStart() {
        super.onStart();

        // 创建带安全标志的广播过滤器
        IntentFilter filter = new IntentFilter(GEOFENCE_BROADCAST_ACTION);

        // 适配Android 13+广播权限要求
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            registerReceiver(
                    mGeoFenceReceiver,
                    filter,
                    Context.RECEIVER_NOT_EXPORTED // 禁止外部应用访问
            );
        } else {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                registerReceiver(mGeoFenceReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
            }
        }

        createNotificationChannel();
    }

    @Override
    protected void onStop() {
        super.onStop();
        // 取消注册接收器
        unregisterReceiver(mGeoFenceReceiver);
    }

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = "地理围栏警报";
            String description = "电子围栏越界通知";
            int importance = NotificationManager.IMPORTANCE_HIGH;

            NotificationChannel channel = new NotificationChannel(ALERT_CHANNEL_ID, name, importance);
            channel.setDescription(description);

            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }
    }

发送日志

 // 在MapActivity中
    private final BroadcastReceiver mGeoFenceReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (!isValidBroadcast(intent)) return;

            Bundle bundle = intent.getExtras();
            if (bundle == null) return;

            // 解析基础数据
            int status = bundle.getInt(GeoFence.BUNDLE_KEY_FENCESTATUS);
            String fenceId = bundle.getString(GeoFence.BUNDLE_KEY_FENCEID);
            GeoFence fence = bundle.getParcelable(GeoFence.BUNDLE_KEY_FENCE);

            // 分发事件处理
            handleGeoFenceEvent(context, status, fenceId, fence);
        }

        private boolean isValidBroadcast(Intent intent) {
            return intent != null &&
                    GEOFENCE_BROADCAST_ACTION.equals(intent.getAction());
        }

        private void handleGeoFenceEvent(Context context, int status,
                                         String fenceId, GeoFence fence) {
            switch (status) {
                case GeoFence.STATUS_IN:
                    handleEnter(context, fenceId);
                    break;

                case GeoFence.STATUS_OUT:
                    handleExit(context, fence);
                    break;

                case GeoFence.STATUS_STAYED:
                    handleStay(fence);
                    break;
            }
        }

        private void handleEnter(Context context, String fenceId) {
            // 记录日志
            GeoFenceLogger.logEnter(fenceId);

            // UI提示
            Toast.makeText(context, "进入监控区域", Toast.LENGTH_SHORT).show();
        }

        private void handleExit(Context context, GeoFence fence) {
            if (fence == null) return;

            // 记录日志
            GeoFenceLogger.logExit(fence.getFenceId());

            // 触发警报
            String alertMsg = "⚠️ 已离开安全区域: " + fence.getFenceId();
            Toast.makeText(context, alertMsg, Toast.LENGTH_LONG).show();
            sendAlertNotification(context, alertMsg);
        }

        private void handleStay(GeoFence fence) {
            if (fence == null) return;

            // 记录日志
            GeoFenceLogger.logStay(fence.getFenceId(), fence.getExpiration());
        }
    };


    private void sendAlertNotification(Context context, String message) {
        NotificationManager manager = (NotificationManager)
                getSystemService(Context.NOTIFICATION_SERVICE);

        // 构建通知
        Notification notification = new NotificationCompat.Builder(context, ALERT_CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_alert)
                .setContentTitle("区域越界警告")
                .setContentText(message)
                .setPriority(NotificationCompat.PRIORITY_MAX)
                .setAutoCancel(true)
                .build();

        // 显示通知
        if (manager != null) {
            manager.notify(new Random().nextInt(1000), notification);
        }
    }
package com.example.gdmap;

import android.util.Log;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;


//用来记录学生何时进出入电子围栏
//这部分可将log打印的日志部分写为string放在教师端的文本框中
// GeoFenceLogger.java
public class GeoFenceLogger {
    private static final String TAG = "GeoFenceTracker";
    private static final SimpleDateFormat DATE_FORMAT =
            new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault());

    // 记录进入事件
    public static void logEnter(String fenceId) {
        String timestamp = DATE_FORMAT.format(new Date());
        Log.d(TAG, String.format("[进入] 围栏ID: %s | 时间: %s", fenceId, timestamp));
    }

    // 记录离开事件
    public static void logExit(String fenceId) {
        String timestamp = DATE_FORMAT.format(new Date());
        Log.d(TAG, String.format("[离开] 围栏ID: %s | 时间: %s", fenceId, timestamp));
    }

    // 记录停留事件
    public static void logStay(String fenceId, long duration) {
        String timestamp = DATE_FORMAT.format(new Date());
        Log.d(TAG, String.format("[停留] 围栏ID: %s | 时间: %s | 持续时间: %dms",
                fenceId, timestamp, duration));
    }
}

activity代码

package com.example.gdmap;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.content.ContextCompat;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.amap.api.fence.GeoFence;
import com.amap.api.fence.GeoFenceListener;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.MapView;
import com.amap.api.maps.MapsInitializer;
import com.amap.api.maps.model.CircleOptions;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.api.fence.GeoFence;
import com.amap.api.fence.GeoFenceClient;
import com.amap.api.maps.model.Polygon;
import com.amap.api.maps.model.PolygonOptions;
import com.amap.api.maps.model.Circle;
import com.amap.api.location.DPoint; // 注意:高德使用DPoint而非LatLng
import android.Manifest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

public class MapActivity extends AppCompatActivity implements
        AMap.OnMarkerClickListener,
        AMap.InfoWindowAdapter {

    private MapView mMapView;
    // 地理围栏相关
    private GeoFenceClient mClientInAndStayAction;
    private int mCustomID = 1000; // 围栏ID种子值
    private HashMap<String, Object> mCustomEntitys = new HashMap<>(); // 存储围栏图形对象
    private static final String GEOFENCE_BROADCAST_ACTION = "com.example.gdmap.geofence";
    private AMap aMap;
    private static final int PERMISSION_REQUEST_CODE = 1001;
    // 在MapActivity类中添加以下代码
    private static final String TAG = "GeoFenceTracker";


    // 定义通知渠道ID
    private static final String ALERT_CHANNEL_ID = "geo_fence_alerts";

    private static final int REQUEST_CODE = 1001;

    private void requestLocationPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    REQUEST_CODE);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults); // 关键调用
        if (requestCode == REQUEST_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                initializeMap();
            } else {
                Toast.makeText(this, "权限被拒绝,部分功能受限", Toast.LENGTH_SHORT).show();
            }
        }
    }


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

        // 初始化地图
        MapsInitializer.updatePrivacyShow(this, true, true);
        MapsInitializer.updatePrivacyAgree(this, true);
        mMapView = findViewById(R.id.map);
        mMapView.onCreate(savedInstanceState);

        initializeMap();
        setupLocationStyle();
        addMarkers();
        addTiananmenFence();

    }

    private void initializeMap() {
        if (aMap == null) {
            aMap = mMapView.getMap();
            mClientInAndStayAction = new GeoFenceClient(getApplicationContext());
            mClientInAndStayAction.createPendingIntent(GEOFENCE_BROADCAST_ACTION);
            mClientInAndStayAction.setActivateAction(
                    GeoFenceClient.GEOFENCE_IN | GeoFenceClient.GEOFENCE_STAYED
            );

            // 设置信息窗口适配器
            aMap.setInfoWindowAdapter(this);
            // 设置Marker点击监听器
            aMap.setOnMarkerClickListener(this);

            // 初始地图位置和缩放级别
            aMap.animateCamera(CameraUpdateFactory.zoomTo(16));
            aMap.getUiSettings().setScaleControlsEnabled(true);
        }
    }

    private void setupLocationStyle() {
        MyLocationStyle myLocationStyle = new MyLocationStyle();
        myLocationStyle.interval(6000);
        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_SHOW);
        aMap.setMyLocationStyle(myLocationStyle);
        aMap.setMyLocationEnabled(true);
    }


    //这里可以通过数据库进行添加点

    private void addMarkers() {
        // 使用自定义方法创建带数据的Marker
        addMarker(28.711666, 115.826600, "AAA水果批发商小王", "苹果");
        addMarker(28.711667, 115.826750, "AAA水果批发商小李", "芒果");
        addMarker(28.711680, 115.826450, "AAA水果批发商小张", "草莓");
        // 东北地区
        addMarker(45.8038, 126.5340, "哈尔滨水果批发商老刘", "蓝莓"); // 黑龙江哈尔滨
        addMarker(43.8171, 125.3235, "长春水果批发商孙姐", "人参果"); // 吉林长春
        addMarker(41.8354, 123.4299, "沈阳水果批发商老金", "南果梨"); // 辽宁沈阳

        // 华北地区
        addMarker(39.9042, 116.4074, "北京新发地批发市场", "平谷大桃"); // 北京
        addMarker(37.8706, 112.5489, "太原水果批发商老陈", "沙金红杏"); // 山西太原
        addMarker(38.0428, 114.5149, "石家庄水果批发商赵总", "赞皇大枣"); // 河北石家庄

        // 华东地区
        addMarker(31.2304, 121.4737, "上海西郊国际批发", "南汇水蜜桃"); // 上海
        addMarker(30.2595, 120.2194, "杭州水果批发商王姐", "塘栖枇杷"); // 浙江杭州
        addMarker(32.0603, 118.7969, "南京众彩批发市场", "固城湖螃蟹"); // 江苏南京
        addMarker(36.6512, 117.1201, "济南堤口批发市场", "烟台樱桃"); // 山东济南

        // 华中地区
        addMarker(30.5951, 114.2999, "武汉光霞果批市场", "梁子湖螃蟹"); // 湖北武汉
        addMarker(28.1941, 112.9723, "长沙红星批发市场", "炎陵黄桃"); // 湖南长沙
        addMarker(34.7473, 113.6253, "郑州万邦物流城", "灵宝苹果"); // 河南郑州

        // 华南地区
        addMarker(23.1291, 113.2644, "广州江南果菜市场", "增城荔枝"); // 广东广州
        addMarker(20.0444, 110.1999, "海口南北水果市场", "文昌椰子"); // 海南海口
        addMarker(22.8176, 108.3663, "南宁海吉星市场", "百色芒果"); // 广西南宁

        // 西北地区
        addMarker(34.3416, 108.9398, "西安雨润批发市场", "周至猕猴桃"); // 陕西西安
        addMarker(36.0611, 103.8343, "兰州大青山市场", "白兰瓜"); // 甘肃兰州
        addMarker(43.8256, 87.6168, "乌鲁木齐九鼎市场", "哈密瓜"); // 新疆乌鲁木齐

        // 西南地区
        addMarker(29.6535, 91.1705, "拉萨药王山市场", "林芝苹果"); // 西藏拉萨
        addMarker(25.0433, 102.7062, "昆明金马正昌市场", "蒙自石榴"); // 云南昆明
        addMarker(26.6470, 106.6302, "贵阳石板哨市场", "修文猕猴桃"); // 贵州贵阳
        addMarker(30.5728, 104.0668, "成都濛阳农批市场", "攀枝花芒果"); // 四川成都

        // 特别行政区
        addMarker(22.3193, 114.1694, "香港长沙湾市场", "菲律宾香蕉"); // 香港


    }

    private void addMarker(double lat, double lng, String title, String phone) {
        LatLng position = new LatLng(lat, lng);
        aMap.addMarker(new MarkerOptions()
                .position(position)
                .title(title)
                .snippet("售卖商品: " + phone)
                .draggable(false));
    }

    // 实现信息窗口布局
    @Override
    public View getInfoWindow(Marker marker) {
        View infoWindow = getLayoutInflater().inflate(R.layout.custom_info_window, null);
        renderInfoWindow(marker, infoWindow);
        return infoWindow;
    }

    @Override
    public View getInfoContents(Marker marker) {
        return null; // 使用默认信息窗口背景时返回null
    }

    private void renderInfoWindow(Marker marker, View view) {
        TextView title = view.findViewById(R.id.info_window_title);
        TextView content = view.findViewById(R.id.info_window_content);

        title.setText(marker.getTitle());
        content.setText(marker.getSnippet());
    }

    // 处理Marker点击事件
    @Override
    public boolean onMarkerClick(Marker marker) {
        // 显示信息窗口(第二个参数为是否强制使用默认布局)
        marker.showInfoWindow();
        return true; // 消费点击事件
    }


    // 添加多边形地理围栏(兼容2023版SDK)
    private void addPolygon(String fenceName, List<LatLng> points) {
        if (points == null || points.size() < 3) {
            Toast.makeText(this, "多边形至少需要3个点", Toast.LENGTH_SHORT).show();
            return;
        }

        // 生成唯一围栏ID
        String fenceId = "polygon_" + mCustomID++;

        // 转换坐标点格式
        List<DPoint> dPoints = new ArrayList<>();
        for (LatLng point : points) {
            dPoints.add(new DPoint(point.latitude, point.longitude));
        }

        // 正确调用方式(关键修改点)
        mClientInAndStayAction.addGeoFence(
                dPoints,               // 参数1: 多边形顶点坐标(必须闭合)
                fenceId                // 参数2: 自定义围栏ID
        );

        // 绘制多边形到地图
        PolygonOptions options = new PolygonOptions()
                .addAll(points)
                .fillColor(0x5566CCFF)    // 填充色(带透明度)
                .strokeColor(Color.BLUE)  // 边框色
                .strokeWidth(5);         // 边框宽度(px)

        Polygon polygon = aMap.addPolygon(options);
        mCustomEntitys.put(fenceId, polygon);

        // 设置围栏监听(新增)
        mClientInAndStayAction.setGeoFenceListener(new GeoFenceListener() {
            @Override
            public void onGeoFenceCreateFinished(List<GeoFence> geoFences, int errorCode, String msg) {
                if (errorCode == GeoFence.ADDGEOFENCE_SUCCESS) {
                    runOnUiThread(() ->
                            Toast.makeText(MapActivity.this, fenceName + "围栏创建成功", Toast.LENGTH_SHORT).show()
                    );
                }
            }
        });

        // 移动视角到围栏中心
        aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(points.get(0), 15));
    }

    //这里通过数据库进行添加电子围栏的多边形
    private void addTiananmenFence() {
        List<LatLng> tiananmenArea = new ArrayList<>();
        // 添加闭合坐标点(示例数据)
        tiananmenArea.add(new LatLng(39.908722, 116.397499)); // 天安门中心
        tiananmenArea.add(new LatLng(39.910000, 116.395000)); // 西北角
        tiananmenArea.add(new LatLng(39.909500, 116.400000));  // 东北角
        tiananmenArea.add(tiananmenArea.get(0)); // 闭合多边形

        addPolygon("天安门核心区", tiananmenArea);
    }

    // 修改onStart方法中的注册逻辑
    @Override
    protected void onStart() {
        super.onStart();

        // 创建带安全标志的广播过滤器
        IntentFilter filter = new IntentFilter(GEOFENCE_BROADCAST_ACTION);

        // 适配Android 13+广播权限要求
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            registerReceiver(
                    mGeoFenceReceiver,
                    filter,
                    Context.RECEIVER_NOT_EXPORTED // 禁止外部应用访问
            );
        } else {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                registerReceiver(mGeoFenceReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
            }
        }

        createNotificationChannel();
    }

    @Override
    protected void onStop() {
        super.onStop();
        // 取消注册接收器
        unregisterReceiver(mGeoFenceReceiver);
    }

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = "地理围栏警报";
            String description = "电子围栏越界通知";
            int importance = NotificationManager.IMPORTANCE_HIGH;

            NotificationChannel channel = new NotificationChannel(ALERT_CHANNEL_ID, name, importance);
            channel.setDescription(description);

            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }
    }

    // 在MapActivity中
    private final BroadcastReceiver mGeoFenceReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (!isValidBroadcast(intent)) return;

            Bundle bundle = intent.getExtras();
            if (bundle == null) return;

            // 解析基础数据
            int status = bundle.getInt(GeoFence.BUNDLE_KEY_FENCESTATUS);
            String fenceId = bundle.getString(GeoFence.BUNDLE_KEY_FENCEID);
            GeoFence fence = bundle.getParcelable(GeoFence.BUNDLE_KEY_FENCE);

            // 分发事件处理
            handleGeoFenceEvent(context, status, fenceId, fence);
        }

        private boolean isValidBroadcast(Intent intent) {
            return intent != null &&
                    GEOFENCE_BROADCAST_ACTION.equals(intent.getAction());
        }

        private void handleGeoFenceEvent(Context context, int status,
                                         String fenceId, GeoFence fence) {
            switch (status) {
                case GeoFence.STATUS_IN:
                    handleEnter(context, fenceId);
                    break;

                case GeoFence.STATUS_OUT:
                    handleExit(context, fence);
                    break;

                case GeoFence.STATUS_STAYED:
                    handleStay(fence);
                    break;
            }
        }

        private void handleEnter(Context context, String fenceId) {
            // 记录日志
            GeoFenceLogger.logEnter(fenceId);

            // UI提示
            Toast.makeText(context, "进入监控区域", Toast.LENGTH_SHORT).show();
        }

        private void handleExit(Context context, GeoFence fence) {
            if (fence == null) return;

            // 记录日志
            GeoFenceLogger.logExit(fence.getFenceId());

            // 触发警报
            String alertMsg = "⚠️ 已离开安全区域: " + fence.getFenceId();
            Toast.makeText(context, alertMsg, Toast.LENGTH_LONG).show();
            sendAlertNotification(context, alertMsg);
        }

        private void handleStay(GeoFence fence) {
            if (fence == null) return;

            // 记录日志
            GeoFenceLogger.logStay(fence.getFenceId(), fence.getExpiration());
        }
    };


    private void sendAlertNotification(Context context, String message) {
        NotificationManager manager = (NotificationManager)
                getSystemService(Context.NOTIFICATION_SERVICE);

        // 构建通知
        Notification notification = new NotificationCompat.Builder(context, ALERT_CHANNEL_ID)
                .setSmallIcon(R.drawable.ic_alert)
                .setContentTitle("区域越界警告")
                .setContentText(message)
                .setPriority(NotificationCompat.PRIORITY_MAX)
                .setAutoCancel(true)
                .build();

        // 显示通知
        if (manager != null) {
            manager.notify(new Random().nextInt(1000), notification);
        }
    }

    // 生命周期方法
    @Override
    protected void onResume() {
        super.onResume();
        mMapView.onResume();
    }

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

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

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

标志.XML

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24">
    <path
        android:fillColor="#FF0000"
        android:pathData="M12,2L3,20h18L12,2zM13,16h-2v-2h2v2zm0-4h-2V8h2v4z"/>
</vector>

请添加图片描述

效果图:

请添加图片描述
请添加图片描述


网站公告

今日签到

点亮在社区的每一天
去签到