├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── xuezhy │ │ └── drawmap │ │ ├── BaseActivity.java │ │ ├── EventCode.java │ │ ├── FirstActivity.java │ │ ├── MainActivity.java │ │ ├── MyApplication.java │ │ ├── bean │ │ ├── BaseEvent.java │ │ ├── DrawCircle.java │ │ ├── DrawLatLng.java │ │ ├── LatlngBean.java │ │ └── LocationEvent.java │ │ └── utils │ │ ├── CommonUtil.java │ │ ├── DensityUtil.java │ │ ├── DrawMapUtil.java │ │ ├── GoogleMapUtil.java │ │ ├── GpsManager.java │ │ ├── PopWindowUtil.java │ │ ├── ScreenUtil.java │ │ └── StatusBarUtil.java │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ ├── ic_launcher_background.xml │ ├── my_cursor.xml │ ├── popu_dialog_bg.xml │ ├── shape_input_dialog.xml │ └── shape_map_draw_point_white.xml │ ├── layout │ ├── act_first.xml │ ├── act_main.xml │ ├── layout_dialog_notice.xml │ ├── layout_ensure_notitle_dialog.xml │ ├── map_draw_marker.xml │ ├── map_draw_marker_big_white.xml │ └── map_draw_marker_small_white.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── arrow_back.png │ ├── arrow_next_white.png │ ├── ic_launcher.png │ ├── ic_launcher_round.png │ ├── iv_cancel.png │ ├── iv_delete.png │ ├── map_handle.png │ └── map_positioning.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── ids.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DaodeDemo 2 | 3 | 高德地图和百度地图平时大家用的都比较多,两者也都提供了很多的api供我们使用,但是是有时候复杂点的需求就需要我们自己去实现了,今天我要分享的是如何使用高德地图绘制一个多边形多来,移动某个点可以调节多边形形状,先展示下我的项目实现的效果图。 4 | 5 | 6 | 7 | ![img](https://upload-images.jianshu.io/upload_images/15072242-656e8c187ff98812.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 8 | 9 | 你可以下载demoapk体验:https://d.3appstore.com/dw56 10 | 11 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 29 5 | buildToolsVersion "29.0.0" 6 | defaultConfig { 7 | applicationId "com.xuezhy.drawmap" 8 | minSdkVersion 19 9 | targetSdkVersion 29 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 13 | 14 | ndk { 15 | //设置支持的SO库架构(开发者可以根据需要,选择一个或多个平台的so) 16 | abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86","x86_64" 17 | } 18 | } 19 | 20 | 21 | compileOptions { 22 | sourceCompatibility JavaVersion.VERSION_1_8 23 | targetCompatibility JavaVersion.VERSION_1_8 24 | } 25 | 26 | } 27 | 28 | dependencies { 29 | implementation fileTree(include: ['*.jar'], dir: 'libs') 30 | 31 | implementation 'com.android.support:appcompat-v7:28.0.0' 32 | implementation 'com.android.support.constraint:constraint-layout:1.1.0-beta5' 33 | implementation 'com.orhanobut:hawk:2.0.1' 34 | implementation 'org.greenrobot:eventbus:3.1.1' 35 | // For developers using the Android Support Library 36 | implementation 'pub.devrel:easypermissions:2.0.1' 37 | 38 | //3D地图so及jar 39 | implementation 'com.amap.api:3dmap:latest.integration' 40 | // 定位功能 41 | implementation 'com.amap.api:location:latest.integration' 42 | implementation 'com.amap.api:search:latest.integration' 43 | 44 | testImplementation 'junit:junit:4.12' 45 | androidTestImplementation 'com.android.support.test:runner:1.0.1' 46 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' 47 | 48 | } 49 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 51 | 52 | 55 | 56 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 68 | 69 | 70 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuezhy/drawmap/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.xuezhy.drawmap; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.app.AppCompatActivity; 6 | import org.greenrobot.eventbus.EventBus; 7 | 8 | public abstract class BaseActivity extends AppCompatActivity { 9 | //是否注册eventBus 10 | public Boolean isRegisterEventBus = false; 11 | 12 | 13 | @Override 14 | protected void onCreate(@Nullable Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | if (onBindLayout() != -1) { 17 | setContentView(onBindLayout()); 18 | } 19 | isRegisterEventBus = (isRegisterEventBus() == null ? false : isRegisterEventBus()); 20 | if (isRegisterEventBus) { 21 | EventBus.getDefault().register(this); 22 | } 23 | initView(savedInstanceState); 24 | initData(); 25 | } 26 | 27 | 28 | public abstract int onBindLayout(); 29 | 30 | public abstract void initView(Bundle savedInstanceState); 31 | 32 | public abstract void initData(); 33 | 34 | protected abstract Boolean isRegisterEventBus(); 35 | 36 | 37 | @Override 38 | protected void onDestroy() { 39 | super.onDestroy(); 40 | if (isRegisterEventBus) { 41 | EventBus.getDefault().unregister(this); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuezhy/drawmap/EventCode.java: -------------------------------------------------------------------------------- 1 | package com.xuezhy.drawmap; 2 | 3 | /** 4 | * 类功能描述: 5 | * 作者: zhongyangxue 6 | * 创建时间: 2020/5/16 12:16 AM 7 | * 邮箱 1366411749@qq.com 8 | * 版本: 1.0 9 | */ 10 | public class EventCode { 11 | public static int LOCATION_CODE = 1001; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuezhy/drawmap/FirstActivity.java: -------------------------------------------------------------------------------- 1 | package com.xuezhy.drawmap; 2 | 3 | import android.Manifest; 4 | import android.content.Intent; 5 | import android.location.SettingInjectorService; 6 | import android.os.Bundle; 7 | import android.support.annotation.NonNull; 8 | import android.util.Log; 9 | 10 | import com.amap.api.services.core.ServiceSettings; 11 | 12 | import java.util.List; 13 | import pub.devrel.easypermissions.AfterPermissionGranted; 14 | import pub.devrel.easypermissions.AppSettingsDialog; 15 | import pub.devrel.easypermissions.EasyPermissions; 16 | 17 | public class FirstActivity extends BaseActivity implements EasyPermissions.PermissionCallbacks, 18 | EasyPermissions.RationaleCallbacks { 19 | private static final String TAG = "FirstActivity"; 20 | private static final String[] LOCATION_AND_CONTACTS = 21 | {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, 22 | Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}; 23 | private static final int RC_LOCATION_CONTACTS_PERM = 124; 24 | 25 | @Override 26 | public int onBindLayout() { 27 | return R.layout.act_first; 28 | } 29 | 30 | @Override 31 | public void initView(Bundle savedInstanceState) { 32 | 33 | } 34 | 35 | @Override 36 | public void initData() { 37 | if (hasLocationAndContactsPermissions() && hasStoragePermission()) { 38 | goToMainActivity(); 39 | } else { 40 | EasyPermissions.requestPermissions( 41 | this, 42 | getString(R.string.rationale_location_storage), 43 | RC_LOCATION_CONTACTS_PERM, 44 | LOCATION_AND_CONTACTS); 45 | } 46 | 47 | } 48 | 49 | private boolean hasLocationAndContactsPermissions() { 50 | return EasyPermissions.hasPermissions(this, LOCATION_AND_CONTACTS); 51 | } 52 | 53 | 54 | private boolean hasStoragePermission() { 55 | return EasyPermissions.hasPermissions(this, Manifest.permission.WRITE_EXTERNAL_STORAGE); 56 | } 57 | 58 | @AfterPermissionGranted(RC_LOCATION_CONTACTS_PERM) 59 | public void locationAndContactsTask() { 60 | if (hasLocationAndContactsPermissions()) { 61 | // Have permissions, do the thing! 62 | goToMainActivity(); 63 | } else { 64 | // Ask for both permissions 65 | EasyPermissions.requestPermissions( 66 | this, 67 | getString(R.string.rationale_location_storage), 68 | RC_LOCATION_CONTACTS_PERM, 69 | LOCATION_AND_CONTACTS); 70 | } 71 | } 72 | 73 | @Override 74 | protected Boolean isRegisterEventBus() { 75 | return null; 76 | } 77 | 78 | 79 | @Override 80 | public void onRequestPermissionsResult(int requestCode, 81 | @NonNull String[] permissions, 82 | @NonNull int[] grantResults) { 83 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 84 | 85 | // EasyPermissions handles the request result. 86 | EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this); 87 | } 88 | 89 | @Override 90 | public void onPermissionsGranted(int requestCode, @NonNull List perms) { 91 | Log.d(TAG, "onPermissionsGranted:" + requestCode + ":" + perms.size()); 92 | } 93 | 94 | @Override 95 | public void onPermissionsDenied(int requestCode, @NonNull List perms) { 96 | Log.d(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size()); 97 | 98 | // (Optional) Check whether the user denied any permissions and checked "NEVER ASK AGAIN." 99 | // This will display a dialog directing them to enable the permission in app settings. 100 | if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) { 101 | new AppSettingsDialog.Builder(this).build().show(); 102 | } 103 | } 104 | 105 | @Override 106 | public void onActivityResult(int requestCode, int resultCode, Intent data) { 107 | super.onActivityResult(requestCode, resultCode, data); 108 | 109 | if (requestCode == AppSettingsDialog.DEFAULT_SETTINGS_REQ_CODE) { 110 | String yes = getString(R.string.yes); 111 | String no = getString(R.string.no); 112 | 113 | // Do something after user returned from app settings screen, like showing a Toast. 114 | } 115 | } 116 | 117 | @Override 118 | public void onRationaleAccepted(int requestCode) { 119 | Log.d(TAG, "onRationaleAccepted:" + requestCode); 120 | } 121 | 122 | @Override 123 | public void onRationaleDenied(int requestCode) { 124 | Log.d(TAG, "onRationaleDenied:" + requestCode); 125 | } 126 | 127 | private void goToMainActivity() { 128 | ServiceSettings.updatePrivacyShow(this,true,true); 129 | ServiceSettings.updatePrivacyAgree(this,true); 130 | startActivity(new Intent(this, MainActivity.class)); 131 | finish(); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuezhy/drawmap/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.xuezhy.drawmap; 2 | 3 | import android.graphics.Color; 4 | import android.graphics.Point; 5 | import android.os.Bundle; 6 | import android.text.TextUtils; 7 | import android.util.Log; 8 | import android.view.MotionEvent; 9 | import android.view.View; 10 | import android.widget.ImageView; 11 | import com.amap.api.maps.AMap; 12 | import com.amap.api.maps.AMapOptions; 13 | import com.amap.api.maps.AMapUtils; 14 | import com.amap.api.maps.CameraUpdateFactory; 15 | import com.amap.api.maps.MapView; 16 | import com.amap.api.maps.model.BitmapDescriptor; 17 | import com.amap.api.maps.model.BitmapDescriptorFactory; 18 | import com.amap.api.maps.model.LatLng; 19 | import com.amap.api.maps.model.Marker; 20 | import com.amap.api.maps.model.MarkerOptions; 21 | import com.amap.api.maps.model.MyLocationStyle; 22 | import com.amap.api.maps.model.Polygon; 23 | import com.amap.api.maps.model.PolygonOptions; 24 | import com.amap.api.maps.model.Polyline; 25 | import com.amap.api.maps.model.PolylineOptions; 26 | import com.amap.api.maps.model.TileOverlayOptions; 27 | import com.orhanobut.hawk.Hawk; 28 | import com.xuezhy.drawmap.bean.LocationEvent; 29 | import com.xuezhy.drawmap.bean.DrawLatLng; 30 | import com.xuezhy.drawmap.bean.LatlngBean; 31 | import com.xuezhy.drawmap.utils.CommonUtil; 32 | import com.xuezhy.drawmap.utils.DensityUtil; 33 | import com.xuezhy.drawmap.utils.DrawMapUtil; 34 | import com.xuezhy.drawmap.utils.GoogleMapUtil; 35 | import com.xuezhy.drawmap.utils.GpsManager; 36 | import com.xuezhy.drawmap.utils.StatusBarUtil; 37 | import org.greenrobot.eventbus.Subscribe; 38 | import org.greenrobot.eventbus.ThreadMode; 39 | import java.util.ArrayList; 40 | import java.util.HashMap; 41 | import java.util.List; 42 | import java.util.Map; 43 | 44 | 45 | public class MainActivity extends BaseActivity implements AMap.OnMapClickListener, AMap.OnMarkerClickListener, View.OnClickListener { 46 | public double latitude = 39.90613850442552; //默认北京 47 | public double longitude = 116.40717000000001; //默认北京 48 | private TileOverlayOptions options; 49 | private Boolean hasDrawFinish = false; //是否绘制完毕 50 | private List points = new ArrayList<>(); 51 | private ArrayList circleList = new ArrayList<>(); 52 | private int CIRCLE_DEFAULT; 53 | private Polyline polyline; 54 | private Polygon polygon; 55 | private int movePosition = -1; 56 | private int signMarkPosition = -1; 57 | private Marker signMark; 58 | private Boolean canClickMap = false; 59 | private MapView mMapView = null; 60 | private Boolean isDrawPress = false; 61 | private Map distanceMap = new HashMap<>(); 62 | private Boolean pressCircle_isBig = false; 63 | private Boolean moveSign_center = false; 64 | private Boolean moveSign_right = false; 65 | private Boolean isFirstPoint = false; 66 | private Boolean isLastPoint = false; 67 | private int down_x = 0; 68 | private int down_y = 0; 69 | private int move_x = 0; 70 | private int move_y = 0; 71 | 72 | private AMap aMap; 73 | private ImageView ivCancel; 74 | private ImageView ivDelete; 75 | private ImageView ivPre; 76 | private ImageView ivNext; 77 | 78 | @Override 79 | public int onBindLayout() { 80 | return R.layout.act_main; 81 | } 82 | 83 | 84 | @Override 85 | public void initView(Bundle savedInstanceState) { 86 | StatusBarUtil.setTranslucentForImageViewInFragment(this, 0, null); 87 | 88 | //获取地图控件引用 89 | mMapView = (MapView) findViewById(R.id.map); 90 | //tools 91 | ivCancel = findViewById(R.id.iv_cancel); 92 | ivDelete = findViewById(R.id.iv_delete); 93 | ivPre = findViewById(R.id.iv_pre); 94 | ivNext = findViewById(R.id.iv_next); 95 | ivNext.setOnClickListener(this); 96 | ivPre.setOnClickListener(this); 97 | ivDelete.setOnClickListener(this); 98 | ivCancel.setOnClickListener(this); 99 | 100 | 101 | //在activity执行onCreate时执行mMapView.onCreate(savedInstanceState),创建地图 102 | mMapView.onCreate(savedInstanceState); 103 | if (aMap == null) { 104 | aMap = mMapView.getMap(); 105 | } 106 | aMap.getUiSettings().setLogoPosition(AMapOptions.LOGO_POSITION_BOTTOM_RIGHT);//Logo位置(地图右下角) 107 | aMap.getUiSettings().setRotateGesturesEnabled(false);//关闭旋转手势 108 | aMap.getUiSettings().setTiltGesturesEnabled(false);//关闭倾斜手势 109 | aMap.getUiSettings().setMyLocationButtonEnabled(true);//设置默认定位按钮是否显示,非必需设置。 110 | //隐藏高德地图默认的放大缩小控件 111 | aMap.getUiSettings().setZoomControlsEnabled(false); 112 | aMap.setMapType(AMap.MAP_TYPE_SATELLITE); 113 | MyLocationStyle style = new MyLocationStyle(); 114 | BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.mipmap.map_positioning); 115 | style.myLocationIcon(bitmapDescriptor); 116 | style.strokeColor(Color.argb(0, 0, 0, 0));// 设置圆形的边框颜色 117 | style.radiusFillColor(Color.argb(0, 0, 0, 0));// 设置圆形的填充颜色 118 | // style.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER); 119 | style.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE); 120 | aMap.setMyLocationStyle(style); 121 | // 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false 122 | aMap.setMyLocationEnabled(true); 123 | aMap.setOnMapClickListener(this);// 对amap添加单击地图事件监听器 124 | options = GoogleMapUtil.getGooleMapTileOverlayOptions(); //有的地区没有图层切片,可以调用谷歌接口获取切片数据(任意地方都有数据) 125 | aMap.addTileOverlay(options); 126 | aMap.setLoadOfflineData(true); 127 | aMap.setOnMarkerClickListener(this); 128 | 129 | if (Hawk.get("latitude") != null && Hawk.get("longitude") != null) { 130 | //说明没有定位过,定位到 131 | latitude = Hawk.get("latitude"); 132 | longitude = Hawk.get("longitude"); 133 | } 134 | LatLng latLng = new LatLng(latitude, longitude); 135 | aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 18)); 136 | aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 18)); 137 | 138 | } 139 | 140 | @Override 141 | public void initData() { 142 | canClickMap = true; 143 | CIRCLE_DEFAULT = DensityUtil.dip2px(this, 20.0f); 144 | try { 145 | GpsManager.getInstance().init(this); 146 | } catch (Exception e) { 147 | e.printStackTrace(); 148 | } 149 | //通过 检查定位又没有打开 150 | if (GpsManager.getInstance().checkGps()) { 151 | //开始定位 152 | GpsManager.getInstance().startLocation(); 153 | } 154 | } 155 | 156 | @Override 157 | protected Boolean isRegisterEventBus() { 158 | //如果返回true 必须重写@Subscribe(threadMode = ThreadMode.MAIN) 如果返回false则不需要做任何事 159 | return true; 160 | } 161 | 162 | @Subscribe(threadMode = ThreadMode.MAIN) 163 | public void onEventMainThread(LocationEvent event) { 164 | if (event.getCode() == EventCode.LOCATION_CODE && event.getData() instanceof LatlngBean) { 165 | LatlngBean latLng = (LatlngBean) event.getData(); 166 | try { 167 | if (latLng == null) { 168 | return; 169 | } 170 | if (Hawk.get("latitude") == null || Hawk.get("longitude") == null) { 171 | //第一次 172 | latitude = latLng.getLatitude(); 173 | longitude = latLng.getLongitude(); 174 | } else { 175 | //判断上次经纬度和这次的经纬度相差多少米 超过界限就移动视图 176 | double distance = (int) AMapUtils.calculateLineDistance( 177 | new LatLng(Hawk.get("latitude", 0), Hawk.get("longitude", 0)), 178 | new LatLng(latLng.getLatitude(), latLng.getLongitude())); 179 | Log.e("xuezhy", "distance=" + distance); 180 | if (distance < 1000) { 181 | return; 182 | } 183 | } 184 | 185 | LatLng newLatlng = new LatLng(latitude, longitude); 186 | aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(newLatlng, 18)); 187 | aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(newLatlng, 18)); 188 | 189 | } catch (Exception e) { 190 | e.printStackTrace(); 191 | } 192 | 193 | } 194 | } 195 | 196 | 197 | @Override 198 | public void onClick(View v) { 199 | int id = v.getId(); 200 | if (id == R.id.iv_cancel) { 201 | if (hasDrawFinish) { 202 | //已完成 203 | circleList.get(circleList.size() - 1).remove(); 204 | circleList.remove(circleList.size() - 1); 205 | points.remove(points.size() - 1); 206 | hasDrawFinish = false; 207 | } else { 208 | //还没完成 209 | if (circleList.size() > 0) { 210 | //删除最后一个 211 | circleList.get(circleList.size() - 1).remove(); 212 | circleList.remove(circleList.size() - 1); 213 | points.remove(points.size() - 1); 214 | 215 | if (circleList.size() > 1) { 216 | //删除倒数第二个 217 | circleList.get(circleList.size() - 1).remove(); 218 | circleList.remove(circleList.size() - 1); 219 | points.remove(points.size() - 1); 220 | } 221 | } 222 | 223 | } 224 | if (signMark != null) { 225 | signMark.remove(); 226 | signMarkPosition = -1; 227 | } 228 | drawLine(); 229 | } else if (id == R.id.iv_delete) { 230 | for (int i = 0; i < circleList.size(); i++) { 231 | circleList.get(i).remove(); 232 | } 233 | circleList.clear(); 234 | points.clear(); 235 | if (polygon != null) { 236 | polygon.remove(); 237 | } 238 | if (polyline != null) { 239 | polyline.remove(); 240 | } 241 | 242 | if (signMark != null) { 243 | signMark.remove(); 244 | movePosition = -1; 245 | signMarkPosition = -1; 246 | } 247 | 248 | hasDrawFinish = false; 249 | } else if (id == R.id.iv_pre) { 250 | if (signMarkPosition == -1) { 251 | return; 252 | } 253 | if (signMarkPosition == 0) { 254 | DrawLatLng drawLatLng = points.get(points.size() - 1); 255 | signMarkPosition = points.size() - 1; 256 | drawSignMark(drawLatLng.getLatLng()); 257 | } else { 258 | DrawLatLng drawLatLng = points.get(signMarkPosition - 1); 259 | signMarkPosition = signMarkPosition - 1; 260 | drawSignMark(drawLatLng.getLatLng()); 261 | } 262 | } else if (id == R.id.iv_next) { 263 | if (signMarkPosition == -1) { 264 | return; 265 | } 266 | 267 | if (signMarkPosition == points.size() - 1) { 268 | DrawLatLng drawLatLng = points.get(0); 269 | signMarkPosition = 0; 270 | drawSignMark(drawLatLng.getLatLng()); 271 | } else { 272 | DrawLatLng drawLatLng = points.get(signMarkPosition + 1); 273 | signMarkPosition = signMarkPosition + 1; 274 | drawSignMark(drawLatLng.getLatLng()); 275 | } 276 | } 277 | } 278 | 279 | 280 | @Override 281 | protected void onDestroy() { 282 | super.onDestroy(); 283 | //在activity执行onDestroy时执行mMapView.onDestroy(),销毁地图 284 | mMapView.onDestroy(); 285 | } 286 | 287 | @Override 288 | protected void onResume() { 289 | super.onResume(); 290 | //在activity执行onResume时执行mMapView.onResume (),重新绘制加载地图 291 | mMapView.onResume(); 292 | } 293 | 294 | @Override 295 | protected void onPause() { 296 | super.onPause(); 297 | //在activity执行onPause时执行mMapView.onPause (),暂停地图的绘制 298 | mMapView.onPause(); 299 | } 300 | 301 | @Override 302 | protected void onSaveInstanceState(Bundle outState) { 303 | super.onSaveInstanceState(outState); 304 | //在activity执行onSaveInstanceState时执行mMapView.onSaveInstanceState (outState),保存地图当前的状态 305 | mMapView.onSaveInstanceState(outState); 306 | } 307 | 308 | 309 | @Override 310 | public void onMapClick(LatLng latLng) { 311 | if (aMap == null || isDrawPress || !canClickMap) { 312 | return; 313 | } 314 | 315 | //如果没有 316 | if (!hasDrawFinish) { 317 | if (points.size() == 0) { 318 | //画个大圆圈 319 | DrawLatLng myLatlng = new DrawLatLng(latLng, true); 320 | circleList.add(drawBigCircle(latLng, 0)); 321 | points.add(myLatlng); 322 | // upDateLandInfo(); 323 | return; 324 | } 325 | //判断是否点击页面的点 326 | for (int i = 0; i < points.size(); i++) { 327 | double distance = DrawMapUtil.getScreenDistance(aMap, points.get(i).getLatLng(), latLng); 328 | // double distance = (int) AMapUtils.calculateLineDistance(points.get(i).getLatLng(), latLng); 329 | if (distance < CIRCLE_DEFAULT) { 330 | if (points.size() > 1) { 331 | DrawLatLng drawLatLng = points.get(i); 332 | //判断该点是不是小点 333 | 334 | if (!drawLatLng.getBigCircle()) { 335 | 336 | drawOneBigAndTwoSmallCirclr(i, drawLatLng.getLatLng()); 337 | return; 338 | } 339 | } 340 | 341 | return; 342 | } 343 | 344 | } 345 | 346 | //先画小圈圈 347 | LatLng centerLatLng = getCenterLatlng(points.get(points.size() - 1).getLatLng(), latLng); 348 | circleList.add(drawSmallCircle(centerLatLng, circleList.size())); 349 | 350 | //再画大圈圈 351 | 352 | circleList.add(drawBigCircle(latLng, circleList.size())); 353 | points.add(new DrawLatLng(centerLatLng, false)); 354 | points.add(new DrawLatLng(latLng, true)); 355 | 356 | drawLine(); 357 | return; 358 | 359 | } 360 | 361 | //判断是否点击页面的点 362 | for (int i = 0; i < points.size(); i++) { 363 | double distance = DrawMapUtil.getScreenDistance(aMap, points.get(i).getLatLng(), latLng); 364 | // double distance = (int) AMapUtils.calculateLineDistance(points.get(i).getLatLng(), latLng); 365 | if (distance < CIRCLE_DEFAULT) { 366 | DrawLatLng drawLatLng = points.get(i); 367 | //选中了该点 368 | //判断是大圆圈还是小圆圈 369 | if (!points.get(i).getBigCircle()) { 370 | drawOneBigAndTwoSmallCirclr(i, drawLatLng.getLatLng()); 371 | return; 372 | } 373 | 374 | /******选中标签****************/ 375 | signMarkPosition = i; 376 | drawSignMark(points.get(i).getLatLng()); 377 | 378 | return; 379 | } 380 | 381 | 382 | } 383 | 384 | } 385 | 386 | @Override 387 | public boolean onMarkerClick(Marker marker) { 388 | if (!canClickMap) { 389 | return false; 390 | } 391 | if (points.size() <= 2) { 392 | return false; 393 | } 394 | if (!hasDrawFinish && marker.getPosition().latitude == points.get(0).getLatLng().latitude 395 | && marker.getPosition().longitude == points.get(0).getLatLng().longitude) { 396 | //画小圈圈 397 | LatLng centerLatLng_last = getCenterLatlng(points.get(points.size() - 1).getLatLng(), points.get(0).getLatLng()); 398 | circleList.add(drawSmallCircle(centerLatLng_last, circleList.size())); 399 | points.add(new DrawLatLng(centerLatLng_last, false)); 400 | drawPolygon(); 401 | hasDrawFinish = true; 402 | } 403 | String title = marker.getTitle(); 404 | if (!TextUtils.isEmpty(title)) { 405 | int position = Integer.valueOf(title); 406 | signMarkPosition = position; 407 | drawSignMark(points.get(position).getLatLng()); 408 | } 409 | 410 | return true; 411 | } 412 | 413 | 414 | /** 415 | * 监听手势滑动 416 | * 417 | * @param ev 418 | * @return 419 | */ 420 | 421 | @Override 422 | public boolean dispatchTouchEvent(final MotionEvent ev) { 423 | 424 | if (points.size() <= 2 || !canClickMap) { 425 | return super.dispatchTouchEvent(ev); 426 | } 427 | try { 428 | if (MotionEvent.ACTION_DOWN == ev.getAction()) { 429 | down_x = (int) ev.getX(); 430 | down_y = (int) ev.getY(); 431 | move_x = (int) ev.getX(); 432 | move_y = (int) ev.getY(); 433 | } else if (MotionEvent.ACTION_MOVE == ev.getAction()) { 434 | if (isDrawPress) { 435 | handlePressEvent(ev); 436 | } else { 437 | move_x = (int) ev.getX(); 438 | move_y = (int) ev.getY(); 439 | double distance = Math.sqrt(Math.pow(down_x - move_x, 2) 440 | + Math.pow(down_y - move_y, 2)); 441 | if (distance > DensityUtil.dip2px(this, 10.0f)) { 442 | isDrawPress = true; 443 | handleDownTouchEvent(ev); 444 | } 445 | } 446 | 447 | } else if (MotionEvent.ACTION_UP == ev.getAction()) { 448 | handleMoveTouchEvent(); 449 | } 450 | } catch (Exception e) { 451 | 452 | } 453 | 454 | return super.dispatchTouchEvent(ev); 455 | 456 | } 457 | 458 | 459 | /**************************************************************绘制**************************************************************/ 460 | 461 | /** 462 | * 画大圆圈 463 | */ 464 | private Marker drawBigCircle(LatLng latLng, int position) { 465 | return aMap.addMarker(new MarkerOptions() 466 | .position(latLng) 467 | .anchor(0.5f, 0.5f) 468 | .title(String.valueOf(position)) 469 | .icon(BitmapDescriptorFactory.fromView(getLayoutInflater().inflate(R.layout.map_draw_marker_big_white, null)))); 470 | } 471 | 472 | /** 473 | * 画小圆圈 474 | */ 475 | private Marker drawSmallCircle(LatLng latLng, int position) { 476 | return aMap.addMarker(new MarkerOptions() 477 | .position(latLng) 478 | .anchor(0.5f, 0.5f) 479 | .title(String.valueOf(position)) 480 | .icon(BitmapDescriptorFactory.fromView(getLayoutInflater().inflate(R.layout.map_draw_marker_small_white, null)))); 481 | } 482 | 483 | /** 484 | * 获取两个经纬度的中点经纬度 485 | * 486 | * @param latLng1 487 | * @param latLng2 488 | * @return 489 | */ 490 | private LatLng getCenterLatlng(LatLng latLng1, LatLng latLng2) { 491 | Point point1 = aMap.getProjection().toScreenLocation(latLng1); 492 | Point point2 = aMap.getProjection().toScreenLocation(latLng2); 493 | Point centerPoint = new Point(CommonUtil.avg(point1.x, point2.x), 494 | CommonUtil.avg(point1.y, point2.y)); 495 | return aMap.getProjection().fromScreenLocation(centerPoint); 496 | } 497 | 498 | /** 499 | * 绘制线,把点连起来 500 | */ 501 | protected void drawLine() { 502 | 503 | if (polyline != null) { 504 | polyline.remove(); 505 | } 506 | 507 | if (polygon != null) { 508 | polygon.remove(); 509 | } 510 | 511 | if (aMap != null && points.size() > 0) { 512 | polyline = aMap.addPolyline(new PolylineOptions(). 513 | addAll(DrawMapUtil.drawLatlngToLatlng(points)).width(2).color(getResources().getColor(R.color.green)).zIndex(999)); 514 | } 515 | } 516 | 517 | private void drawOneBigAndTwoSmallCirclr(int i, LatLng latLng) { 518 | //再判断该点是不是最后一个点 519 | if (i == points.size() - 1) { 520 | /******左边圆圈****************/ 521 | LatLng centerLatLng_left = getCenterLatlng(points.get(i - 1).getLatLng(), points.get(i).getLatLng()); 522 | circleList.add(i, drawSmallCircle(centerLatLng_left, i)); 523 | points.add(i, new DrawLatLng(centerLatLng_left, false)); 524 | 525 | /******大圆圈****************/ 526 | circleList.get(i + 1).remove(); 527 | circleList.remove(i + 1); 528 | points.remove(i + 1); 529 | circleList.add(i + 1, drawBigCircle(latLng, i + 1)); 530 | points.add(i + 1, new DrawLatLng(latLng, true)); 531 | 532 | /******选中标签****************/ 533 | signMarkPosition = movePosition; 534 | drawSignMark(latLng); 535 | 536 | /******右边圆圈****************/ 537 | LatLng centerLatLng_right = getCenterLatlng(points.get(i + 1).getLatLng(), points.get(0).getLatLng()); 538 | circleList.add(drawSmallCircle(centerLatLng_right, circleList.size())); 539 | points.add(new DrawLatLng(centerLatLng_right, false)); 540 | return; 541 | } 542 | 543 | /******左边圆圈****************/ 544 | LatLng centerLatLng_left = getCenterLatlng(points.get(i - 1).getLatLng(), points.get(i).getLatLng()); 545 | circleList.add(i, drawSmallCircle(centerLatLng_left, i)); 546 | points.add(i, new DrawLatLng(centerLatLng_left, false)); 547 | 548 | /******大圆圈****************/ 549 | circleList.get(i + 1).remove(); 550 | circleList.remove(i + 1); 551 | points.remove(i + 1); 552 | circleList.add(i + 1, drawBigCircle(latLng, i + 1)); 553 | points.add(i + 1, new DrawLatLng(latLng, true)); 554 | 555 | /******选中标签****************/ 556 | signMarkPosition = movePosition; 557 | drawSignMark(latLng); 558 | 559 | /******右边圆圈****************/ 560 | LatLng centerLatLng_right = getCenterLatlng(points.get(i + 1).getLatLng(), points.get(i + 2).getLatLng()); 561 | circleList.add(i + 2, drawSmallCircle(centerLatLng_right, i + 2)); 562 | points.add(i + 2, new DrawLatLng(centerLatLng_right, false)); 563 | } 564 | 565 | 566 | /** 567 | * @param latLng 568 | */ 569 | private void drawSignMark(LatLng latLng) { 570 | LatLng centerLatlng = CommonUtil.getCenterOfDrawPoint(points); 571 | View view = getLayoutInflater().inflate(R.layout.map_draw_marker, null); 572 | /******选中标签****************/ 573 | if (signMark != null) { 574 | signMark.remove(); 575 | } 576 | 577 | signMark = aMap.addMarker(new MarkerOptions() 578 | .position(latLng).icon(BitmapDescriptorFactory.fromView(view))); 579 | //判断方向 580 | if (latLng.latitude > centerLatlng.latitude && latLng.longitude < centerLatlng.longitude) { 581 | //第一象限 582 | signMark.setRotateAngle(45); 583 | 584 | } else if (latLng.latitude < centerLatlng.latitude && latLng.longitude < centerLatlng.longitude) { 585 | //第二象限 586 | signMark.setRotateAngle(135); 587 | } else if (latLng.latitude < centerLatlng.latitude && latLng.longitude > centerLatlng.longitude) { 588 | //第三象限 589 | signMark.setRotateAngle(225); 590 | } else if (latLng.latitude > centerLatlng.latitude && latLng.longitude > centerLatlng.longitude) { 591 | //第四象限 592 | signMark.setRotateAngle(-45); 593 | } 594 | 595 | } 596 | 597 | /** 598 | * 绘制多边形 599 | */ 600 | private void drawPolygon() { 601 | 602 | if (polyline != null) { 603 | polyline.remove(); 604 | } 605 | 606 | if (polygon != null) { 607 | polygon.remove(); 608 | } 609 | 610 | // 声明 多边形参数对象 611 | PolygonOptions polygonOptions = new PolygonOptions(); 612 | // 添加 多边形的每个顶点(顺序添加) 613 | for (int i = 0; i < points.size(); i++) { 614 | polygonOptions.add(points.get(i).getLatLng()); 615 | } 616 | 617 | Boolean hasOverlap = DrawMapUtil.checkDraw(points, aMap); 618 | if (hasOverlap) { 619 | //说明重合了 620 | polygonOptions.strokeWidth(2) // 多边形的边框 621 | .strokeColor(getResources().getColor(R.color.white)) // 边框颜色 622 | .fillColor(getResources().getColor(R.color.half_red)); // 多边形的填充色 623 | } else { 624 | polygonOptions.strokeWidth(2) // 多边形的边框 625 | .strokeColor(getResources().getColor(R.color.white)) // 边框颜色 626 | .fillColor(getResources().getColor(R.color.black60)); // 多边形的填充色 627 | 628 | } 629 | 630 | polygon = aMap.addPolygon(polygonOptions.zIndex(100)); 631 | 632 | // if (!hasOverlap) { 633 | // upDateLandInfo(); 634 | // } 635 | 636 | } 637 | 638 | 639 | /**************************************************************处理滑动事件**************************************************************/ 640 | 641 | /** 642 | * 滑动事件 643 | * 644 | * @param ev 645 | */ 646 | private void handlePressEvent(MotionEvent ev) { 647 | if (movePosition == -1) { 648 | return; 649 | } 650 | if (hasDrawFinish) { 651 | handleFinishPress(ev); 652 | } else { 653 | handleCommonPress(ev); 654 | 655 | } 656 | 657 | } 658 | 659 | private void handleDownTouchEvent(MotionEvent ev) { 660 | distanceMap.clear(); 661 | for (int i = 0; i < points.size(); i++) { 662 | Point point = aMap.getProjection().toScreenLocation(points.get(i).getLatLng()); 663 | int distance = (int) Math.sqrt(Math.pow(ev.getX() - point.x, 2) 664 | + Math.pow(ev.getY() - point.y, 2)); 665 | distanceMap.put(i, distance); 666 | } 667 | 668 | int[] arr = CommonUtil.getKeyOfMinValue(distanceMap); 669 | if (arr != null && arr[1] < CIRCLE_DEFAULT) { 670 | isDrawPress = true; 671 | aMap.getUiSettings().setAllGesturesEnabled(false); 672 | //说明选中该点 673 | if (signMark != null) { 674 | signMark.remove(); 675 | } 676 | 677 | movePosition = arr[0]; 678 | pressCircle_isBig = points.get(movePosition).getBigCircle(); 679 | } 680 | 681 | } 682 | 683 | /** 684 | * 滑动结束 685 | */ 686 | private void handleMoveTouchEvent() { 687 | isDrawPress = false; 688 | pressCircle_isBig = false; 689 | movePosition = -1; 690 | moveSign_center = false; 691 | moveSign_right = false; 692 | isFirstPoint = false; 693 | isLastPoint = false; 694 | aMap.getUiSettings().setAllGesturesEnabled(true); 695 | aMap.getUiSettings().setRotateGesturesEnabled(false);//关闭旋转手势 696 | aMap.getUiSettings().setTiltGesturesEnabled(false);//关闭倾斜手势 697 | } 698 | 699 | /** 700 | * 没有闭合 701 | * 702 | * @param ev 703 | */ 704 | private void handleCommonPress(MotionEvent ev) { 705 | LatLng latLng = aMap.getProjection().fromScreenLocation(new Point((int) ev.getX(), (int) ev.getY())); 706 | 707 | if (pressCircle_isBig) { 708 | 709 | if (movePosition == 0) { 710 | 711 | /******大圆圈****************/ 712 | circleList.get(0).remove(); 713 | circleList.remove(0); 714 | points.remove(0); 715 | circleList.add(0, drawBigCircle(latLng, 0)); 716 | points.add(0, new DrawLatLng(latLng, true)); 717 | 718 | /*********画右边的小圆圈***********/ 719 | LatLng latLng_right = getCenterLatlng(points.get(2).getLatLng(), latLng); 720 | circleList.get(1).remove(); 721 | circleList.remove(1); 722 | points.remove(1); 723 | circleList.add(1, drawSmallCircle(latLng_right, 1)); 724 | 725 | points.add(1, new DrawLatLng(latLng_right, false)); 726 | 727 | /******选中标签****************/ 728 | signMarkPosition = movePosition; 729 | drawSignMark(latLng); 730 | drawLine(); 731 | return; 732 | } 733 | 734 | if (movePosition == points.size() - 1) { 735 | /*********画左边的小圆圈***********/ 736 | LatLng latLng_left = getCenterLatlng(points.get(movePosition - 2).getLatLng(), latLng); 737 | circleList.get(movePosition - 1).remove(); 738 | circleList.remove(movePosition - 1); 739 | points.remove(movePosition - 1); 740 | circleList.add(movePosition - 1, drawSmallCircle(latLng_left, movePosition - 1)); 741 | 742 | points.add(movePosition - 1, new DrawLatLng(latLng_left, false)); 743 | 744 | 745 | /******大圆圈****************/ 746 | circleList.get(movePosition).remove(); 747 | circleList.remove(movePosition); 748 | points.remove(movePosition); 749 | circleList.add(movePosition, drawBigCircle(latLng, movePosition)); 750 | points.add(movePosition, new DrawLatLng(latLng, true)); 751 | 752 | /******选中标签****************/ 753 | signMarkPosition = movePosition; 754 | drawSignMark(latLng); 755 | drawLine(); 756 | return; 757 | } 758 | 759 | //移动的是大圆圈 760 | //重新计算两边小圆圈的位置 761 | 762 | /*********画左边的小圆圈***********/ 763 | LatLng latLng_left = getCenterLatlng(points.get(movePosition - 2).getLatLng(), latLng); 764 | circleList.get(movePosition - 1).remove(); 765 | circleList.remove(movePosition - 1); 766 | points.remove(movePosition - 1); 767 | circleList.add(movePosition - 1, drawSmallCircle(latLng_left, movePosition - 1)); 768 | 769 | points.add(movePosition - 1, new DrawLatLng(latLng_left, false)); 770 | 771 | 772 | /******大圆圈****************/ 773 | circleList.get(movePosition).remove(); 774 | circleList.remove(movePosition); 775 | points.remove(movePosition); 776 | circleList.add(movePosition, drawBigCircle(latLng, movePosition)); 777 | points.add(movePosition, new DrawLatLng(latLng, true)); 778 | 779 | /*********画右边的小圆圈***********/ 780 | LatLng latLng_right = getCenterLatlng(points.get(movePosition + 2).getLatLng(), latLng); 781 | circleList.get(movePosition + 1).remove(); 782 | circleList.remove(movePosition + 1); 783 | points.remove(movePosition + 1); 784 | circleList.add(movePosition + 1, drawSmallCircle(latLng_right, movePosition + 1)); 785 | 786 | points.add(movePosition + 1, new DrawLatLng(latLng_right, false)); 787 | 788 | /******选中标签****************/ 789 | signMarkPosition = movePosition; 790 | drawSignMark(latLng); 791 | drawLine(); 792 | } else { 793 | if (movePosition == points.size() - 1 || isLastPoint) { 794 | handleSmallCircleIsLastPoint(ev, latLng); 795 | isLastPoint = true; 796 | return; 797 | } 798 | 799 | //判断是否是位置1 800 | if (movePosition == 1 || isFirstPoint) { 801 | handleSmallCircleIsFirstPoint(ev, latLng); 802 | isFirstPoint = true; 803 | return; 804 | } 805 | handleSmallCircleNotLastPoint(ev, latLng); 806 | } 807 | } 808 | 809 | /** 810 | * 已经完成了 811 | * 812 | * @param ev 813 | */ 814 | private void handleFinishPress(MotionEvent ev) { 815 | LatLng latLng = aMap.getProjection().fromScreenLocation(new Point((int) ev.getX(), (int) ev.getY())); 816 | if (pressCircle_isBig) { 817 | // 完成,需要判断是否是第一个点 818 | if (movePosition == 0 || isFirstPoint) { 819 | isFirstPoint = true; 820 | handleBigCircleIsFirtPoint(ev, latLng); 821 | return; 822 | } 823 | //判断是否是最后一个大圆圈 824 | if (movePosition == points.size() - 2 || isLastPoint) { 825 | isLastPoint = true; 826 | handleBigCircleIsLastPoint(ev, latLng); 827 | return; 828 | } 829 | 830 | handleBigCircleNotFirtPoint(ev, latLng); 831 | 832 | 833 | } else { 834 | //移动的是小圆圈,小圆圈需要判断是否是最后一个 835 | 836 | if (movePosition == points.size() - 1 || isLastPoint) { 837 | isLastPoint = true; 838 | handleSmallCircleIsLastPoint(ev, latLng); 839 | return; 840 | } 841 | 842 | //判断是否是位置1 843 | if (movePosition == 1 || isFirstPoint) { 844 | isFirstPoint = true; 845 | handleSmallCircleIsFirstPoint(ev, latLng); 846 | return; 847 | } 848 | 849 | handleSmallCircleNotLastPoint(ev, latLng); 850 | } 851 | 852 | } 853 | 854 | private void handleSmallCircleIsLastPoint(MotionEvent ev, LatLng latLng) { 855 | /*********画左边的小圆圈***********/ 856 | LatLng latLng_left = getCenterLatlng(points.get(movePosition - 1).getLatLng(), latLng); 857 | 858 | //两边是小圆圈,清除上次的 859 | circleList.get(movePosition).remove(); 860 | circleList.remove(movePosition); 861 | points.remove(movePosition); 862 | circleList.add(movePosition, drawSmallCircle(latLng_left, movePosition)); 863 | points.add(movePosition, new DrawLatLng(latLng_left, false)); 864 | 865 | 866 | /******大圆圈****************/ 867 | 868 | if (moveSign_center) { 869 | circleList.get(movePosition + 1).remove(); 870 | circleList.remove(movePosition + 1); 871 | points.remove(movePosition + 1); 872 | circleList.add(movePosition + 1, drawBigCircle(latLng, movePosition + 1)); 873 | points.add(movePosition + 1, new DrawLatLng(latLng, true)); 874 | } else { 875 | circleList.add(drawBigCircle(latLng, circleList.size())); 876 | points.add(new DrawLatLng(latLng, true)); 877 | moveSign_center = true; 878 | } 879 | 880 | /******选中标签****************/ 881 | signMarkPosition = movePosition; 882 | drawSignMark(latLng); 883 | 884 | /*********画右边的小圆圈***********/ 885 | LatLng latLng_right = getCenterLatlng(points.get(0).getLatLng(), latLng); 886 | 887 | if (moveSign_right) { 888 | circleList.get(movePosition + 2).remove(); 889 | circleList.remove(movePosition + 2); 890 | points.remove(movePosition + 2); 891 | circleList.add(movePosition + 2, drawSmallCircle(latLng_right, movePosition + 2)); 892 | points.add(movePosition + 2, new DrawLatLng(latLng_right, false)); 893 | } else { 894 | circleList.add(drawSmallCircle(latLng_right, circleList.size())); 895 | points.add(new DrawLatLng(latLng_right, false)); 896 | moveSign_right = true; 897 | } 898 | 899 | if (hasDrawFinish) { 900 | drawPolygon(); 901 | } else { 902 | drawLine(); 903 | } 904 | 905 | } 906 | 907 | private void handleBigCircleNotFirtPoint(MotionEvent ev, LatLng latLng) { 908 | //移动的是大圆圈 909 | //重新计算两边小圆圈的位置 910 | 911 | /*********画左边的小圆圈***********/ 912 | LatLng latLng_left = getCenterLatlng(points.get(movePosition - 2).getLatLng(), latLng); 913 | circleList.get(movePosition - 1).remove(); 914 | circleList.remove(movePosition - 1); 915 | points.remove(movePosition - 1); 916 | circleList.add(movePosition - 1, drawSmallCircle(latLng_left, movePosition - 1)); 917 | 918 | points.add(movePosition - 1, new DrawLatLng(latLng_left, false)); 919 | 920 | 921 | /******大圆圈****************/ 922 | 923 | circleList.get(movePosition).remove(); 924 | circleList.remove(movePosition); 925 | points.remove(movePosition); 926 | circleList.add(movePosition, drawBigCircle(latLng, movePosition)); 927 | points.add(movePosition, new DrawLatLng(latLng, true)); 928 | 929 | /******选中标签****************/ 930 | signMarkPosition = movePosition; 931 | drawSignMark(latLng); 932 | 933 | /*********画右边的小圆圈***********/ 934 | LatLng latLng_right = getCenterLatlng(points.get(movePosition + 2).getLatLng(), latLng); 935 | 936 | circleList.get(movePosition + 1).remove(); 937 | circleList.remove(movePosition + 1); 938 | points.remove(movePosition + 1); 939 | circleList.add(movePosition + 1, drawSmallCircle(latLng_right, movePosition + 1)); 940 | 941 | points.add(movePosition + 1, new DrawLatLng(latLng_right, false)); 942 | 943 | drawPolygon(); 944 | } 945 | 946 | private void handleBigCircleIsFirtPoint(MotionEvent ev, LatLng latLng) { 947 | 948 | /*********画左边的小圆圈***********/ 949 | LatLng latLng_left = getCenterLatlng(points.get(points.size() - 2).getLatLng(), latLng); 950 | 951 | circleList.get(circleList.size() - 1).remove(); 952 | circleList.remove(circleList.size() - 1); 953 | circleList.add(drawSmallCircle(latLng_left, circleList.size())); 954 | points.remove(points.size() - 1); 955 | points.add(new DrawLatLng(latLng_left, false)); 956 | 957 | 958 | /******大圆圈****************/ 959 | 960 | circleList.get(0).remove(); 961 | circleList.remove(0); 962 | points.remove(0); 963 | circleList.add(0, drawBigCircle(latLng, 0)); 964 | points.add(0, new DrawLatLng(latLng, true)); 965 | 966 | /******选中标签****************/ 967 | signMarkPosition = movePosition; 968 | drawSignMark(latLng); 969 | 970 | /*********画右边的小圆圈***********/ 971 | LatLng latLng_right = getCenterLatlng(points.get(2).getLatLng(), latLng); 972 | 973 | //清除上次的 974 | circleList.get(1).remove(); 975 | circleList.remove(1); 976 | points.remove(1); 977 | 978 | circleList.add(1, drawSmallCircle(latLng_right, 1)); 979 | points.add(1, new DrawLatLng(latLng_right, false)); 980 | drawPolygon(); 981 | } 982 | 983 | 984 | private void handleSmallCircleIsFirstPoint(MotionEvent ev, LatLng latLng) { 985 | /*********画左边的小圆圈***********/ 986 | 987 | Point point_left = aMap.getProjection().toScreenLocation(points.get(0).getLatLng()); 988 | Point centerPoint_left = new Point(CommonUtil.avg(point_left.x, (int) ev.getX()), 989 | CommonUtil.avg(point_left.y, (int) ev.getY())); 990 | 991 | LatLng latLng_left = aMap.getProjection().fromScreenLocation(centerPoint_left); 992 | 993 | //两边是小圆圈,清除上次的 994 | circleList.get(movePosition).remove(); 995 | circleList.remove(movePosition); 996 | points.remove(movePosition); 997 | 998 | circleList.add(movePosition, drawSmallCircle(latLng_left, movePosition)); 999 | points.add(movePosition, new DrawLatLng(latLng_left, false)); 1000 | 1001 | 1002 | /******大圆圈****************/ 1003 | 1004 | if (moveSign_center) { 1005 | circleList.get(movePosition + 1).remove(); 1006 | circleList.remove(movePosition + 1); 1007 | points.remove(movePosition + 1); 1008 | circleList.add(movePosition + 1, drawBigCircle(latLng, movePosition + 1)); 1009 | points.add(movePosition + 1, new DrawLatLng(latLng, true)); 1010 | } else { 1011 | circleList.add(movePosition + 1, drawBigCircle(latLng, movePosition + 1)); 1012 | points.add(movePosition + 1, new DrawLatLng(latLng, true)); 1013 | moveSign_center = true; 1014 | } 1015 | 1016 | 1017 | /******选中标签****************/ 1018 | signMarkPosition = movePosition; 1019 | drawSignMark(latLng); 1020 | 1021 | /*********画右边的小圆圈***********/ 1022 | 1023 | LatLng newLatLng; 1024 | if (moveSign_right) { 1025 | newLatLng = points.get(movePosition + 3).getLatLng(); 1026 | } else { 1027 | newLatLng = points.get(movePosition + 2).getLatLng(); 1028 | } 1029 | 1030 | Point point_right = aMap.getProjection().toScreenLocation(newLatLng); 1031 | Point centerPoint_right = new Point(CommonUtil.avg(point_right.x, (int) ev.getX()), 1032 | CommonUtil.avg(point_right.y, (int) ev.getY())); 1033 | 1034 | LatLng latLng_right = aMap.getProjection().fromScreenLocation(centerPoint_right); 1035 | 1036 | if (moveSign_right) { 1037 | //两边是小圆圈,清除上次的 1038 | circleList.get(movePosition + 2).remove(); 1039 | circleList.remove(movePosition + 2); 1040 | points.remove(movePosition + 2); 1041 | circleList.add(movePosition + 2, drawSmallCircle(latLng_right, movePosition + 2)); 1042 | points.add(movePosition + 2, new DrawLatLng(latLng_right, false)); 1043 | 1044 | } else { 1045 | circleList.add(movePosition + 2, drawSmallCircle(latLng_right, movePosition + 2)); 1046 | points.add(movePosition + 2, new DrawLatLng(latLng_right, false)); 1047 | moveSign_right = true; 1048 | } 1049 | if (hasDrawFinish) { 1050 | drawPolygon(); 1051 | } else { 1052 | drawLine(); 1053 | } 1054 | } 1055 | 1056 | private void handleSmallCircleNotLastPoint(MotionEvent ev, LatLng latLng) { 1057 | /*********画左边的小圆圈***********/ 1058 | 1059 | Point point_left = aMap.getProjection().toScreenLocation(points.get(movePosition - 1).getLatLng()); 1060 | Point centerPoint_left = new Point(CommonUtil.avg(point_left.x, (int) ev.getX()), 1061 | CommonUtil.avg(point_left.y, (int) ev.getY())); 1062 | 1063 | LatLng latLng_left = aMap.getProjection().fromScreenLocation(centerPoint_left); 1064 | 1065 | //两边是小圆圈,清除上次的 1066 | circleList.get(movePosition).remove(); 1067 | circleList.remove(movePosition); 1068 | points.remove(movePosition); 1069 | circleList.add(movePosition, drawSmallCircle(latLng_left, movePosition)); 1070 | points.add(movePosition, new DrawLatLng(latLng_left, false)); 1071 | 1072 | 1073 | /******大圆圈****************/ 1074 | 1075 | if (moveSign_center) { 1076 | circleList.get(movePosition + 1).remove(); 1077 | circleList.remove(movePosition + 1); 1078 | points.remove(movePosition + 1); 1079 | circleList.add(movePosition + 1, drawBigCircle(latLng, movePosition + 1)); 1080 | points.add(movePosition + 1, new DrawLatLng(latLng, true)); 1081 | 1082 | } else { 1083 | circleList.add(movePosition + 1, drawBigCircle(latLng, movePosition + 1)); 1084 | points.add(movePosition + 1, new DrawLatLng(latLng, true)); 1085 | moveSign_center = true; 1086 | } 1087 | 1088 | 1089 | /******选中标签****************/ 1090 | signMarkPosition = movePosition; 1091 | drawSignMark(latLng); 1092 | 1093 | /*********画右边的小圆圈***********/ 1094 | LatLng newLatlng; 1095 | if (moveSign_right) { 1096 | newLatlng = points.get(movePosition + 3).getLatLng(); 1097 | } else { 1098 | newLatlng = points.get(movePosition + 2).getLatLng(); 1099 | } 1100 | 1101 | Point point_right = aMap.getProjection().toScreenLocation(newLatlng); 1102 | Point centerPoint_right = new Point(CommonUtil.avg(point_right.x, (int) ev.getX()), 1103 | CommonUtil.avg(point_right.y, (int) ev.getY())); 1104 | 1105 | LatLng latLng_right = aMap.getProjection().fromScreenLocation(centerPoint_right); 1106 | 1107 | if (moveSign_right) { 1108 | //两边是小圆圈,清除上次的 1109 | circleList.get(movePosition + 2).remove(); 1110 | circleList.remove(movePosition + 2); 1111 | points.remove(movePosition + 2); 1112 | circleList.add(movePosition + 2, drawSmallCircle(latLng_right, movePosition + 2)); 1113 | points.add(movePosition + 2, new DrawLatLng(latLng_right, false)); 1114 | } else { 1115 | circleList.add(movePosition + 2, drawSmallCircle(latLng_right, movePosition + 2)); 1116 | points.add(movePosition + 2, new DrawLatLng(latLng_right, false)); 1117 | moveSign_right = true; 1118 | } 1119 | 1120 | if (hasDrawFinish) { 1121 | drawPolygon(); 1122 | } else { 1123 | drawLine(); 1124 | } 1125 | } 1126 | 1127 | private void handleBigCircleIsLastPoint(MotionEvent ev, LatLng latLng) { 1128 | //移动的是大圆圈 1129 | //重新计算两边小圆圈的位置 1130 | 1131 | /*********画左边的小圆圈***********/ 1132 | 1133 | Point point_left = aMap.getProjection().toScreenLocation(points.get(movePosition - 2).getLatLng()); 1134 | Point centerPoint_left = new Point(CommonUtil.avg(point_left.x, (int) ev.getX()), 1135 | CommonUtil.avg(point_left.y, (int) ev.getY())); 1136 | 1137 | LatLng latLng_left = aMap.getProjection().fromScreenLocation(centerPoint_left); 1138 | 1139 | circleList.get(movePosition - 1).remove(); 1140 | circleList.remove(movePosition - 1); 1141 | points.remove(movePosition - 1); 1142 | circleList.add(movePosition - 1, drawSmallCircle(latLng_left, movePosition - 1)); 1143 | 1144 | points.add(movePosition - 1, new DrawLatLng(latLng_left, false)); 1145 | 1146 | 1147 | /******大圆圈****************/ 1148 | 1149 | circleList.get(movePosition).remove(); 1150 | circleList.remove(movePosition); 1151 | points.remove(movePosition); 1152 | circleList.add(movePosition, drawBigCircle(latLng, movePosition)); 1153 | points.add(movePosition, new DrawLatLng(latLng, true)); 1154 | 1155 | /******选中标签****************/ 1156 | signMarkPosition = movePosition; 1157 | drawSignMark(latLng); 1158 | 1159 | /*********画右边的小圆圈***********/ 1160 | 1161 | Point point_right = aMap.getProjection().toScreenLocation(points.get(0).getLatLng()); 1162 | Point centerPoint_right = new Point(CommonUtil.avg(point_right.x, (int) ev.getX()), 1163 | CommonUtil.avg(point_right.y, (int) ev.getY())); 1164 | 1165 | LatLng latLng_right = aMap.getProjection().fromScreenLocation(centerPoint_right); 1166 | 1167 | circleList.get(movePosition + 1).remove(); 1168 | circleList.remove(movePosition + 1); 1169 | points.remove(movePosition + 1); 1170 | circleList.add(movePosition + 1, drawSmallCircle(latLng_right, movePosition + 1)); 1171 | 1172 | points.add(movePosition + 1, new DrawLatLng(latLng_right, false)); 1173 | 1174 | drawPolygon(); 1175 | } 1176 | 1177 | } 1178 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuezhy/drawmap/MyApplication.java: -------------------------------------------------------------------------------- 1 | package com.xuezhy.drawmap; 2 | 3 | import android.app.Application; 4 | import com.orhanobut.hawk.Hawk; 5 | 6 | public class MyApplication extends Application { 7 | private static MyApplication mApplication; 8 | 9 | public static MyApplication getInstance() { 10 | return mApplication; 11 | } 12 | 13 | 14 | @Override 15 | public void onCreate() { 16 | super.onCreate(); 17 | mApplication = this; 18 | Hawk.init(getApplicationContext()).build(); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuezhy/drawmap/bean/BaseEvent.java: -------------------------------------------------------------------------------- 1 | package com.xuezhy.drawmap.bean; 2 | 3 | /** 4 | * 类功能描述: 5 | * 作者: zhongyangxue 6 | * 创建时间: 2019-12-31 15:34 7 | * 邮箱 1366411749@qq.com 8 | * 版本: 1.0 9 | */ 10 | public class BaseEvent { 11 | private int code; 12 | private T data; 13 | 14 | public BaseEvent(int code) { 15 | this.code = code; 16 | } 17 | 18 | public BaseEvent(int code, T data) { 19 | this.code = code; 20 | this.data = data; 21 | } 22 | 23 | public int getCode() { 24 | return code; 25 | } 26 | 27 | public void setCode(int code) { 28 | this.code = code; 29 | } 30 | 31 | public T getData() { 32 | return data; 33 | } 34 | 35 | public void setData(T data) { 36 | this.data = data; 37 | } 38 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuezhy/drawmap/bean/DrawCircle.java: -------------------------------------------------------------------------------- 1 | package com.xuezhy.drawmap.bean; 2 | 3 | import com.amap.api.maps.model.Circle; 4 | 5 | /** 6 | * 类功能描述: 7 | * 作者: zhongyangxue 8 | * 创建时间: 2019/11/10 下午6:11 9 | * 邮箱 1366411749@qq.com 10 | * 版本: 1.0 11 | */ 12 | public class DrawCircle { 13 | private Circle circle; 14 | private Boolean isBigCircle; 15 | 16 | public DrawCircle(Circle circle, Boolean isBigCircle) { 17 | this.circle = circle; 18 | this.isBigCircle = isBigCircle; 19 | } 20 | 21 | public Circle getCircle() { 22 | return circle; 23 | } 24 | 25 | public void setCircle(Circle circle) { 26 | this.circle = circle; 27 | } 28 | 29 | public Boolean getBigCircle() { 30 | return isBigCircle; 31 | } 32 | 33 | public void setBigCircle(Boolean bigCircle) { 34 | isBigCircle = bigCircle; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuezhy/drawmap/bean/DrawLatLng.java: -------------------------------------------------------------------------------- 1 | package com.xuezhy.drawmap.bean; 2 | 3 | 4 | import com.amap.api.maps.model.LatLng; 5 | 6 | /** 7 | * 类功能描述: 8 | * 作者: zhongyangxue 9 | * 创建时间: 2019/10/5 下午1:33 10 | * 邮箱 1366411749@qq.com 11 | * 版本: 1.0 12 | */ 13 | public class DrawLatLng { 14 | private LatLng latLng; //经纬度 15 | private Boolean isBigCircle; //是否是原始采集点 16 | 17 | public DrawLatLng(LatLng latLng, Boolean isBigCircle) { 18 | this.latLng = latLng; 19 | this.isBigCircle = isBigCircle; 20 | } 21 | 22 | public LatLng getLatLng() { 23 | return latLng; 24 | } 25 | 26 | public void setLatLng(LatLng latLng) { 27 | this.latLng = latLng; 28 | } 29 | 30 | public Boolean getBigCircle() { 31 | return isBigCircle; 32 | } 33 | 34 | public void setBigCircle(Boolean bigCircle) { 35 | isBigCircle = bigCircle; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuezhy/drawmap/bean/LatlngBean.java: -------------------------------------------------------------------------------- 1 | package com.xuezhy.drawmap.bean; 2 | 3 | import java.io.Serializable; 4 | 5 | public class LatlngBean implements Serializable { 6 | private double latitude; 7 | private double longitude; 8 | 9 | public LatlngBean(double latitude, double longitude) { 10 | this.latitude = latitude; 11 | this.longitude = longitude; 12 | } 13 | 14 | public double getLatitude() { 15 | return latitude; 16 | } 17 | 18 | public void setLatitude(double latitude) { 19 | this.latitude = latitude; 20 | } 21 | 22 | public double getLongitude() { 23 | return longitude; 24 | } 25 | 26 | public void setLongitude(double longitude) { 27 | this.longitude = longitude; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuezhy/drawmap/bean/LocationEvent.java: -------------------------------------------------------------------------------- 1 | package com.xuezhy.drawmap.bean; 2 | 3 | public class LocationEvent extends BaseEvent{ 4 | 5 | public LocationEvent(int code) { 6 | super(code); 7 | } 8 | 9 | public LocationEvent(int code, Object data) { 10 | super(code, data); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuezhy/drawmap/utils/CommonUtil.java: -------------------------------------------------------------------------------- 1 | package com.xuezhy.drawmap.utils; 2 | 3 | import com.amap.api.maps.model.LatLng; 4 | import com.xuezhy.drawmap.bean.DrawLatLng; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Collections; 8 | import java.util.Comparator; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | public class CommonUtil { 13 | /** 14 | * 计算平均值 15 | * 16 | * @param a 17 | * @param b 18 | * @return 19 | */ 20 | public static int avg(int a, int b) { 21 | 22 | return ((a & b) + ((a ^ b) >> 1)); 23 | 24 | } 25 | 26 | /** 27 | * 获取不规则多边形重心点 28 | * 29 | * @param mPoints 30 | * @return 31 | */ 32 | public static LatLng getCenterOfDrawPoint(List mPoints) { 33 | double area = 0.0;//多边形面积 34 | double Gx = 0.0, Gy = 0.0;// 重心的x、y 35 | for (int i = 1; i <= mPoints.size(); i++) { 36 | double iLat = mPoints.get(i % mPoints.size()).getLatLng().latitude; 37 | double iLng = mPoints.get(i % mPoints.size()).getLatLng().longitude; 38 | double nextLat = mPoints.get(i - 1).getLatLng().latitude; 39 | double nextLng = mPoints.get(i - 1).getLatLng().longitude; 40 | double temp = (iLat * nextLng - iLng * nextLat) / 2.0; 41 | area += temp; 42 | Gx += temp * (iLat + nextLat) / 3.0; 43 | Gy += temp * (iLng + nextLng) / 3.0; 44 | } 45 | Gx = Gx / area; 46 | Gy = Gy / area; 47 | return new LatLng(Gx, Gy); 48 | } 49 | 50 | 51 | 52 | public static int[] getKeyOfMinValue(Map map) { 53 | int[] arr = new int[2];//设置一个 长度为2的数组 用作记录 规定第一个元素存储角标 第二个元素存储值 54 | 55 | 56 | List> list = new ArrayList>(map.entrySet()); 57 | Collections.sort(list, new Comparator>() { 58 | public int compare(Map.Entry o1, Map.Entry o2) { 59 | //升序排列 60 | return (o1.getValue() - o2.getValue()); 61 | 62 | //降序排列 63 | 64 | //return (o1.getValue() - o2.getValue()); 65 | 66 | } 67 | }); 68 | 69 | arr[0] = list.get(0).getKey(); 70 | arr[1] = list.get(0).getValue(); 71 | return arr; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuezhy/drawmap/utils/DensityUtil.java: -------------------------------------------------------------------------------- 1 | package com.xuezhy.drawmap.utils; 2 | 3 | import android.content.Context; 4 | 5 | public class DensityUtil { 6 | /** 7 | * 根据手机的分辨率从 dp 的单位 转成为 px(像素) 8 | */ 9 | public static int dip2px(Context context, float dpValue) { 10 | final float scale = context.getResources().getDisplayMetrics().density; 11 | return (int) (dpValue * scale + 0.5f); 12 | } 13 | 14 | /** 15 | * 根据手机的分辨率从 px(像素) 的单位 转成为 dp 16 | */ 17 | public static int px2dip(Context context, float pxValue) { 18 | final float scale = context.getResources().getDisplayMetrics().density; 19 | return (int) (pxValue / scale + 0.5f); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuezhy/drawmap/utils/DrawMapUtil.java: -------------------------------------------------------------------------------- 1 | package com.xuezhy.drawmap.utils; 2 | 3 | import android.graphics.Color; 4 | import android.graphics.Point; 5 | 6 | import com.amap.api.maps.AMap; 7 | import com.amap.api.maps.model.Circle; 8 | import com.amap.api.maps.model.CircleOptions; 9 | import com.amap.api.maps.model.LatLng; 10 | import com.amap.api.maps.model.Polyline; 11 | import com.amap.api.maps.model.PolylineOptions; 12 | import com.xuezhy.drawmap.bean.DrawCircle; 13 | import com.xuezhy.drawmap.bean.DrawLatLng; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | /** 19 | * 类功能描述: 20 | * 作者: zhongyangxue 21 | * 创建时间: 2019/11/10 下午2:42 22 | * 邮箱 1366411749@qq.com 23 | * 版本: 1.0 24 | */ 25 | public class DrawMapUtil { 26 | 27 | public static float getScreenDistance(AMap aMap, LatLng latLng1, LatLng latLng2) { 28 | Point point1 = aMap.getProjection().toScreenLocation(latLng1); 29 | Point point2 = aMap.getProjection().toScreenLocation(latLng2); 30 | float fLen = (float) Math.sqrt(Math.pow(point1.x - point2.x, 2) 31 | + Math.pow(point1.y - point2.y, 2)); 32 | return fLen; 33 | } 34 | 35 | public static void drawBigCircle(AMap aMap, DrawLatLng latLng) { 36 | Circle circle = aMap.addCircle(new CircleOptions() 37 | .center(latLng.getLatLng()) 38 | .radius(5) 39 | .fillColor(Color.argb(255, 255, 255, 255)) 40 | .strokeColor(Color.argb(255, 255, 255, 255)) 41 | .strokeWidth(0).zIndex(999)); 42 | } 43 | 44 | public static void drawSmallCircle(AMap aMap, LatLng latLng1, LatLng latLng2) { 45 | Point point1 = aMap.getProjection().toScreenLocation(latLng1); 46 | Point point2 = aMap.getProjection().toScreenLocation(latLng2); 47 | Point centerPoint = new Point(avg(point1.x, point2.x), 48 | avg(point1.y, point2.y)); 49 | 50 | LatLng centerLatLng = aMap.getProjection().fromScreenLocation(centerPoint); 51 | Circle circle = aMap.addCircle(new CircleOptions() 52 | .center(centerLatLng) 53 | .radius(3) 54 | .fillColor(Color.argb(255, 255, 255, 255)) 55 | .strokeColor(Color.argb(255, 255, 255, 255)) 56 | .strokeWidth(0).zIndex(999)); 57 | } 58 | 59 | public static void drawBigCircle2(AMap aMap, ArrayList circleList, DrawLatLng latLng, int position) { 60 | Circle circle = aMap.addCircle(new CircleOptions() 61 | .center(latLng.getLatLng()) 62 | .radius(5) 63 | .fillColor(Color.argb(255, 255, 255, 255)) 64 | .strokeColor(Color.argb(255, 255, 255, 255)) 65 | .strokeWidth(0).zIndex(999)); 66 | circleList.add(position, new DrawCircle(circle, true)); 67 | } 68 | 69 | 70 | public static void drawSmallCircle2(AMap aMap, ArrayList circleList, DrawLatLng drawLatLng, ArrayList points, int position) { 71 | Circle circle = aMap.addCircle(new CircleOptions() 72 | .center(drawLatLng.getLatLng()) 73 | .radius(3) 74 | .fillColor(Color.argb(255, 255, 255, 255)) 75 | .strokeColor(Color.argb(255, 255, 255, 255)) 76 | .strokeWidth(0).zIndex(999)); 77 | circleList.add(position, new DrawCircle(circle, false)); 78 | points.add(position, new DrawLatLng(drawLatLng.getLatLng(), false)); 79 | } 80 | 81 | public static void drawLine(AMap aMap, LatLng latLng1, LatLng latLng2, List polylineList) { 82 | Polyline polyline = aMap.addPolyline(new PolylineOptions(). 83 | add(latLng1, latLng2).width(5).color(Color.argb(255, 255, 255, 255)).zIndex(999)); 84 | polylineList.add(polyline); 85 | } 86 | 87 | public static ArrayList drawLatlngToLatlng(List drawLatLngs) { 88 | ArrayList latLngs = new ArrayList<>(); 89 | for (int i = 0; i < drawLatLngs.size(); i++) { 90 | latLngs.add(drawLatLngs.get(i).getLatLng()); 91 | } 92 | return latLngs; 93 | } 94 | 95 | 96 | 97 | public static Boolean checkDraw(List latLngs, AMap aMap) { 98 | Boolean flag = false; 99 | try { 100 | 101 | for (int i = 0; i < latLngs.size() - 2; i++) { 102 | Point point1, point2, point3, point4; 103 | 104 | point1 = aMap.getProjection().toScreenLocation(latLngs.get(i).getLatLng()); 105 | point2 = aMap.getProjection().toScreenLocation(latLngs.get(i + 1).getLatLng()); 106 | 107 | for (int j = i + 2; j < latLngs.size(); j++) { 108 | 109 | if (i == 0 && j == latLngs.size() - 1) { 110 | break; 111 | 112 | } else if (j == latLngs.size() - 1) { 113 | point3 = aMap.getProjection().toScreenLocation(latLngs.get(j).getLatLng()); 114 | point4 = aMap.getProjection().toScreenLocation(latLngs.get(0).getLatLng()); 115 | flag = intersection(point1, point2, point3, point4); 116 | 117 | } else { 118 | point3 = aMap.getProjection().toScreenLocation(latLngs.get(j).getLatLng()); 119 | point4 = aMap.getProjection().toScreenLocation(latLngs.get(j + 1).getLatLng()); 120 | flag = intersection(point1, point2, point3, point4); 121 | } 122 | 123 | if (flag) { 124 | return flag; 125 | } 126 | } 127 | } 128 | 129 | } catch (Exception e) { 130 | } 131 | 132 | 133 | return flag; 134 | } 135 | 136 | 137 | public static boolean intersection(Point point1, Point point2, Point point3, Point point4) { 138 | double l1x1 = point1.x; 139 | double l1y1 = point1.y; 140 | double l1x2 = point2.x; 141 | double l1y2 = point2.y; 142 | double l2x1 = point3.x; 143 | double l2y1 = point3.y; 144 | double l2x2 = point4.x; 145 | double l2y2 = point4.y; 146 | 147 | 148 | // 快速排斥实验 首先判断两条线段在 x 以及 y 坐标的投影是否有重合。 有一个为真,则代表两线段必不可交。 149 | if (Math.max(l1x1, l1x2) < Math.min(l2x1, l2x2) 150 | || Math.max(l1y1, l1y2) < Math.min(l2y1, l2y2) 151 | || Math.max(l2x1, l2x2) < Math.min(l1x1, l1x2) 152 | || Math.max(l2y1, l2y2) < Math.min(l1y1, l1y2)) { 153 | return false; 154 | } 155 | // 跨立实验 如果相交则矢量叉积异号或为零,大于零则不相交 156 | if ((((l1x1 - l2x1) * (l2y2 - l2y1) - (l1y1 - l2y1) * (l2x2 - l2x1)) 157 | * ((l1x2 - l2x1) * (l2y2 - l2y1) - (l1y2 - l2y1) * (l2x2 - l2x1))) > 0 158 | || (((l2x1 - l1x1) * (l1y2 - l1y1) - (l2y1 - l1y1) * (l1x2 - l1x1)) 159 | * ((l2x2 - l1x1) * (l1y2 - l1y1) - (l2y2 - l1y1) * (l1x2 - l1x1))) > 0) { 160 | return false; 161 | } 162 | return true; 163 | } 164 | 165 | /** 166 | * 计算平均值 167 | * 168 | * @param a 169 | * @param b 170 | * @return 171 | */ 172 | public static int avg(int a, int b) { 173 | 174 | return ((a & b) + ((a ^ b) >> 1)); 175 | 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuezhy/drawmap/utils/GoogleMapUtil.java: -------------------------------------------------------------------------------- 1 | package com.xuezhy.drawmap.utils; 2 | 3 | import com.amap.api.maps.model.TileOverlayOptions; 4 | import com.amap.api.maps.model.TileProvider; 5 | import com.amap.api.maps.model.UrlTileProvider; 6 | 7 | import java.net.MalformedURLException; 8 | import java.net.URL; 9 | 10 | /** 11 | * 类功能描述: 高德地图切换到有的地方没有卫星图片,此处使用谷歌地图的卫星切片替换 12 | * 作者: zhongyangxue 13 | * 创建时间: 2019/10/16 上午12:40 14 | * 邮箱 1366411749@qq.com 15 | * 版本: 1.0 16 | */ 17 | public class GoogleMapUtil { 18 | // final static String url = "http://mt2.google.cn/vt/lyrs=y@167000000&hl=zh-CN&gl=cn&x=%d&y=%d&z=%d&s=Galil"; 19 | // final static String url = "http://mt0.google.cn/vt/lyrs=y@198&hl=zh-CN&gl=cn&src=app&x=%d&y=%d&z=%d&s="; 20 | final static String url = "http://mt3.google.cn/maps/vt?lyrs=y@194&hl=zh-CN&gl=cn&x=%d&y=%d&z=%d"; 21 | 22 | 23 | public static TileOverlayOptions getGooleMapTileOverlayOptions() { 24 | 25 | TileProvider tileProvider = new UrlTileProvider(256, 256) { 26 | public URL getTileUrl(int x, int y, int zoom) { 27 | try { 28 | return new URL(String.format(url, x, y, zoom)); 29 | } catch (MalformedURLException e) { 30 | e.printStackTrace(); 31 | } 32 | return null; 33 | } 34 | }; 35 | 36 | return new TileOverlayOptions() 37 | .tileProvider(tileProvider) 38 | .diskCacheEnabled(true) 39 | .diskCacheSize(50000) 40 | .diskCacheDir("/storage/emulated/0/amap/OMCcache") 41 | .memoryCacheEnabled(false) 42 | .memCacheSize(10000) 43 | .zIndex(-9999); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuezhy/drawmap/utils/GpsManager.java: -------------------------------------------------------------------------------- 1 | package com.xuezhy.drawmap.utils; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.location.LocationManager; 6 | import android.provider.Settings; 7 | import com.amap.api.location.AMapLocation; 8 | import com.amap.api.location.AMapLocationClient; 9 | import com.amap.api.location.AMapLocationClientOption; 10 | import com.amap.api.location.AMapLocationListener; 11 | import com.xuezhy.drawmap.bean.LocationEvent; 12 | import com.xuezhy.drawmap.EventCode; 13 | import com.xuezhy.drawmap.bean.LatlngBean; 14 | 15 | import org.greenrobot.eventbus.EventBus; 16 | 17 | import static android.content.Context.LOCATION_SERVICE; 18 | 19 | /** 20 | * 类功能描述: 21 | * 作者: zhongyangxue 22 | * 创建时间: 2020-03-30 14:18 23 | * 邮箱 1366411749@qq.com 24 | * 版本: 1.0 25 | */ 26 | public class GpsManager { 27 | private AMapLocationClient locationClient = null; 28 | private LocationManager mLocationManager; 29 | private static final GpsManager checkGpsManager = new GpsManager(); 30 | 31 | private GpsManager() { 32 | } 33 | 34 | 35 | public static GpsManager getInstance() { 36 | return checkGpsManager; 37 | } 38 | 39 | public void init(Activity context) throws Exception { 40 | if (mLocationManager == null) { 41 | mLocationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE); 42 | } 43 | if (locationClient == null) { 44 | //初始化client 45 | locationClient = new AMapLocationClient(context); 46 | //设置定位参数 47 | locationClient.setLocationOption(getDefaultOption()); 48 | // 设置定位监听 49 | locationClient.setLocationListener(locationListener); 50 | // 启动定位 51 | // locationClient.startLocation(); 52 | } 53 | } 54 | 55 | public void startLocation() { 56 | if (locationClient != null) { 57 | //先暂停 58 | locationClient.stopLocation(); 59 | // 启动定位 60 | locationClient.startLocation(); 61 | } 62 | } 63 | 64 | /** 65 | * 默认的定位参数 66 | * 67 | * @author hongming.wang 68 | * @since 2.8.0 69 | */ 70 | private AMapLocationClientOption getDefaultOption() { 71 | AMapLocationClientOption mOption = new AMapLocationClientOption(); 72 | mOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);//可选,设置定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式 73 | mOption.setGpsFirst(true);//可选,设置是否gps优先,只在高精度模式下有效。默认关闭 74 | mOption.setHttpTimeOut(30 * 000);//可选,设置网络请求超时时间。默认为30秒。在仅设备模式下无效 75 | mOption.setInterval(50 * 1000);//可选,设置定位间隔。 76 | mOption.setNeedAddress(true);//可选,设置是否返回逆地理地址信息。默认是true 77 | mOption.setOnceLocation(false);//可选,设置是否单次定位。默认是false 78 | mOption.setWifiScan(true); //可选,设置是否开启wifi扫描。默认为true,如果设置为false会同时停止主动刷新,停止以后完全依赖于系统刷新,定位位置可能存在误差 79 | mOption.setLocationCacheEnable(true); //可选,设置是否使用缓存定位,默认为true 80 | mOption.setMockEnable(false); ////设置是否允许模拟位置,默认为false,不允许模拟位置 81 | return mOption; 82 | } 83 | 84 | /** 85 | * 判断是否打开定位 86 | * 87 | * @return 88 | */ 89 | public Boolean checkGps() { 90 | //判断gps是否打开 91 | return mLocationManager 92 | .isProviderEnabled(LocationManager.GPS_PROVIDER); 93 | } 94 | 95 | /** 96 | * 跳转到设置页面 97 | * 98 | * @param context 99 | * @param GPS_REQUEST_CODE 100 | */ 101 | public void goToSetting(Activity context, int GPS_REQUEST_CODE) { 102 | PopWindowUtil.buildNoTitleEnsureDialog(context, "请在设置中打开定位", "取消", "去设置", new PopWindowUtil.EnsureListener() { 103 | @Override 104 | public void sure(Object obj) { 105 | Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); 106 | context.startActivityForResult(intent, GPS_REQUEST_CODE); 107 | } 108 | 109 | @Override 110 | public void cancel() { 111 | 112 | } 113 | }); 114 | 115 | } 116 | 117 | 118 | /** 119 | * 定位监听 120 | */ 121 | AMapLocationListener locationListener = new AMapLocationListener() { 122 | @Override 123 | public void onLocationChanged(AMapLocation loc) { 124 | if (null == loc) { 125 | return; 126 | } 127 | try { 128 | if (loc.getLatitude() != 0 &&loc.getLongitude() != 0) { 129 | EventBus.getDefault().post(new LocationEvent(EventCode.LOCATION_CODE,new LatlngBean(loc.getLatitude(),loc.getLongitude()))); 130 | } 131 | 132 | } catch (Exception e) { 133 | 134 | } 135 | 136 | } 137 | }; 138 | 139 | 140 | } 141 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuezhy/drawmap/utils/PopWindowUtil.java: -------------------------------------------------------------------------------- 1 | package com.xuezhy.drawmap.utils; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.content.Context; 6 | import android.os.Build; 7 | import android.text.TextUtils; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.WindowManager; 11 | import android.widget.TextView; 12 | 13 | import com.xuezhy.drawmap.R; 14 | 15 | 16 | /** 17 | * 类功能描述: 18 | * 作者: zhongyangxue 19 | * 创建时间: 2020-01-12 17:05 20 | * 邮箱 1366411749@qq.com 21 | * 版本: 1.0 22 | */ 23 | public class PopWindowUtil { 24 | 25 | public static final AlertDialog buildNoTitleEnsureDialog(Context context, String content, String cancel, String sure, final EnsureListener listener) { 26 | if (context instanceof Activity) { 27 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 28 | if (((Activity) context).isDestroyed()) 29 | return null; 30 | } 31 | } 32 | 33 | final AlertDialog dialog; 34 | AlertDialog.Builder builder = new AlertDialog.Builder(context); 35 | builder.setCancelable(false); 36 | dialog = builder.create(); 37 | 38 | dialog.show(); 39 | View baseView = LayoutInflater.from(context).inflate(R.layout.layout_ensure_notitle_dialog, null); 40 | ((TextView) baseView.findViewById(R.id.dialog_cancel_btn)).setText(cancel); 41 | ((TextView) baseView.findViewById(R.id.dialog_sure_btn)).setText(sure); 42 | if (!TextUtils.isEmpty(content)) { 43 | ((TextView) baseView.findViewById(R.id.dialog_content)).setText(content); 44 | } else { 45 | baseView.findViewById(R.id.dialog_content).setVisibility(View.GONE); 46 | } 47 | baseView.findViewById(R.id.dialog_sure_btn).setOnClickListener(new View.OnClickListener() { 48 | 49 | @Override 50 | public void onClick(View v) { 51 | if (listener != null) 52 | listener.sure(null); 53 | dialog.dismiss(); 54 | } 55 | }); 56 | 57 | baseView.findViewById(R.id.dialog_cancel_btn).setOnClickListener(new View.OnClickListener() { 58 | 59 | @Override 60 | public void onClick(View v) { 61 | if (listener != null) 62 | listener.cancel(); 63 | dialog.dismiss(); 64 | } 65 | }); 66 | WindowManager.LayoutParams lp = dialog.getWindow().getAttributes(); 67 | lp.width = ScreenUtil.getPxByDp(context,320);//定义宽度 68 | lp.height = WindowManager.LayoutParams.WRAP_CONTENT;//定义高度 69 | dialog.getWindow().setAttributes(lp); 70 | dialog.setContentView(baseView); 71 | dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 72 | return dialog; 73 | } 74 | 75 | public interface EnsureListener { 76 | void sure(Object obj); 77 | 78 | void cancel(); 79 | } 80 | 81 | 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuezhy/drawmap/utils/ScreenUtil.java: -------------------------------------------------------------------------------- 1 | package com.xuezhy.drawmap.utils; 2 | 3 | import android.content.Context; 4 | import android.content.res.Configuration; 5 | import android.content.res.Resources; 6 | import android.graphics.Point; 7 | import android.graphics.Rect; 8 | import android.support.annotation.NonNull; 9 | import android.util.DisplayMetrics; 10 | import android.view.Display; 11 | import android.view.View; 12 | import android.view.Window; 13 | import android.view.WindowManager; 14 | import java.lang.reflect.Method; 15 | 16 | 17 | public class ScreenUtil { 18 | 19 | private static final String TAG = ScreenUtil.class.getSimpleName(); 20 | 21 | private static int navigationBarHeight = 0; 22 | private static int SOFT_INPUT_HEIGHT = 0; 23 | 24 | public static boolean checkNavigationBarShow(@NonNull Context context, @NonNull Window window) { 25 | boolean show; 26 | Display display = window.getWindowManager().getDefaultDisplay(); 27 | Point point = new Point(); 28 | display.getRealSize(point); 29 | 30 | View decorView = window.getDecorView(); 31 | Configuration conf = context.getResources().getConfiguration(); 32 | if (Configuration.ORIENTATION_LANDSCAPE == conf.orientation) { 33 | View contentView = decorView.findViewById(android.R.id.content); 34 | show = (point.x != contentView.getWidth()); 35 | } else { 36 | Rect rect = new Rect(); 37 | decorView.getWindowVisibleDisplayFrame(rect); 38 | show = (rect.bottom != point.y); 39 | } 40 | return show; 41 | } 42 | 43 | public static int getNavigationBarHeight(Context context) { 44 | if (navigationBarHeight != 0) 45 | return navigationBarHeight; 46 | Resources resources =context.getResources(); 47 | int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); 48 | int height = resources.getDimensionPixelSize(resourceId); 49 | navigationBarHeight = height; 50 | return height; 51 | } 52 | 53 | public static int[] getScreenSize(Context context) { 54 | int size[] = new int[2]; 55 | DisplayMetrics dm = context.getResources().getDisplayMetrics(); 56 | size[0] = dm.widthPixels; 57 | size[1] = dm.heightPixels; 58 | return size; 59 | } 60 | 61 | public static int getStatusBarHeight(Context context) { 62 | int result = 0; 63 | int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); 64 | if (resourceId > 0) { 65 | result = context.getResources().getDimensionPixelSize(resourceId); 66 | } 67 | return result; 68 | } 69 | 70 | public static int getScreenHeight(Context context) { 71 | DisplayMetrics metric = new DisplayMetrics(); 72 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 73 | wm.getDefaultDisplay().getMetrics(metric); 74 | return metric.heightPixels; 75 | } 76 | 77 | public static int getScreenWidth(Context context) { 78 | DisplayMetrics metric = new DisplayMetrics(); 79 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 80 | wm.getDefaultDisplay().getMetrics(metric); 81 | return metric.widthPixels; 82 | } 83 | 84 | public static int getPxByDp(Context context,float dp) { 85 | float scale = context.getResources().getDisplayMetrics().density; 86 | return (int) (dp * scale + 0.5f); 87 | } 88 | 89 | public static int getDpi(Context context) { 90 | int dpi = 0; 91 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 92 | Display display = windowManager.getDefaultDisplay(); 93 | DisplayMetrics displayMetrics = new DisplayMetrics(); 94 | @SuppressWarnings("rawtypes") 95 | Class c; 96 | try { 97 | c = Class.forName("android.view.Display"); 98 | @SuppressWarnings("unchecked") 99 | Method method = c.getMethod("getRealMetrics", DisplayMetrics.class); 100 | method.invoke(display, displayMetrics); 101 | dpi = displayMetrics.heightPixels; 102 | } catch (Exception e) { 103 | e.printStackTrace(); 104 | } 105 | return dpi; 106 | } 107 | 108 | /** 109 | * 获取 虚拟按键的高度 110 | * 111 | * @param context 112 | * @return 113 | */ 114 | public static int getBottomStatusHeight(Context context) { 115 | if (SOFT_INPUT_HEIGHT > 0) 116 | return SOFT_INPUT_HEIGHT; 117 | int totalHeight = getDpi(context); 118 | int contentHeight = getScreenHeight(context); 119 | SOFT_INPUT_HEIGHT = totalHeight - contentHeight; 120 | return SOFT_INPUT_HEIGHT; 121 | } 122 | 123 | public static int[] scaledSize(int containerWidth, int containerHeight, int realWidth, int realHeight) { 124 | 125 | float deviceRate = (float) containerWidth / (float) containerHeight; 126 | float rate = (float) realWidth / (float) realHeight; 127 | int width = 0; 128 | int height = 0; 129 | if (rate < deviceRate) { 130 | height = containerHeight; 131 | width = (int) (containerHeight * rate); 132 | } else { 133 | width = containerWidth; 134 | height = (int) (containerWidth / rate); 135 | } 136 | return new int[]{width, height}; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuezhy/drawmap/utils/StatusBarUtil.java: -------------------------------------------------------------------------------- 1 | package com.xuezhy.drawmap.utils; 2 | 3 | import android.annotation.TargetApi; 4 | import android.app.Activity; 5 | import android.content.Context; 6 | import android.graphics.Color; 7 | import android.os.Build; 8 | import android.support.annotation.ColorInt; 9 | import android.support.annotation.IntDef; 10 | import android.support.annotation.IntRange; 11 | import android.support.annotation.NonNull; 12 | import android.support.design.widget.CoordinatorLayout; 13 | import android.support.v4.widget.DrawerLayout; 14 | import android.view.View; 15 | import android.view.ViewGroup; 16 | import android.view.Window; 17 | import android.view.WindowManager; 18 | import android.widget.LinearLayout; 19 | 20 | import com.xuezhy.drawmap.R; 21 | 22 | import java.lang.annotation.Retention; 23 | import java.lang.annotation.RetentionPolicy; 24 | import java.lang.reflect.Field; 25 | import java.lang.reflect.Method; 26 | 27 | 28 | public class StatusBarUtil { 29 | 30 | public static final int DEFAULT_STATUS_BAR_ALPHA = 112; 31 | private static final int FAKE_STATUS_BAR_VIEW_ID = R.id.statusbarutil_fake_status_bar_view; 32 | private static final int FAKE_TRANSLUCENT_VIEW_ID = R.id.statusbarutil_translucent_view; 33 | private static final int TAG_KEY_HAVE_SET_OFFSET = -123; 34 | 35 | public final static int TYPE_MIUI = 0; 36 | public final static int TYPE_FLYME = 1; 37 | public final static int TYPE_M = 3;//6.0 38 | 39 | @IntDef({TYPE_MIUI, 40 | TYPE_FLYME, 41 | TYPE_M}) 42 | @Retention(RetentionPolicy.SOURCE) 43 | @interface ViewType { 44 | } 45 | 46 | /** 47 | * 设置状态栏颜色 48 | * 49 | * @param activity 需要设置的 activity 50 | * @param color 状态栏颜色值 51 | */ 52 | public static void setColor(Activity activity, @ColorInt int color) { 53 | setColor(activity, color, DEFAULT_STATUS_BAR_ALPHA); 54 | } 55 | 56 | /** 57 | * 设置状态栏颜色 58 | * 59 | * @param activity 需要设置的activity 60 | * @param color 状态栏颜色值 61 | * @param statusBarAlpha 状态栏透明度 62 | */ 63 | 64 | public static void setColor(Activity activity, @ColorInt int color, @IntRange(from = 0, to = 255) int statusBarAlpha) { 65 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 66 | activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 67 | activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 68 | activity.getWindow().setStatusBarColor(calculateStatusColor(color, statusBarAlpha)); 69 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 70 | activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 71 | ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView(); 72 | View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID); 73 | if (fakeStatusBarView != null) { 74 | if (fakeStatusBarView.getVisibility() == View.GONE) { 75 | fakeStatusBarView.setVisibility(View.VISIBLE); 76 | } 77 | fakeStatusBarView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha)); 78 | } else { 79 | decorView.addView(createStatusBarView(activity, color, statusBarAlpha)); 80 | } 81 | setRootView(activity); 82 | } 83 | } 84 | 85 | /** 86 | * 为滑动返回界面设置状态栏颜色 87 | * 88 | * @param activity 需要设置的activity 89 | * @param color 状态栏颜色值 90 | */ 91 | public static void setColorForSwipeBack(Activity activity, int color) { 92 | setColorForSwipeBack(activity, color, DEFAULT_STATUS_BAR_ALPHA); 93 | } 94 | 95 | /** 96 | * 为滑动返回界面设置状态栏颜色 97 | * 98 | * @param activity 需要设置的activity 99 | * @param color 状态栏颜色值 100 | * @param statusBarAlpha 状态栏透明度 101 | */ 102 | public static void setColorForSwipeBack(Activity activity, @ColorInt int color, 103 | @IntRange(from = 0, to = 255) int statusBarAlpha) { 104 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 105 | 106 | ViewGroup contentView = ((ViewGroup) activity.findViewById(android.R.id.content)); 107 | View rootView = contentView.getChildAt(0); 108 | int statusBarHeight = getStatusBarHeight(activity); 109 | if (rootView != null && rootView instanceof CoordinatorLayout) { 110 | final CoordinatorLayout coordinatorLayout = (CoordinatorLayout) rootView; 111 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { 112 | coordinatorLayout.setFitsSystemWindows(false); 113 | contentView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha)); 114 | boolean isNeedRequestLayout = contentView.getPaddingTop() < statusBarHeight; 115 | if (isNeedRequestLayout) { 116 | contentView.setPadding(0, statusBarHeight, 0, 0); 117 | coordinatorLayout.post(new Runnable() { 118 | @Override 119 | public void run() { 120 | coordinatorLayout.requestLayout(); 121 | } 122 | }); 123 | } 124 | } else { 125 | coordinatorLayout.setStatusBarBackgroundColor(calculateStatusColor(color, statusBarAlpha)); 126 | } 127 | } else { 128 | contentView.setPadding(0, statusBarHeight, 0, 0); 129 | contentView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha)); 130 | } 131 | setTransparentForWindow(activity); 132 | } 133 | } 134 | 135 | /** 136 | * 设置状态栏纯色 不加半透明效果 137 | * 138 | * @param activity 需要设置的 activity 139 | * @param color 状态栏颜色值 140 | */ 141 | public static void setColorNoTranslucent(Activity activity, @ColorInt int color) { 142 | setColor(activity, color, 0); 143 | } 144 | 145 | /** 146 | * 设置状态栏颜色(5.0以下无半透明效果,不建议使用) 147 | * 148 | * @param activity 需要设置的 activity 149 | * @param color 状态栏颜色值 150 | */ 151 | @Deprecated 152 | public static void setColorDiff(Activity activity, @ColorInt int color) { 153 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { 154 | return; 155 | } 156 | transparentStatusBar(activity); 157 | ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content); 158 | // 移除半透明矩形,以免叠加 159 | View fakeStatusBarView = contentView.findViewById(FAKE_STATUS_BAR_VIEW_ID); 160 | if (fakeStatusBarView != null) { 161 | if (fakeStatusBarView.getVisibility() == View.GONE) { 162 | fakeStatusBarView.setVisibility(View.VISIBLE); 163 | } 164 | fakeStatusBarView.setBackgroundColor(color); 165 | } else { 166 | contentView.addView(createStatusBarView(activity, color)); 167 | } 168 | setRootView(activity); 169 | } 170 | 171 | /** 172 | * 使状态栏半透明 173 | *

174 | * 适用于图片作为背景的界面,此时需要图片填充到状态栏 175 | * 176 | * @param activity 需要设置的activity 177 | */ 178 | public static void setTranslucent(Activity activity) { 179 | setTranslucent(activity, DEFAULT_STATUS_BAR_ALPHA); 180 | } 181 | 182 | /** 183 | * 使状态栏半透明 184 | *

185 | * 适用于图片作为背景的界面,此时需要图片填充到状态栏 186 | * 187 | * @param activity 需要设置的activity 188 | * @param statusBarAlpha 状态栏透明度 189 | */ 190 | public static void setTranslucent(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) { 191 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { 192 | return; 193 | } 194 | setTransparent(activity); 195 | addTranslucentView(activity, statusBarAlpha); 196 | } 197 | 198 | /** 199 | * 针对根布局是 CoordinatorLayout, 使状态栏半透明 200 | *

201 | * 适用于图片作为背景的界面,此时需要图片填充到状态栏 202 | * 203 | * @param activity 需要设置的activity 204 | * @param statusBarAlpha 状态栏透明度 205 | */ 206 | public static void setTranslucentForCoordinatorLayout(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) { 207 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { 208 | return; 209 | } 210 | transparentStatusBar(activity); 211 | addTranslucentView(activity, statusBarAlpha); 212 | } 213 | 214 | /** 215 | * 设置状态栏全透明 216 | * 217 | * @param activity 需要设置的activity 218 | */ 219 | public static void setTransparent(Activity activity) { 220 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { 221 | return; 222 | } 223 | transparentStatusBar(activity); 224 | setRootView(activity); 225 | } 226 | 227 | /** 228 | * 使状态栏透明(5.0以上半透明效果,不建议使用) 229 | *

230 | * 适用于图片作为背景的界面,此时需要图片填充到状态栏 231 | * 232 | * @param activity 需要设置的activity 233 | */ 234 | @Deprecated 235 | public static void setTranslucentDiff(Activity activity) { 236 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 237 | // 设置状态栏透明 238 | activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 239 | setRootView(activity); 240 | } 241 | } 242 | 243 | /** 244 | * 为DrawerLayout 布局设置状态栏变色 245 | * 246 | * @param activity 需要设置的activity 247 | * @param drawerLayout DrawerLayout 248 | * @param color 状态栏颜色值 249 | */ 250 | public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) { 251 | setColorForDrawerLayout(activity, drawerLayout, color, DEFAULT_STATUS_BAR_ALPHA); 252 | } 253 | 254 | /** 255 | * 为DrawerLayout 布局设置状态栏颜色,纯色 256 | * 257 | * @param activity 需要设置的activity 258 | * @param drawerLayout DrawerLayout 259 | * @param color 状态栏颜色值 260 | */ 261 | public static void setColorNoTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) { 262 | setColorForDrawerLayout(activity, drawerLayout, color, 0); 263 | } 264 | 265 | /** 266 | * 为DrawerLayout 布局设置状态栏变色 267 | * 268 | * @param activity 需要设置的activity 269 | * @param drawerLayout DrawerLayout 270 | * @param color 状态栏颜色值 271 | * @param statusBarAlpha 状态栏透明度 272 | */ 273 | public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color, 274 | @IntRange(from = 0, to = 255) int statusBarAlpha) { 275 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { 276 | return; 277 | } 278 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 279 | activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 280 | activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 281 | activity.getWindow().setStatusBarColor(Color.TRANSPARENT); 282 | } else { 283 | activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 284 | } 285 | // 生成一个状态栏大小的矩形 286 | // 添加 statusBarView 到布局中 287 | ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0); 288 | View fakeStatusBarView = contentLayout.findViewById(FAKE_STATUS_BAR_VIEW_ID); 289 | if (fakeStatusBarView != null) { 290 | if (fakeStatusBarView.getVisibility() == View.GONE) { 291 | fakeStatusBarView.setVisibility(View.VISIBLE); 292 | } 293 | fakeStatusBarView.setBackgroundColor(color); 294 | } else { 295 | contentLayout.addView(createStatusBarView(activity, color), 0); 296 | } 297 | // 内容布局不是 LinearLayout 时,设置padding top 298 | if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) { 299 | contentLayout.getChildAt(1) 300 | .setPadding(contentLayout.getPaddingLeft(), getStatusBarHeight(activity) + contentLayout.getPaddingTop(), 301 | contentLayout.getPaddingRight(), contentLayout.getPaddingBottom()); 302 | } 303 | // 设置属性 304 | setDrawerLayoutProperty(drawerLayout, contentLayout); 305 | addTranslucentView(activity, statusBarAlpha); 306 | } 307 | 308 | /** 309 | * 设置 DrawerLayout 属性 310 | * 311 | * @param drawerLayout DrawerLayout 312 | * @param drawerLayoutContentLayout DrawerLayout 的内容布局 313 | */ 314 | private static void setDrawerLayoutProperty(DrawerLayout drawerLayout, ViewGroup drawerLayoutContentLayout) { 315 | ViewGroup drawer = (ViewGroup) drawerLayout.getChildAt(1); 316 | drawerLayout.setFitsSystemWindows(false); 317 | drawerLayoutContentLayout.setFitsSystemWindows(false); 318 | drawerLayoutContentLayout.setClipToPadding(true); 319 | drawer.setFitsSystemWindows(false); 320 | } 321 | 322 | /** 323 | * 为DrawerLayout 布局设置状态栏变色(5.0以下无半透明效果,不建议使用) 324 | * 325 | * @param activity 需要设置的activity 326 | * @param drawerLayout DrawerLayout 327 | * @param color 状态栏颜色值 328 | */ 329 | @Deprecated 330 | public static void setColorForDrawerLayoutDiff(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) { 331 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 332 | activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 333 | // 生成一个状态栏大小的矩形 334 | ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0); 335 | View fakeStatusBarView = contentLayout.findViewById(FAKE_STATUS_BAR_VIEW_ID); 336 | if (fakeStatusBarView != null) { 337 | if (fakeStatusBarView.getVisibility() == View.GONE) { 338 | fakeStatusBarView.setVisibility(View.VISIBLE); 339 | } 340 | fakeStatusBarView.setBackgroundColor(calculateStatusColor(color, DEFAULT_STATUS_BAR_ALPHA)); 341 | } else { 342 | // 添加 statusBarView 到布局中 343 | contentLayout.addView(createStatusBarView(activity, color), 0); 344 | } 345 | // 内容布局不是 LinearLayout 时,设置padding top 346 | if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) { 347 | contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0); 348 | } 349 | // 设置属性 350 | setDrawerLayoutProperty(drawerLayout, contentLayout); 351 | } 352 | } 353 | 354 | /** 355 | * 为 DrawerLayout 布局设置状态栏透明 356 | * 357 | * @param activity 需要设置的activity 358 | * @param drawerLayout DrawerLayout 359 | */ 360 | public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) { 361 | setTranslucentForDrawerLayout(activity, drawerLayout, DEFAULT_STATUS_BAR_ALPHA); 362 | } 363 | 364 | /** 365 | * 为 DrawerLayout 布局设置状态栏透明 366 | * 367 | * @param activity 需要设置的activity 368 | * @param drawerLayout DrawerLayout 369 | */ 370 | public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout, 371 | @IntRange(from = 0, to = 255) int statusBarAlpha) { 372 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { 373 | return; 374 | } 375 | setTransparentForDrawerLayout(activity, drawerLayout); 376 | addTranslucentView(activity, statusBarAlpha); 377 | } 378 | 379 | /** 380 | * 为 DrawerLayout 布局设置状态栏透明 381 | * 382 | * @param activity 需要设置的activity 383 | * @param drawerLayout DrawerLayout 384 | */ 385 | public static void setTransparentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) { 386 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { 387 | return; 388 | } 389 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 390 | activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 391 | activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 392 | activity.getWindow().setStatusBarColor(Color.TRANSPARENT); 393 | } else { 394 | activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 395 | } 396 | 397 | ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0); 398 | // 内容布局不是 LinearLayout 时,设置padding top 399 | if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) { 400 | contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0); 401 | } 402 | 403 | // 设置属性 404 | setDrawerLayoutProperty(drawerLayout, contentLayout); 405 | } 406 | 407 | /** 408 | * 为 DrawerLayout 布局设置状态栏透明(5.0以上半透明效果,不建议使用) 409 | * 410 | * @param activity 需要设置的activity 411 | * @param drawerLayout DrawerLayout 412 | */ 413 | @Deprecated 414 | public static void setTranslucentForDrawerLayoutDiff(Activity activity, DrawerLayout drawerLayout) { 415 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 416 | // 设置状态栏透明 417 | activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 418 | // 设置内容布局属性 419 | ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0); 420 | contentLayout.setFitsSystemWindows(true); 421 | contentLayout.setClipToPadding(true); 422 | // 设置抽屉布局属性 423 | ViewGroup vg = (ViewGroup) drawerLayout.getChildAt(1); 424 | vg.setFitsSystemWindows(false); 425 | // 设置 DrawerLayout 属性 426 | drawerLayout.setFitsSystemWindows(false); 427 | } 428 | } 429 | 430 | /** 431 | * 为头部是 ImageView 的界面设置状态栏全透明 432 | * 433 | * @param activity 需要设置的activity 434 | * @param needOffsetView 需要向下偏移的 View 435 | */ 436 | public static void setTransparentForImageView(Activity activity, View needOffsetView) { 437 | setTranslucentForImageView(activity, 0, needOffsetView); 438 | } 439 | 440 | /** 441 | * 为头部是 ImageView 的界面设置状态栏透明(使用默认透明度) 442 | * 443 | * @param activity 需要设置的activity 444 | * @param needOffsetView 需要向下偏移的 View 445 | */ 446 | public static void setTranslucentForImageView(Activity activity, View needOffsetView) { 447 | setTranslucentForImageView(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView); 448 | } 449 | 450 | /** 451 | * 为头部是 ImageView 的界面设置状态栏透明 452 | * 453 | * @param activity 需要设置的activity 454 | * @param statusBarAlpha 状态栏透明度 455 | * @param needOffsetView 需要向下偏移的 View 456 | */ 457 | public static void setTranslucentForImageView(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha, 458 | View needOffsetView) { 459 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { 460 | return; 461 | } 462 | setTransparentForWindow(activity); 463 | addTranslucentView(activity, statusBarAlpha); 464 | if (needOffsetView != null) { 465 | Object haveSetOffset = needOffsetView.getTag(TAG_KEY_HAVE_SET_OFFSET); 466 | if (haveSetOffset != null && (Boolean) haveSetOffset) { 467 | return; 468 | } 469 | ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) needOffsetView.getLayoutParams(); 470 | layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin + getStatusBarHeight(activity), 471 | layoutParams.rightMargin, layoutParams.bottomMargin); 472 | needOffsetView.setTag(TAG_KEY_HAVE_SET_OFFSET, true); 473 | } 474 | } 475 | 476 | /** 477 | * 为 fragment 头部是 ImageView 的设置状态栏透明 478 | * 479 | * @param activity fragment 对应的 activity 480 | * @param needOffsetView 需要向下偏移的 View 481 | */ 482 | public static void setTranslucentForImageViewInFragment(Activity activity, View needOffsetView) { 483 | setTranslucentForImageViewInFragment(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView); 484 | } 485 | 486 | /** 487 | * 为 fragment 头部是 ImageView 的设置状态栏透明 488 | * 489 | * @param activity fragment 对应的 activity 490 | * @param needOffsetView 需要向下偏移的 View 491 | */ 492 | public static void setTransparentForImageViewInFragment(Activity activity, View needOffsetView) { 493 | setTranslucentForImageViewInFragment(activity, 0, needOffsetView); 494 | } 495 | 496 | /** 497 | * 为 fragment 头部是 ImageView 的设置状态栏透明 498 | * 499 | * @param activity fragment 对应的 activity 500 | * @param statusBarAlpha 状态栏透明度 501 | * @param needOffsetView 需要向下偏移的 View 502 | */ 503 | public static void setTranslucentForImageViewInFragment(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha, 504 | View needOffsetView) { 505 | setTranslucentForImageView(activity, statusBarAlpha, needOffsetView); 506 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { 507 | clearPreviousSetting(activity); 508 | } 509 | } 510 | 511 | /** 512 | * 隐藏伪状态栏 View 513 | * 514 | * @param activity 调用的 Activity 515 | */ 516 | public static void hideFakeStatusBarView(Activity activity) { 517 | ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView(); 518 | View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID); 519 | if (fakeStatusBarView != null) { 520 | fakeStatusBarView.setVisibility(View.GONE); 521 | } 522 | View fakeTranslucentView = decorView.findViewById(FAKE_TRANSLUCENT_VIEW_ID); 523 | if (fakeTranslucentView != null) { 524 | fakeTranslucentView.setVisibility(View.GONE); 525 | } 526 | } 527 | 528 | @TargetApi(Build.VERSION_CODES.M) 529 | public static void setLightMode(Activity activity) { 530 | setMIUIStatusBarDarkIcon(activity, true); 531 | setMeizuStatusBarDarkIcon(activity, true); 532 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 533 | activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); 534 | } 535 | } 536 | 537 | @TargetApi(Build.VERSION_CODES.M) 538 | public static void setDarkMode(Activity activity) { 539 | setMIUIStatusBarDarkIcon(activity, false); 540 | setMeizuStatusBarDarkIcon(activity, false); 541 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 542 | activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); 543 | } 544 | } 545 | 546 | /** 547 | * 修改 MIUI V6 以上状态栏颜色 548 | */ 549 | private static void setMIUIStatusBarDarkIcon(@NonNull Activity activity, boolean darkIcon) { 550 | Class clazz = activity.getWindow().getClass(); 551 | try { 552 | Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams"); 553 | Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE"); 554 | int darkModeFlag = field.getInt(layoutParams); 555 | Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class); 556 | extraFlagField.invoke(activity.getWindow(), darkIcon ? darkModeFlag : 0, darkModeFlag); 557 | } catch (Exception e) { 558 | //e.printStackTrace(); 559 | } 560 | } 561 | 562 | /** 563 | * 修改魅族状态栏字体颜色 Flyme 4.0 564 | */ 565 | private static void setMeizuStatusBarDarkIcon(@NonNull Activity activity, boolean darkIcon) { 566 | try { 567 | WindowManager.LayoutParams lp = activity.getWindow().getAttributes(); 568 | Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON"); 569 | Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags"); 570 | darkFlag.setAccessible(true); 571 | meizuFlags.setAccessible(true); 572 | int bit = darkFlag.getInt(null); 573 | int value = meizuFlags.getInt(lp); 574 | if (darkIcon) { 575 | value |= bit; 576 | } else { 577 | value &= ~bit; 578 | } 579 | meizuFlags.setInt(lp, value); 580 | activity.getWindow().setAttributes(lp); 581 | } catch (Exception e) { 582 | //e.printStackTrace(); 583 | } 584 | } 585 | 586 | /////////////////////////////////////////////////////////////////////////////////// 587 | 588 | @TargetApi(Build.VERSION_CODES.KITKAT) 589 | private static void clearPreviousSetting(Activity activity) { 590 | ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView(); 591 | View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID); 592 | if (fakeStatusBarView != null) { 593 | decorView.removeView(fakeStatusBarView); 594 | ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0); 595 | rootView.setPadding(0, 0, 0, 0); 596 | } 597 | } 598 | 599 | /** 600 | * 添加半透明矩形条 601 | * 602 | * @param activity 需要设置的 activity 603 | * @param statusBarAlpha 透明值 604 | */ 605 | private static void addTranslucentView(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) { 606 | ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content); 607 | View fakeTranslucentView = contentView.findViewById(FAKE_TRANSLUCENT_VIEW_ID); 608 | if (fakeTranslucentView != null) { 609 | if (fakeTranslucentView.getVisibility() == View.GONE) { 610 | fakeTranslucentView.setVisibility(View.VISIBLE); 611 | } 612 | fakeTranslucentView.setBackgroundColor(Color.argb(statusBarAlpha, 255, 255, 255)); 613 | } else { 614 | contentView.addView(createTranslucentStatusBarView(activity, statusBarAlpha)); 615 | } 616 | } 617 | 618 | /** 619 | * 生成一个和状态栏大小相同的彩色矩形条 620 | * 621 | * @param activity 需要设置的 activity 622 | * @param color 状态栏颜色值 623 | * @return 状态栏矩形条 624 | */ 625 | private static View createStatusBarView(Activity activity, @ColorInt int color) { 626 | return createStatusBarView(activity, color, 0); 627 | } 628 | 629 | /** 630 | * 生成一个和状态栏大小相同的半透明矩形条 631 | * 632 | * @param activity 需要设置的activity 633 | * @param color 状态栏颜色值 634 | * @param alpha 透明值 635 | * @return 状态栏矩形条 636 | */ 637 | private static View createStatusBarView(Activity activity, @ColorInt int color, int alpha) { 638 | // 绘制一个和状态栏一样高的矩形 639 | View statusBarView = new View(activity); 640 | LinearLayout.LayoutParams params = 641 | new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity)); 642 | statusBarView.setLayoutParams(params); 643 | statusBarView.setBackgroundColor(calculateStatusColor(color, alpha)); 644 | statusBarView.setId(FAKE_STATUS_BAR_VIEW_ID); 645 | return statusBarView; 646 | } 647 | 648 | /** 649 | * 设置根布局参数 650 | */ 651 | private static void setRootView(Activity activity) { 652 | ViewGroup parent = (ViewGroup) activity.findViewById(android.R.id.content); 653 | for (int i = 0, count = parent.getChildCount(); i < count; i++) { 654 | View childView = parent.getChildAt(i); 655 | if (childView instanceof ViewGroup) { 656 | childView.setFitsSystemWindows(true); 657 | ((ViewGroup) childView).setClipToPadding(true); 658 | } 659 | } 660 | } 661 | 662 | /** 663 | * 设置透明 664 | */ 665 | private static void setTransparentForWindow(Activity activity) { 666 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 667 | activity.getWindow().setStatusBarColor(Color.TRANSPARENT); 668 | activity.getWindow() 669 | .getDecorView() 670 | .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); 671 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 672 | activity.getWindow() 673 | .setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 674 | } 675 | } 676 | 677 | /** 678 | * 使状态栏透明 679 | */ 680 | @TargetApi(Build.VERSION_CODES.KITKAT) 681 | private static void transparentStatusBar(Activity activity) { 682 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 683 | activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 684 | activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 685 | activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 686 | activity.getWindow().setStatusBarColor(Color.TRANSPARENT); 687 | } else { 688 | activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 689 | } 690 | } 691 | 692 | /** 693 | * 创建半透明矩形 View 694 | * 695 | * @param alpha 透明值 696 | * @return 半透明 View 697 | */ 698 | private static View createTranslucentStatusBarView(Activity activity, int alpha) { 699 | // 绘制一个和状态栏一样高的矩形 700 | View statusBarView = new View(activity); 701 | LinearLayout.LayoutParams params = 702 | new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity)); 703 | statusBarView.setLayoutParams(params); 704 | statusBarView.setBackgroundColor(Color.argb(alpha, 0, 0, 0)); 705 | statusBarView.setId(FAKE_TRANSLUCENT_VIEW_ID); 706 | return statusBarView; 707 | } 708 | 709 | /** 710 | * 获取状态栏高度 711 | * 712 | * @param context context 713 | * @return 状态栏高度 714 | */ 715 | public static int getStatusBarHeight(Context context) { 716 | // 获得状态栏高度 717 | int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); 718 | return context.getResources().getDimensionPixelSize(resourceId); 719 | } 720 | 721 | /** 722 | * 计算状态栏颜色 723 | * 724 | * @param color color值 725 | * @param alpha alpha值 726 | * @return 最终的状态栏颜色 727 | */ 728 | private static int calculateStatusColor(@ColorInt int color, int alpha) { 729 | if (alpha == 0) { 730 | return color; 731 | } 732 | float a = 1 - alpha / 255f; 733 | int red = color >> 16 & 0xff; 734 | int green = color >> 8 & 0xff; 735 | int blue = color & 0xff; 736 | red = (int) (red * a + 0.5); 737 | green = (int) (green * a + 0.5); 738 | blue = (int) (blue * a + 0.5); 739 | return 0xff << 24 | red << 16 | green << 8 | blue; 740 | } 741 | 742 | /** 743 | * 设置文字颜色 744 | */ 745 | public static void setStatusBarFontIconDark(Activity activity,@ViewType int type) { 746 | switch (type) { 747 | case TYPE_MIUI: 748 | setMiuiUI(activity,true); 749 | break; 750 | case TYPE_M: 751 | setCommonUI(activity); 752 | break; 753 | case TYPE_FLYME: 754 | setFlymeUI(activity,true); 755 | break; 756 | } 757 | } 758 | 759 | //设置6.0的字体 760 | public static void setCommonUI(Activity activity) { 761 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 762 | activity.getWindow().getDecorView().setSystemUiVisibility( 763 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 764 | | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); 765 | } 766 | } 767 | 768 | //设置Flyme的字体 769 | public static void setFlymeUI(Activity activity,boolean dark) { 770 | try { 771 | Window window = activity.getWindow(); 772 | WindowManager.LayoutParams lp = window.getAttributes(); 773 | Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON"); 774 | Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags"); 775 | darkFlag.setAccessible(true); 776 | meizuFlags.setAccessible(true); 777 | int bit = darkFlag.getInt(null); 778 | int value = meizuFlags.getInt(lp); 779 | if (dark) { 780 | value |= bit; 781 | } else { 782 | value &= ~bit; 783 | } 784 | meizuFlags.setInt(lp, value); 785 | window.setAttributes(lp); 786 | } catch (Exception e) { 787 | e.printStackTrace(); 788 | } 789 | } 790 | 791 | //设置MIUI字体 792 | public static void setMiuiUI(Activity activity,boolean dark) { 793 | try { 794 | Window window = activity.getWindow(); 795 | Class clazz = activity.getWindow().getClass(); 796 | Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams"); 797 | Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE"); 798 | int darkModeFlag = field.getInt(layoutParams); 799 | Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class); 800 | if (dark) { //状态栏亮色且黑色字体 801 | extraFlagField.invoke(window, darkModeFlag, darkModeFlag); 802 | } else { 803 | extraFlagField.invoke(window, 0, darkModeFlag); 804 | } 805 | } catch (Exception e) { 806 | e.printStackTrace(); 807 | } 808 | } 809 | 810 | } 811 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/my_cursor.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/popu_dialog_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_input_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_map_draw_point_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/layout/act_first.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/act_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | 12 | 18 | 19 | 30 | 31 | 36 | 37 | 45 | 46 | 54 | 55 | 56 | 57 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_dialog_notice.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 17 | 31 | 32 | 33 | 38 | 39 | 44 | 45 | 56 | 57 | 61 | 62 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_ensure_notitle_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 17 | 25 | 26 | 27 | 32 | 33 | 38 | 39 | 48 | 49 | 53 | 54 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /app/src/main/res/layout/map_draw_marker.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 11 | 12 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/map_draw_marker_big_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 11 | 12 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/map_draw_marker_small_white.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 11 | 12 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuezhongyang/MapDrawDemo/018d9f2ece6a4bea8f5466a96cbaf0db922b7d89/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuezhongyang/MapDrawDemo/018d9f2ece6a4bea8f5466a96cbaf0db922b7d89/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuezhongyang/MapDrawDemo/018d9f2ece6a4bea8f5466a96cbaf0db922b7d89/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuezhongyang/MapDrawDemo/018d9f2ece6a4bea8f5466a96cbaf0db922b7d89/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/arrow_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuezhongyang/MapDrawDemo/018d9f2ece6a4bea8f5466a96cbaf0db922b7d89/app/src/main/res/mipmap-xhdpi/arrow_back.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/arrow_next_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuezhongyang/MapDrawDemo/018d9f2ece6a4bea8f5466a96cbaf0db922b7d89/app/src/main/res/mipmap-xhdpi/arrow_next_white.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuezhongyang/MapDrawDemo/018d9f2ece6a4bea8f5466a96cbaf0db922b7d89/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuezhongyang/MapDrawDemo/018d9f2ece6a4bea8f5466a96cbaf0db922b7d89/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/iv_cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuezhongyang/MapDrawDemo/018d9f2ece6a4bea8f5466a96cbaf0db922b7d89/app/src/main/res/mipmap-xhdpi/iv_cancel.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/iv_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuezhongyang/MapDrawDemo/018d9f2ece6a4bea8f5466a96cbaf0db922b7d89/app/src/main/res/mipmap-xhdpi/iv_delete.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/map_handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuezhongyang/MapDrawDemo/018d9f2ece6a4bea8f5466a96cbaf0db922b7d89/app/src/main/res/mipmap-xhdpi/map_handle.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/map_positioning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuezhongyang/MapDrawDemo/018d9f2ece6a4bea8f5466a96cbaf0db922b7d89/app/src/main/res/mipmap-xhdpi/map_positioning.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuezhongyang/MapDrawDemo/018d9f2ece6a4bea8f5466a96cbaf0db922b7d89/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuezhongyang/MapDrawDemo/018d9f2ece6a4bea8f5466a96cbaf0db922b7d89/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuezhongyang/MapDrawDemo/018d9f2ece6a4bea8f5466a96cbaf0db922b7d89/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuezhongyang/MapDrawDemo/018d9f2ece6a4bea8f5466a96cbaf0db922b7d89/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | #333333 8 | #70C160 9 | #DDDDDD 10 | #ffffff 11 | #80FF0000 12 | #80269A3F 13 | #80000000 14 | #1A000000 15 | #33000000 16 | #40000000 17 | #4D000000 18 | #66000000 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | MapDrawDemo 3 | 应用需要定位权限和存储读写权限 4 | 同意 5 | 取消 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | google() 6 | jcenter() 7 | } 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.5.2' 10 | 11 | // NOTE: Do not place your application dependencies here; they belong 12 | // in the individual module build.gradle files 13 | } 14 | } 15 | 16 | allprojects { 17 | repositories { 18 | google() 19 | jcenter() 20 | } 21 | } 22 | 23 | task clean(type: Delete) { 24 | delete rootProject.buildDir 25 | } 26 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | #android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | #android.enableJetifier=true 20 | 21 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuezhongyang/MapDrawDemo/018d9f2ece6a4bea8f5466a96cbaf0db922b7d89/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Jul 23 16:44:47 CST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | rootProject.name='MapDrawDemo' 3 | --------------------------------------------------------------------------------