├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── junmeng │ │ └── region │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── junmeng │ │ │ └── region │ │ │ ├── MainActivity.java │ │ │ └── RegionDetectSViewActivity.java │ └── res │ │ ├── drawable │ │ ├── ic_china.xml │ │ └── ic_chinalow.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_region_detect_sview.xml │ │ └── activity_region_detect_view.xml │ │ ├── menu │ │ └── menu_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── junmeng │ └── region │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── lib_regiondetector ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── junmeng │ │ │ └── rdetecte │ │ │ ├── bean │ │ │ ├── MapPathInfo.java │ │ │ └── VectorPathInfo.java │ │ │ ├── utils │ │ │ ├── CommonUtil.java │ │ │ ├── PathParser.java │ │ │ └── VectorMapParser.java │ │ │ └── widget │ │ │ ├── BaseSurfaceView.java │ │ │ └── RegionDetectSurfaceView.java │ └── res │ │ ├── drawable │ │ ├── ic_location_24dp.xml │ │ └── ic_map_china.xml │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── junmeng │ └── rdetecte │ └── ExampleUnitTest.java ├── screenshots ├── QQ截图20170220173408.png ├── device-2017-02-20-174131.mp4_1487584213.gif ├── device-2017-02-20-174131.mp4_1487584269.gif └── device-2017-02-20-174131.mp4_1487584566.gif └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | 34 | 35 | 36 | 37 | 1.8 38 | 39 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RegionDetector 2 | 一个支持灵活设置的不规则区域检测控件 3 | --- 4 | 5 | ![image](https://github.com/huweijian5/RegionDetector/blob/master/screenshots/QQ%E6%88%AA%E5%9B%BE20170220173408.png) 6 | 7 | ![image](https://github.com/huweijian5/RegionDetector/blob/master/screenshots/device-2017-02-20-174131.mp4_1487584213.gif) 8 | ![image](https://github.com/huweijian5/RegionDetector/blob/master/screenshots/device-2017-02-20-174131.mp4_1487584269.gif) 9 | ![image](https://github.com/huweijian5/RegionDetector/blob/master/screenshots/device-2017-02-20-174131.mp4_1487584566.gif) 10 | --- 11 | ## 更新说明 12 | > 1.1.0 13 | * 去除反射 14 | * 增加矢量图解析器,路径解析器 15 | * 兼容到API27 16 | 17 | 18 | --- 19 | ## 介绍说明 20 | 21 | * 此控件支持不规则区域的识别监测,采用矢量图,有效降低内存,常用来做地图区域识别 22 | * 支持手动点击模式和中心点定位模式 23 | * 支持缩放位移操作 24 | * 支持双击缩放操作 25 | * 提供渐变动画,拒绝生硬 26 | * 支持自定义矢量图,但需满足一定要求 27 | * 开放众多接口满足个性化定制 28 | * ... 29 | 30 | --- 31 | ## 原理介绍 32 | [实现思路介绍](http://blog.csdn.net/huweijian5/article/details/78921793) 33 | 34 | --- 35 | ## 使用说明 36 | * 布局xml中添加: 37 | ``` 38 | 42 | ``` 43 | * 设置激活区域: 44 | ```java 45 | int[] areaRes = new int[]{ 46 | R.string.china_anhui, R.string.china_beijing, R.string.china_guangdong 47 | , R.string.china_chongqing, R.string.china_xinjiang, R.string.china_fujian 48 | , R.string.china_gansu, R.string.china_zhejiang, R.string.china_yunnan 49 | , R.string.china_xizang, R.string.china_tianjin 50 | , R.string.china_shandong, R.string.china_heilongjiang, R.string.china_hainan 51 | }; 52 | binding.rdvDetect.setAreaActivateStatus(areaRes, true); 53 | ``` 54 | * 全部区域请查看: 55 | ``` 56 | 57 | 北京 58 | 天津 59 | 上海 60 | 重庆 61 | 河北 62 | 山西 63 | 辽宁 64 | 吉林 65 | 黑龙江 66 | 江苏 67 | 浙江 68 | 安徽 69 | 福建 70 | 江西 71 | 山东 72 | 河南 73 | 湖北 74 | 湖南 75 | 广东 76 | 海南 77 | 四川 78 | 贵州 79 | 云南 80 | 陕西 81 | 甘肃 82 | 青海 83 | 台湾 84 | 内蒙古 85 | 广西 86 | 西藏 87 | 宁夏 88 | 新疆 89 | 香港 90 |     91 | ``` 92 | * 设置监听器: 93 | ``` 94 | binding.rdvDetect.setOnActivateRegionDetectListener(new RegionDetectSurfaceView.OnActivateRegionDetectListener() { 95 | @Override 96 | public void onActivateRegionDetect(String name) { 97 | binding.tvActivate.setText("高亮区域:" + name); 98 | binding.rdvDetect.setSelectedAreaOnlyCloseCenterLocation(name); 99 | } 100 | }); 101 | binding.rdvDetect.setOnRegionDetectListener(new RegionDetectSurfaceView.OnRegionDetectListener() { 102 | @Override 103 | public void onRegionDetect(String name) { 104 | binding.tvDetect.setText("当前区域:" + name); 105 | } 106 | }); 107 | 108 | binding.rdvDetect.setOnDoubleClickListener(new RegionDetectSurfaceView.OnDoubleClickListener() { 109 | @Override 110 | public void onDoubleClick(@RegionDetectSurfaceView.ScaleMode int scaleMode) { 111 | binding.tvZoom.setText("双击操作:" + (scaleMode == SCALE_ZOOMIN ? "放大" : "缩小")); 112 | } 113 | }); 114 | ``` 115 | * 至此最简单的引用方式已经结束了。 116 | 117 | ### 常用api说明: 118 | 119 | > public void setRegionDetectMode(@RegionDetectMode int detectMode); 120 | * 可在此设置支持的模式为手动点击模式和中心定位模式 121 | * 手动点击模式符合一般使用习惯,但区域较小时很难点击 122 | * 中心定位模式则可以较细致的定位,推荐使用,默认也是此模式 123 | 124 | --- 125 | > public void setCenterIcon(Bitmap bitmap); 126 | * 自定义中心定位图标 127 | 128 | --- 129 | > public void setCenterIconLocationType(@CenterIconLocationType int locationType); 130 | * 设置中心定位图标的定位位置,支持图标中心和图标底部两种 131 | 132 | --- 133 | > public void fitCenter(); 134 | * 将地图适合屏幕缩放并居中 135 | 136 | --- 137 | > public void setAreaColor(@NonNull String areaName, @ColorInt int highlightColor, @ColorInt int activatedColor, @ColorInt int normalColor); 138 | * 设置区域高亮颜色,激活颜色和普通颜色 139 | * 此设置优先级高于默认的颜色,如上图的广东会变成黄色 140 | 141 | --- 142 | > public void setAreaMap(@DrawableRes int map, int originalWidth, int originalHeight); 143 | * 自定义区域地图 144 | * 矢量图格式需要如下: 145 | ``` 146 | 151 | 152 | 159 | 160 | 167 | 168 | 175 | ...... 176 | 177 | ``` 178 | * 其中vector元素的viewportHeight和viewportWidth以及path元素的name和pathData必须设置 179 | 180 | --- 181 | > 更多请详看在线文档或源码及参照demo 182 | 183 | --- 184 | ## JavaDoc文档 185 | 186 | * [在线JavaDoc](https://jitpack.io/com/github/huweijian5/RegionDetector/1.0.0/javadoc/index.html) 187 | * 网址:`https://jitpack.io/com/github/huweijian5/RegionDetector/[VersionCode]/javadoc/index.html` 188 | * 其中[VersionCode](https://github.com/huweijian5/RegionDetector/releases)请替换为最新版本号 189 | * 注意文档使用UTF-8编码,如遇乱码,请在浏览器选择UTF-8编码即可 190 | 191 | --- 192 | ## 引用 193 | 194 | * 如果需要引用此库,做法如下: 195 | * Add it in your root build.gradle at the end of repositories: 196 | ``` 197 | allprojects { 198 | repositories { 199 | ... 200 | maven { url "https://jitpack.io" } 201 | } 202 | } 203 | ``` 204 | * and then,add the dependecy: 205 | ``` 206 | dependencies { 207 | compile 'com.github.huweijian5:RegionDetector:latest_version' 208 | } 209 | ``` 210 | * 其中latest_version请到[releases](https://github.com/huweijian5/RegionDetector/releases)中查看 211 | 212 | ## 注意 213 | * 为了避免引入第三方库导致工程依赖多个版本的问题,如android support库 214 | * 故建议在个人的工程目录下的build.gradle下加入以下变量,具体请看此[build.gradle](https://github.com/huweijian5/RegionDetector/blob/master/build.gradle) 215 | ``` 216 | ext{ 217 | minSdkVersion = 16 218 | targetSdkVersion = 25 219 | compileSdkVersion = 26 220 | buildToolsVersion = '26.0.1' 221 | 222 | // App dependencies 223 | supportLibraryVersion = '26.1.0' 224 | junitVersion = '4.12' 225 | espressoVersion = '2.2.2' 226 | } 227 | ``` 228 | * 请注意,对于此库已有的变量,命名请保持一致 229 | 230 | 231 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | dataBinding{ 5 | enabled=true 6 | } 7 | 8 | compileSdkVersion rootProject.compileSdkVersion 9 | buildToolsVersion rootProject.buildToolsVersion 10 | defaultConfig { 11 | applicationId "com.junmeng.region" 12 | minSdkVersion rootProject.minSdkVersion 13 | targetSdkVersion rootProject.targetSdkVersion 14 | versionCode 1 15 | versionName "1.0" 16 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 17 | vectorDrawables.useSupportLibrary = true 18 | } 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | } 26 | 27 | dependencies { 28 | compile fileTree(include: ['*.jar'], dir: 'libs') 29 | androidTestCompile("com.android.support.test.espresso:espresso-core:$rootProject.espressoVersion", { 30 | exclude group: 'com.android.support', module: 'support-annotations' 31 | }) 32 | compile "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion" 33 | testCompile "junit:junit:$rootProject.junitVersion" 34 | 35 | compile project(':lib_regiondetector') 36 | } 37 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in E:\Android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/junmeng/region/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.junmeng.region; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.junmeng.region", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/junmeng/region/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.junmeng.region; 2 | 3 | import android.content.Intent; 4 | import android.databinding.DataBindingUtil; 5 | import android.os.Bundle; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.support.v7.app.AppCompatDelegate; 8 | import android.view.View; 9 | 10 | import com.junmeng.region.databinding.ActivityMainBinding; 11 | 12 | public class MainActivity extends AppCompatActivity { 13 | static { 14 | AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); 15 | } 16 | 17 | ActivityMainBinding binding; 18 | 19 | @Override 20 | protected void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | binding = DataBindingUtil.setContentView(this, R.layout.activity_main); 23 | } 24 | 25 | 26 | public void onClickRDSV(View view) { 27 | Intent intent = new Intent(this, RegionDetectSViewActivity.class); 28 | startActivity(intent); 29 | } 30 | 31 | public void onClickRDV(View view) { 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/junmeng/region/RegionDetectSViewActivity.java: -------------------------------------------------------------------------------- 1 | package com.junmeng.region; 2 | 3 | import android.databinding.DataBindingUtil; 4 | import android.graphics.Color; 5 | import android.os.Bundle; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.util.Log; 8 | import android.view.Menu; 9 | import android.view.MenuItem; 10 | 11 | import com.junmeng.rdetecte.utils.CommonUtil; 12 | import com.junmeng.rdetecte.utils.VectorMapParser; 13 | import com.junmeng.rdetecte.widget.RegionDetectSurfaceView; 14 | import com.junmeng.region.databinding.ActivityRegionDetectSviewBinding; 15 | 16 | import static com.junmeng.rdetecte.widget.RegionDetectSurfaceView.SCALE_ZOOMIN; 17 | 18 | public class RegionDetectSViewActivity extends AppCompatActivity { 19 | private static final String TAG = "RegionDetectSViewActivi"; 20 | int[] areaRes = new int[]{ 21 | R.string.china_anhui, R.string.china_beijing, R.string.china_guangdong 22 | , R.string.china_chongqing, R.string.china_xinjiang, R.string.china_fujian 23 | , R.string.china_gansu, R.string.china_zhejiang, R.string.china_yunnan 24 | , R.string.china_xizang, R.string.china_tianjin 25 | , R.string.china_shandong, R.string.china_heilongjiang, R.string.china_hainan 26 | }; 27 | 28 | int[] areaRes2 = new int[]{ 29 | R.string.china_anhui, R.string.china_beijing, R.string.china_guangdong 30 | , R.string.china_chongqing, R.string.china_shanxi, R.string.china_neimenggu 31 | , R.string.china_fujian, R.string.china_gansu, R.string.china_zhejiang 32 | , R.string.china_yunnan, R.string.china_liaoning, R.string.china_tianjin 33 | , R.string.china_shandong, R.string.china_heilongjiang, R.string.china_hainan 34 | }; 35 | 36 | ActivityRegionDetectSviewBinding binding; 37 | 38 | @Override 39 | protected void onCreate(Bundle savedInstanceState) { 40 | super.onCreate(savedInstanceState); 41 | binding = DataBindingUtil.setContentView(this, R.layout.activity_region_detect_sview); 42 | binding.rdvDetect.setOnActivateRegionDetectListener(new RegionDetectSurfaceView.OnActivateRegionDetectListener() { 43 | @Override 44 | public void onActivateRegionDetect(String name) { 45 | binding.tvActivate.setText("高亮区域:" + name); 46 | binding.rdvDetect.setSelectedAreaOnlyCloseCenterLocation(name); 47 | } 48 | }); 49 | binding.rdvDetect.setOnRegionDetectListener(new RegionDetectSurfaceView.OnRegionDetectListener() { 50 | @Override 51 | public void onRegionDetect(String name) { 52 | binding.tvDetect.setText("当前区域:" + name); 53 | } 54 | }); 55 | 56 | binding.rdvDetect.setOnDoubleClickListener(new RegionDetectSurfaceView.OnDoubleClickListener() { 57 | @Override 58 | public void onDoubleClick(@RegionDetectSurfaceView.ScaleMode int scaleMode) { 59 | binding.tvZoom.setText("双击操作:" + (scaleMode == SCALE_ZOOMIN ? "放大" : "缩小")); 60 | } 61 | }); 62 | 63 | //binding.rdvDetect.setCenterIcon(CommonUtil.getBitmapFromVectorDrawable(this,R.mipmap.ic_launcher)); 64 | //binding.rdvDetect.setAllAreaActivateStatus(true); 65 | binding.rdvDetect.setAreaActivateStatus(areaRes, true); 66 | binding.rdvDetect.setAreaColor(R.string.china_guangdong, Color.YELLOW, -1, -1); 67 | binding.rdvDetect.setCenterIconVisibility(true); 68 | //binding.rdvDetect.setCenterIconLocationType(RegionDetectSurfaceView.CENTER_ICON_POSITION_CENTER); 69 | binding.rdvDetect.setDefaultNormalColor(0x8069BBA8); 70 | binding.rdvDetect.setDefaultActivateColor(0x802F8BBB); 71 | binding.rdvDetect.setDefaultHighlightColor(0x80BB945A); 72 | binding.rdvDetect.setBackgroundColor(0xFFdddddd); 73 | } 74 | 75 | 76 | @Override 77 | public boolean onCreateOptionsMenu(Menu menu) { 78 | getMenuInflater().inflate(R.menu.menu_main, menu); 79 | return super.onCreateOptionsMenu(menu); 80 | } 81 | 82 | @Override 83 | public boolean onOptionsItemSelected(MenuItem item) { 84 | int id = item.getItemId(); 85 | Log.i(TAG, "onContextItemSelected: "); 86 | switch (id) { 87 | case R.id.m_fitcenter: 88 | binding.rdvDetect.fitCenter(); 89 | break; 90 | case R.id.m_change_icon: 91 | binding.rdvDetect.setCenterIcon(CommonUtil.getBitmapFromVectorDrawable(this,R.mipmap.ic_launcher)); 92 | break; 93 | case R.id.m_toggle: 94 | binding.rdvDetect.setAreaMap(R.drawable.ic_china); 95 | binding.rdvDetect.setAreaActivateStatus(areaRes2, true); 96 | binding.rdvDetect.setAreaColor(R.string.china_guangdong, Color.YELLOW, -1, -1); 97 | binding.rdvDetect.setDefaultNormalColor(0x8069BBA8); 98 | binding.rdvDetect.setDefaultActivateColor(0x802F8BBB); 99 | binding.rdvDetect.setDefaultHighlightColor(0x80BB945A); 100 | binding.rdvDetect.setBackgroundColor(0xFFFFCAF3); 101 | break; 102 | case R.id.m_mode_center: 103 | binding.rdvDetect.setRegionDetectMode(RegionDetectSurfaceView.REGION_DETECT_MODE_CENTER); 104 | break; 105 | case R.id.m_mode_click: 106 | binding.rdvDetect.setRegionDetectMode(RegionDetectSurfaceView.REGION_DETECT_MODE_CLICK); 107 | break; 108 | } 109 | return super.onOptionsItemSelected(item); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_china.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 22 | 23 | 24 | 28 | 29 | 33 | 34 | 38 | 39 | 43 | 44 | 48 | 49 | 53 | 54 | 58 | 59 | 63 | 64 | 68 | 69 | 73 | 74 | 78 | 79 | 83 | 84 | 88 | 89 | 93 | 94 | 98 | 99 | 103 | 104 | 108 | 109 | 113 | 114 | 118 | 119 | 123 | 124 | 128 | 129 | 133 | 134 | 138 | 139 | 143 | 144 | 148 | 149 | 172 | 173 | 177 | 178 | 182 | 183 | 187 | 188 | 192 | 193 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 15 | 16 | 17 |