├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── smarttop │ │ └── addressselector │ │ └── ExampleInstrumentedTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── smarttop │ │ └── addressselector │ │ └── activity │ │ └── MainActivity.java │ └── res │ ├── layout │ └── activity_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 ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── smarttop │ │ └── library │ │ └── ExampleInstrumentedTest.java │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── address.db │ ├── java │ └── com │ │ └── smarttop │ │ └── library │ │ ├── bean │ │ ├── AdressBean.java │ │ ├── City.java │ │ ├── County.java │ │ ├── Province.java │ │ └── Street.java │ │ ├── db │ │ ├── AssetsDatabaseManager.java │ │ ├── DBOpenHelper.java │ │ ├── DBUtils.java │ │ ├── TableField.java │ │ └── manager │ │ │ └── AddressDictManager.java │ │ ├── utils │ │ ├── Dev.java │ │ ├── GlobalParams.java │ │ ├── Lists.java │ │ └── LogUtil.java │ │ └── widget │ │ ├── AddressSelector.java │ │ ├── BottomDialog.java │ │ ├── OnAddressSelectedListener.java │ │ └── UninterceptableListView.java │ └── res │ ├── anim │ ├── bottom_dialog_enter.xml │ └── bottom_dialog_exit.xml │ ├── color │ └── selector_text_color_tab.xml │ ├── drawable-xxhdpi │ └── icon_close.png │ ├── drawable-xxxhdpi │ └── ic_check.png │ ├── layout │ ├── address_selector.xml │ └── item_area.xml │ └── values │ ├── strings.xml │ └── style.xml ├── screenshots ├── screenshort2.png ├── screenshort3.png ├── screenshort4.png ├── screenshort5.png └── screenshot1.gif └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | /captures 8 | *.iml 9 | .idea 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AddressSelector 2 | 3 | 一个 Android 版京东手机客户端(当前版本V1..0.0 )风格的级联地址选择器。 4 | ![image](https://github.com/smartTop/AddressSelector/blob/master/screenshots/screenshot1.gif) 5 | ## 添加依赖 6 | 7 | 在`build.gradle` 中: 8 | 9 | dependencies { 10 | ... 11 | compile 'com.smartTop:jd-address:1.0.3' 12 | } 13 | 14 | ## 使用方法 15 | 16 | AddressSelector selector = new AddressSelector(context); 17 | selector.setOnAddressSelectedListener(new AddressSelector.OnAddressSelectedListener() { 18 | @Override 19 | public void onAddressSelected(Province province, City city, County county, Street street) { 20 | // blahblahblah 21 | } 22 | }); 23 | 24 | View view = selector.getView(); 25 | content.addView(view); 26 | 27 | 默认的样式 28 | ![image](https://github.com/smartTop/AddressSelector/blob/master/screenshots/screenshort4.png) 29 | 30 | 31 | 自定义样式 32 | 33 | //设置字体的大小 34 | 35 | selector.setTextSize(14); 36 | 37 | //设置指示器的背景颜色 38 | 39 | selector.setIndicatorBackgroundColor("#00ff00"); 40 | 41 | 或 42 | 43 | selector.setIndicatorBackgroundColor(android.R.color.holo_orange_light); 44 | 45 | //设置字体的背景 46 | 47 | selector.setBackgroundColor(android.R.color.holo_red_light); 48 | 49 | //设置字体获得焦点的颜色 50 | 51 | selector.setTextSelectedColor(android.R.color.holo_orange_light); 52 | 53 | //设置字体没有获得焦点的颜色 54 | 55 | selector.setTextUnSelectedColor(android.R.color.holo_blue_light); 56 | 57 | //自定义dialog的样式 58 | 59 | dialog.setTextSize(14);//设置字体的大小 60 | dialog.setIndicatorBackgroundColor(android.R.color.holo_orange_light);//设置指示器的颜色 61 | dialog.setTextSelectedColor(android.R.color.holo_orange_light);//设置字体获得焦点的颜色 62 | dialog.setTextUnSelectedColor(android.R.color.holo_blue_light);//设置字体没有获得焦点的颜色 63 | dialog.setDisplaySelectorArea("31",1,"2704",1,"2711",0,"15582",1);//设置已选中的地区(第一个参数 省份的code,第二个参数 省份在列表中的位置,第三个参数 城市的code 第四个参数 城市在列表中的位置,...) 64 | 效果图 65 | ![image](https://github.com/smartTop/AddressSelector/blob/master/screenshots/screenshort5.png) 66 | 67 | 68 | ### BottomDialog 弹出地址选择器的dialog的用法及回调 69 | 70 | BottomDialog dialog = new BottomDialog(context); 71 | dialog.setOnAddressSelectedListener(this); 72 | dialog.setDialogDismisListener(this); 73 | dialog.setSelectorAreaPositionListener(this); 74 | dialog.show(); 75 | 76 | @Override 77 | public void onAddressSelected(Province province, City city, County county, Street street) { 78 | provinceCode = (province == null ? "" : province.code); 79 | cityCode = (city == null ? "" : city.code); 80 | countyCode = (county == null ? "" : county.code); 81 | streetCode = (street == null ? "" : street.code); 82 | LogUtil.d("数据", "省份id=" + provinceCode); 83 | LogUtil.d("数据", "城市id=" + cityCode); 84 | LogUtil.d("数据", "乡镇id=" + countyCode); 85 | LogUtil.d("数据", "街道id=" + streetCode); 86 | String s = (province == null ? "" : province.name) + (city == null ? "" : city.name) + (county == null ? "" : county.name) + 87 | (street == null ? "" : street.name); 88 | tv_selector_area.setText(s); 89 | if (dialog != null) { 90 | dialog.dismiss(); 91 | } 92 | } 93 | 94 | @Override 95 | public void dialogclose() { 96 | if(dialog!=null){ 97 | dialog.dismiss(); 98 | } 99 | } 100 | 选中的地区在列表中的位置 101 | @Override 102 | public void selectorAreaPosition(int provincePosition, int cityPosition, int countyPosition, int streetPosition) { 103 | this.provincePosition = provincePosition; 104 | this.cityPosition = cityPosition; 105 | this.countyPosition = countyPosition; 106 | this.streetPosition = streetPosition; 107 | LogUtil.d("数据", "省份位置=" + provincePosition); 108 | LogUtil.d("数据", "城市位置=" + cityPosition); 109 | LogUtil.d("数据", "乡镇位置=" + countyPosition); 110 | LogUtil.d("数据", "街道位置=" + streetPosition); 111 | } 112 | ### 113 | 有朋友问,怎么使用自己的数据源,这里我说明一下,因为我的数据库里的地址表,省,市,区,县,镇,都是用同一个表,根据parentId来查询的。 114 | 115 | 想用自己的数据源,就需要把自己的数据源里,各个字段与我的数据源里字段一一对应(id, parentId, code, name),分别对应的中文意思(id,父id(可根据父id查询下一级),地址编码,中文名字) 116 | 117 | 然后在你的项目里的assets目录下,放上你的数据库,名字一定是"address.db". 118 | 119 | 如果你用的是android studio 应该放在 120 | ![image](https://github.com/smartTop/AddressSelector/blob/master/screenshots/screenshort2.png) 121 | ### 122 | 在源数据库里要添加一个数据 123 | AdressBean.ChangeRecordsBean changeRecordsBean = new AdressBean.ChangeRecordsBean(); 124 | 125 | changeRecordsBean.parentId = 0; 126 | 127 | changeRecordsBean.name = "测试省"; 128 | 129 | changeRecordsBean.id = 35; 130 | 131 | addressDictManager.inserddress(changeRecordsBean); 132 | ![image](https://github.com/smartTop/AddressSelector/blob/master/screenshots/screenshort3.png) 133 | ### 134 | 还可以进行已下操作 增加一个数据 inserddress(AdressBean.ChangeRecordsBean adress) 增加一个集合insertAddress(List list) 135 | 136 | 更新数据 updateAddressInfo(AdressBean.ChangeRecordsBean adress) 137 | 138 | 查找数据 getAddressList() 139 | 140 | 获取省市列表 getProvinceList() 141 | 142 | 根据省市id 获取城市列表 getCityList(int provinceId) 143 | 144 | 获取城市对应的区,乡镇列表 getCountyList(int cityId) 145 | 146 | 获取区,乡镇对应的街道列表 getStreetList(int countyId) 147 | 148 | 查找消息临时列表中是否存在这一条记录 isExist() 149 | 150 | ### 151 | 最近在我博客上有人问我,能不能加一个功能,就是记住选择后的地址,点击编辑地址的时候,可以直接显示了。 152 | dialog.setDisplaySelectorArea("31",1,"2704",1,"2711",0,"15582",1);//设置已选中的地区(第一个参数 省份的code,第二个参数 省份在列表中的位置,第三个参数 城市的code 第四个参数 城市在列表中的位置,...) 153 | 用法: 154 | /** 155 | * 根据code 来显示选择过的地区 156 | */ 157 | private void getSelectedArea(){ 158 | //根据省份的code,从数据库里查询省份的名字 159 | String province = addressDictManager.getProvince(provinceCode); 160 | //根据城市的code,从数据库里查询城市的名字 161 | String city = addressDictManager.getCity(cityCode); 162 | //根据乡镇的code,从数据库里查询乡镇的名字 163 | String county = addressDictManager.getCounty(countyCode); 164 | //根据街道的code,从数据库里查询街道的名字 165 | String street = addressDictManager.getStreet(streetCode); 166 | 167 | LogUtil.d("数据", "省份=" + province); 168 | LogUtil.d("数据", "城市=" + city); 169 | LogUtil.d("数据", "乡镇=" + county); 170 | LogUtil.d("数据", "街道=" + street); 171 | } 172 | 173 | ## 关于我 174 | 175 | **smartTop** 176 | 177 | - 博客 http://blog.csdn.net/qq_30740239 178 | - gitHub https://github.com/smartTop/AddressSelector 179 | - QQ 1273436145 180 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | *.iml 3 | .idea -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.3" 6 | defaultConfig { 7 | applicationId "com.smarttop.addressselector" 8 | minSdkVersion 15 9 | targetSdkVersion 22 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | testCompile 'junit:junit:4.12' 28 | compile project(':library') 29 | } 30 | -------------------------------------------------------------------------------- /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 C:\Users\001\AppData\Local\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/smarttop/addressselector/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.smarttop.addressselector; 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.smarttop.addressselector", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/smarttop/addressselector/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.smarttop.addressselector.activity; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.LinearLayout; 7 | import android.widget.TextView; 8 | 9 | import com.smarttop.addressselector.R; 10 | import com.smarttop.library.bean.AdressBean; 11 | import com.smarttop.library.bean.City; 12 | import com.smarttop.library.bean.County; 13 | import com.smarttop.library.bean.Province; 14 | import com.smarttop.library.bean.Street; 15 | import com.smarttop.library.db.manager.AddressDictManager; 16 | import com.smarttop.library.utils.LogUtil; 17 | import com.smarttop.library.widget.AddressSelector; 18 | import com.smarttop.library.widget.BottomDialog; 19 | import com.smarttop.library.widget.OnAddressSelectedListener; 20 | 21 | 22 | /** 23 | * Created by smartTop on 2016/12/6. 24 | */ 25 | 26 | public class MainActivity extends Activity implements View.OnClickListener, OnAddressSelectedListener, AddressSelector.OnDialogCloseListener, AddressSelector.onSelectorAreaPositionListener { 27 | private TextView tv_selector_area; 28 | private BottomDialog dialog; 29 | private String provinceCode; 30 | private String cityCode; 31 | private String countyCode; 32 | private String streetCode; 33 | private int provincePosition; 34 | private int cityPosition; 35 | private int countyPosition; 36 | private int streetPosition; 37 | private LinearLayout content; 38 | private AddressDictManager addressDictManager; 39 | 40 | @Override 41 | protected void onCreate(Bundle savedInstanceState) { 42 | super.onCreate(savedInstanceState); 43 | setContentView(R.layout.activity_main); 44 | tv_selector_area = (TextView) findViewById(R.id.tv_selector_area); 45 | content = (LinearLayout) findViewById(R.id.content); 46 | tv_selector_area.setOnClickListener(this); 47 | AddressSelector selector = new AddressSelector(this); 48 | //获取地址管理数据库 49 | addressDictManager = selector.getAddressDictManager(); 50 | 51 | selector.setTextSize(14);//设置字体的大小 52 | // selector.setIndicatorBackgroundColor("#00ff00"); 53 | selector.setIndicatorBackgroundColor(android.R.color.holo_orange_light);//设置指示器的颜色 54 | // selector.setBackgroundColor(android.R.color.holo_red_light);//设置字体的背景 55 | 56 | selector.setTextSelectedColor(android.R.color.holo_orange_light);//设置字体获得焦点的颜色 57 | 58 | selector.setTextUnSelectedColor(android.R.color.holo_blue_light);//设置字体没有获得焦点的颜色 59 | 60 | // //获取数据库管理 61 | AddressDictManager addressDictManager = selector.getAddressDictManager(); 62 | AdressBean.ChangeRecordsBean changeRecordsBean = new AdressBean.ChangeRecordsBean(); 63 | changeRecordsBean.parentId = 0; 64 | changeRecordsBean.name = "测试省"; 65 | changeRecordsBean.id = 35; 66 | addressDictManager.inserddress(changeRecordsBean);//对数据库里增加一个数据 67 | selector.setOnAddressSelectedListener(new OnAddressSelectedListener() { 68 | @Override 69 | public void onAddressSelected(Province province, City city, County county, Street street) { 70 | 71 | } 72 | }); 73 | View view = selector.getView(); 74 | content.addView(view); 75 | } 76 | 77 | 78 | @Override 79 | public void onClick(View view) { 80 | if (dialog != null) { 81 | dialog.show(); 82 | } else { 83 | dialog = new BottomDialog(this); 84 | dialog.setOnAddressSelectedListener(this); 85 | dialog.setDialogDismisListener(this); 86 | dialog.setTextSize(14);//设置字体的大小 87 | dialog.setIndicatorBackgroundColor(android.R.color.holo_orange_light);//设置指示器的颜色 88 | dialog.setTextSelectedColor(android.R.color.holo_orange_light);//设置字体获得焦点的颜色 89 | dialog.setTextUnSelectedColor(android.R.color.holo_blue_light);//设置字体没有获得焦点的颜色 90 | // dialog.setDisplaySelectorArea("31",1,"2704",1,"2711",0,"15582",1);//设置已选中的地区 91 | dialog.setSelectorAreaPositionListener(this); 92 | dialog.show(); 93 | } 94 | } 95 | 96 | @Override 97 | public void onAddressSelected(Province province, City city, County county, Street street) { 98 | provinceCode = (province == null ? "" : province.code); 99 | cityCode = (city == null ? "" : city.code); 100 | countyCode = (county == null ? "" : county.code); 101 | streetCode = (street == null ? "" : street.code); 102 | LogUtil.d("数据", "省份id=" + provinceCode); 103 | LogUtil.d("数据", "城市id=" + cityCode); 104 | LogUtil.d("数据", "乡镇id=" + countyCode); 105 | LogUtil.d("数据", "街道id=" + streetCode); 106 | String s = (province == null ? "" : province.name) + (city == null ? "" : city.name) + (county == null ? "" : county.name) + 107 | (street == null ? "" : street.name); 108 | tv_selector_area.setText(s); 109 | if (dialog != null) { 110 | dialog.dismiss(); 111 | } 112 | // getSelectedArea(); 113 | } 114 | 115 | @Override 116 | public void dialogclose() { 117 | if(dialog!=null){ 118 | dialog.dismiss(); 119 | } 120 | } 121 | 122 | /** 123 | * 根据code 来显示选择过的地区 124 | */ 125 | private void getSelectedArea(){ 126 | String province = addressDictManager.getProvince(provinceCode); 127 | String city = addressDictManager.getCity(cityCode); 128 | String county = addressDictManager.getCounty(countyCode); 129 | String street = addressDictManager.getStreet(streetCode); 130 | tv_selector_area.setText(province+city+county+street); 131 | LogUtil.d("数据", "省份=" + province); 132 | LogUtil.d("数据", "城市=" + city); 133 | LogUtil.d("数据", "乡镇=" + county); 134 | LogUtil.d("数据", "街道=" + street); 135 | } 136 | 137 | @Override 138 | public void selectorAreaPosition(int provincePosition, int cityPosition, int countyPosition, int streetPosition) { 139 | this.provincePosition = provincePosition; 140 | this.cityPosition = cityPosition; 141 | this.countyPosition = countyPosition; 142 | this.streetPosition = streetPosition; 143 | LogUtil.d("数据", "省份位置=" + provincePosition); 144 | LogUtil.d("数据", "城市位置=" + cityPosition); 145 | LogUtil.d("数据", "乡镇位置=" + countyPosition); 146 | LogUtil.d("数据", "街道位置=" + streetPosition); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartTop/AddressSelector/76bc0f153623d0347b16f16afbfea5d7480c6e16/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartTop/AddressSelector/76bc0f153623d0347b16f16afbfea5d7480c6e16/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartTop/AddressSelector/76bc0f153623d0347b16f16afbfea5d7480c6e16/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartTop/AddressSelector/76bc0f153623d0347b16f16afbfea5d7480c6e16/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartTop/AddressSelector/76bc0f153623d0347b16f16afbfea5d7480c6e16/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | AddressSelector 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | -------------------------------------------------------------------------------- /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 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.2.0' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } 24 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartTop/AddressSelector/76bc0f153623d0347b16f16afbfea5d7480c6e16/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Dec 28 10:00:20 PST 2015 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-2.14.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /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 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 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 Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /library/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.3" 6 | 7 | defaultConfig { 8 | minSdkVersion 15 9 | targetSdkVersion 22 10 | versionCode 1 11 | versionName "1.0.6" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | compile 'com.android.support:appcompat-v7:23.0.1' 24 | } 25 | ext { 26 | PUBLISH_GROUP_ID = 'com.smartTop'//开发者名称 27 | PUBLISH_ARTIFACT_ID ='jd-address'//你项目的名字(最好都是小写) 28 | PUBLISH_VERSION = '1.0.3'//(版本号) 29 | } 30 | 31 | apply from: 'https://raw.githubusercontent.com/blundell/release-android-library/master/android-release-aar.gradle' 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /library/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 C:\Users\001\AppData\Local\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 | -------------------------------------------------------------------------------- /library/src/androidTest/java/com/smarttop/library/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.smarttop.library; 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.smarttop.library.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /library/src/main/assets/address.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartTop/AddressSelector/76bc0f153623d0347b16f16afbfea5d7480c6e16/library/src/main/assets/address.db -------------------------------------------------------------------------------- /library/src/main/java/com/smarttop/library/bean/AdressBean.java: -------------------------------------------------------------------------------- 1 | package com.smarttop.library.bean; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * Created by smartTop on 2016/8/25. 8 | * banner基类 9 | */ 10 | public class AdressBean { 11 | 12 | 13 | /** 14 | * changeCount : 3 15 | * changeRecords : [{"createTime":1471603797064,"flag":1,"id":10000,"picSavedPath":"http://jifenshangcheng-test.oss-cn-beijing.aliyuncs.com/mall/image/9610c9b91fbc433499ff8ba5f4054bbb64.png","sort":0,"syncTime":1471603797064,"url":"https://www.baidu.com"},{"createTime":1471603797065,"flag":1,"id":10001,"picSavedPath":"http://jifenshangcheng-test.oss-cn-beijing.aliyuncs.com/mall/image/9610c9b91fbc433499ff8ba5f4054bbb64.png","sort":1,"syncTime":1471603797065,"url":"https://www.baidu.com"},{"createTime":1471603797066,"flag":1,"id":10002,"picSavedPath":"http://jifenshangcheng-test.oss-cn-beijing.aliyuncs.com/mall/image/9610c9b91fbc433499ff8ba5f4054bbb64.png","sort":2,"syncTime":1471603797066,"url":"https://www.baidu.com"}] 16 | * code : 0 17 | * message : 调用成功 18 | */ 19 | 20 | public int changeCount; 21 | public String code; 22 | public String message; 23 | /** 24 | * createTime : 1471603797064 25 | * flag : 1 26 | * id : 10000 27 | * picSavedPath : http://jifenshangcheng-test.oss-cn-beijing.aliyuncs.com/mall/image/9610c9b91fbc433499ff8ba5f4054bbb64.png 28 | * sort : 0 29 | * syncTime : 1471603797064 30 | * url : https://www.baidu.com 31 | */ 32 | 33 | public List changeRecords = new ArrayList<>(); 34 | 35 | public static class ChangeRecordsBean { 36 | /*** id*/ 37 | public int id; 38 | /*** 地址编号*/ 39 | public String code; 40 | /*** 中文名*/ 41 | public String name; 42 | /*** 父id*/ 43 | public int parentId; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /library/src/main/java/com/smarttop/library/bean/City.java: -------------------------------------------------------------------------------- 1 | package com.smarttop.library.bean; 2 | /** 3 | * Created by smartTop on 2016/10/19. 4 | * 城市的实体类 5 | */ 6 | 7 | public class City { 8 | public int id; 9 | public String name; 10 | public String code; 11 | } -------------------------------------------------------------------------------- /library/src/main/java/com/smarttop/library/bean/County.java: -------------------------------------------------------------------------------- 1 | package com.smarttop.library.bean; 2 | /** 3 | * Created by smartTop on 2016/10/19. 4 | * 区 乡镇的实体类 5 | */ 6 | public class County { 7 | public int id; 8 | public String name; 9 | public String code; 10 | } -------------------------------------------------------------------------------- /library/src/main/java/com/smarttop/library/bean/Province.java: -------------------------------------------------------------------------------- 1 | package com.smarttop.library.bean; 2 | 3 | /** 4 | * Created by smartTop on 2016/10/19. 5 | * 省份的实体类 6 | */ 7 | 8 | public class Province { 9 | public int id; 10 | public String name; 11 | public String code; 12 | } 13 | -------------------------------------------------------------------------------- /library/src/main/java/com/smarttop/library/bean/Street.java: -------------------------------------------------------------------------------- 1 | package com.smarttop.library.bean; 2 | /** 3 | * Created by smartTop on 2016/10/19. 4 | * 街道的实体类 5 | */ 6 | public class Street { 7 | public int id; 8 | public String name; 9 | public String code; 10 | } -------------------------------------------------------------------------------- /library/src/main/java/com/smarttop/library/db/AssetsDatabaseManager.java: -------------------------------------------------------------------------------- 1 | package com.smarttop.library.db; 2 | import android.content.Context; 3 | import android.content.SharedPreferences; 4 | import android.content.res.AssetManager; 5 | import android.database.sqlite.SQLiteDatabase; 6 | import android.util.Log; 7 | 8 | import java.io.File; 9 | import java.io.FileOutputStream; 10 | import java.io.InputStream; 11 | import java.io.OutputStream; 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | /** 16 | * This is a Assets Database Manager 17 | * Use it, you can use a assets database file in you application 18 | * It will copy the database file to "/data/data/[your application package name]/database" when you first time you use it 19 | * Then you can get a SQLiteDatabase object by the assets database file 20 | * @author RobinTang 21 | * @time 2012-09-20 22 | * 23 | * 24 | * How to use: 25 | * 1. Initialize AssetsDatabaseManager 26 | * 2. Get AssetsDatabaseManager 27 | * 3. Get a SQLiteDatabase object through database file 28 | * 4. Use this database object 29 | * 30 | * Using example: 31 | * AssetsDatabaseManager.initManager(getApplication()); // this method is only need call one time 32 | * AssetsDatabaseManager mg = AssetsDatabaseManager.getManager(); // get a AssetsDatabaseManager object 33 | * SQLiteDatabase db1 = mg.getDatabase("db1.db"); // get SQLiteDatabase object, db1.db is a file in assets folder 34 | * db1.??? // every operate by you want 35 | * Of cause, you can use AssetsDatabaseManager.getManager().getDatabase("xx") to get a database when you need use a database 36 | */ 37 | public class AssetsDatabaseManager { 38 | private static String tag = "AssetsDatabase"; // for LogCat 39 | private static String databasepath = "/data/data/%s/database"; // %s is packageName 40 | // A mapping from assets database file to SQLiteDatabase object 41 | private Map databases = new HashMap(); 42 | // Context of application 43 | private Context context = null; 44 | // Singleton Pattern 45 | private static AssetsDatabaseManager mInstance = null; 46 | /** 47 | * Initialize AssetsDatabaseManager 48 | * @param context, context of application 49 | */ 50 | public static void initManager(Context context){ 51 | if(mInstance == null){ 52 | mInstance = new AssetsDatabaseManager(context); 53 | } 54 | } 55 | /** 56 | * Get a AssetsDatabaseManager object 57 | * @return, if success return a AssetsDatabaseManager object, else return null 58 | */ 59 | public static AssetsDatabaseManager getManager(){ 60 | return mInstance; 61 | } 62 | private AssetsDatabaseManager(Context context){ 63 | this.context = context; 64 | } 65 | /** 66 | * Get a assets database, if this database is opened this method is only return a copy of the opened database 67 | * @param dbfile, the assets file which will be opened for a database 68 | * @return, if success it return a SQLiteDatabase object else return null 69 | */ 70 | public SQLiteDatabase getDatabase(String dbfile) { 71 | if(databases.get(dbfile) != null){ 72 | Log.i(tag, String.format("Return a database copy of %s", dbfile)); 73 | return (SQLiteDatabase) databases.get(dbfile); 74 | } 75 | if(context==null) 76 | return null; 77 | Log.i(tag, String.format("Create database %s", dbfile)); 78 | String spath = getDatabaseFilepath(); 79 | String sfile = getDatabaseFile(dbfile); 80 | File file = new File(sfile); 81 | SharedPreferences dbs = context.getSharedPreferences(AssetsDatabaseManager.class.toString(), 0); 82 | boolean flag = dbs.getBoolean(dbfile, false); // Get Database file flag, if true means this database file was copied and valid 83 | if(!flag || !file.exists()){ 84 | file = new File(spath); 85 | if(!file.exists() && !file.mkdirs()){ 86 | Log.i(tag, "Create \""+spath+"\" fail!"); 87 | return null; 88 | } 89 | if(!copyAssetsToFilesystem(dbfile, sfile)){ 90 | Log.i(tag, String.format("Copy %s to %s fail!", dbfile, sfile)); 91 | return null; 92 | } 93 | dbs.edit().putBoolean(dbfile, true).commit(); 94 | } 95 | SQLiteDatabase db = SQLiteDatabase.openDatabase(sfile, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS); 96 | if(db != null){ 97 | databases.put(dbfile, db); 98 | } 99 | return db; 100 | } 101 | private String getDatabaseFilepath(){ 102 | return String.format(databasepath, context.getApplicationInfo().packageName); 103 | } 104 | private String getDatabaseFile(String dbfile){ 105 | return getDatabaseFilepath()+"/"+dbfile; 106 | } 107 | private boolean copyAssetsToFilesystem(String assetsSrc, String des){ 108 | Log.i(tag, "Copy "+assetsSrc+" to "+des); 109 | InputStream istream = null; 110 | OutputStream ostream = null; 111 | try{ 112 | AssetManager am = context.getAssets(); 113 | istream = am.open(assetsSrc); 114 | ostream = new FileOutputStream(des); 115 | byte[] buffer = new byte[1024]; 116 | int length; 117 | while ((length = istream.read(buffer))>0){ 118 | ostream.write(buffer, 0, length); 119 | } 120 | istream.close(); 121 | ostream.close(); 122 | } 123 | catch(Exception e){ 124 | e.printStackTrace(); 125 | try{ 126 | if(istream!=null) 127 | istream.close(); 128 | if(ostream!=null) 129 | ostream.close(); 130 | } 131 | catch(Exception ee){ 132 | ee.printStackTrace(); 133 | } 134 | return false; 135 | } 136 | return true; 137 | } 138 | /** 139 | * Close assets database 140 | * @param dbfile, the assets file which will be closed soon 141 | * @return, the status of this operating 142 | */ 143 | public boolean closeDatabase(String dbfile){ 144 | if(databases.get(dbfile) != null){ 145 | SQLiteDatabase db = (SQLiteDatabase) databases.get(dbfile); 146 | db.close(); 147 | databases.remove(dbfile); 148 | return true; 149 | } 150 | return false; 151 | } 152 | /** 153 | * Close all assets database 154 | */ 155 | static public void closeAllDatabase(){ 156 | Log.i(tag, "closeAllDatabase"); 157 | if(mInstance != null){ 158 | for(int i=0; i list){ 67 | if(list !=null){ 68 | db.beginTransaction();//手动设置开启事务 69 | try{ 70 | for (AdressBean.ChangeRecordsBean adress:list) { 71 | ContentValues values = new ContentValues(); 72 | values.put(ADDRESS_DICT_FIELD_CODE,adress.code); 73 | values.put(TableField.ADDRESS_DICT_FIELD_NAME,adress.name); 74 | values.put(ADDRESS_DICT_FIELD_PARENTID,adress.parentId); 75 | values.put(TableField.ADDRESS_DICT_FIELD_ID,adress.id); 76 | db.insert(TableField.TABLE_ADDRESS_DICT,null,values); 77 | } 78 | db.setTransactionSuccessful(); //设置事务处理成功 79 | }catch (Exception e){ 80 | }finally { 81 | db.endTransaction(); //事务终止 82 | } 83 | } 84 | } 85 | //更新地址 86 | public void updateAddressInfo(AdressBean.ChangeRecordsBean adress){ 87 | if(adress !=null){ 88 | db.beginTransaction();//手动设置开启事务 89 | try{ 90 | ContentValues values = new ContentValues(); 91 | values.put(ADDRESS_DICT_FIELD_CODE,adress.code); 92 | values.put(TableField.ADDRESS_DICT_FIELD_NAME,adress.name); 93 | values.put(ADDRESS_DICT_FIELD_PARENTID,adress.parentId); 94 | values.put(TableField.ADDRESS_DICT_FIELD_ID,adress.id); 95 | String[] args = {String.valueOf(adress.id)}; 96 | db.update(TableField.TABLE_ADDRESS_DICT,values,TableField.FIELD_ID+ "=?",args); 97 | db.setTransactionSuccessful(); //设置事务处理成功 98 | }catch (Exception e){ 99 | }finally { 100 | db.endTransaction(); //事务终止 101 | } 102 | } 103 | } 104 | 105 | /** 106 | * 查找 地址 数据 107 | * @return 108 | */ 109 | public List getAddressList(){ 110 | List list = new ArrayList<>(); 111 | Cursor cursor = db.rawQuery("select * from "+ TableField.TABLE_ADDRESS_DICT+" order by sort asc", null); 112 | while (cursor.moveToNext()){ 113 | AdressBean.ChangeRecordsBean adressInfo = new AdressBean.ChangeRecordsBean(); 114 | adressInfo.id = cursor.getInt(cursor.getColumnIndex(TableField.FIELD_ID)); 115 | adressInfo.parentId = cursor.getInt(cursor.getColumnIndex(ADDRESS_DICT_FIELD_PARENTID)); 116 | adressInfo.code = cursor.getString(cursor.getColumnIndex(ADDRESS_DICT_FIELD_CODE)); 117 | adressInfo.name = cursor.getString(cursor.getColumnIndex(TableField.ADDRESS_DICT_FIELD_NAME)); 118 | list.add(adressInfo); 119 | } 120 | cursor.close(); 121 | return list; 122 | } 123 | 124 | /** 125 | * 获取省份列表 126 | * @return 127 | */ 128 | public List getProvinceList(){ 129 | List provinceList = new ArrayList<>(); 130 | Cursor cursor = db.rawQuery("select * from " + TableField.TABLE_ADDRESS_DICT+" where "+ ADDRESS_DICT_FIELD_PARENTID+"=?", new String[]{String.valueOf(0)}); 131 | while (cursor.moveToNext()){ 132 | Province province = new Province(); 133 | province.id = cursor.getInt(cursor.getColumnIndex(ADDRESS_DICT_FIELD_ID)); 134 | province.code = cursor.getString(cursor.getColumnIndex(ADDRESS_DICT_FIELD_CODE)); 135 | province.name = cursor.getString(cursor.getColumnIndex(TableField.ADDRESS_DICT_FIELD_NAME)); 136 | provinceList.add(province); 137 | } 138 | cursor.close(); 139 | 140 | return provinceList; 141 | } 142 | 143 | /** 144 | * 获取省份 145 | * @return 146 | * @param provinceCode 147 | */ 148 | public String getProvince(String provinceCode){ 149 | Cursor cursor = db.rawQuery("select * from " + TableField.TABLE_ADDRESS_DICT+" where "+ ADDRESS_DICT_FIELD_CODE+"=?", new String[]{provinceCode}); 150 | if(cursor!=null && cursor.moveToFirst()){ 151 | Province province = new Province(); 152 | province.id = cursor.getInt(cursor.getColumnIndex(ADDRESS_DICT_FIELD_ID)); 153 | province.code = cursor.getString(cursor.getColumnIndex(ADDRESS_DICT_FIELD_CODE)); 154 | province.name = cursor.getString(cursor.getColumnIndex(TableField.ADDRESS_DICT_FIELD_NAME)); 155 | cursor.close(); 156 | return province.name; 157 | }else{ 158 | return ""; 159 | } 160 | } 161 | /** 162 | * 获取省份 163 | * @return 164 | * @param provinceCode 165 | */ 166 | public Province getProvinceBean(String provinceCode){ 167 | Cursor cursor = db.rawQuery("select * from " + TableField.TABLE_ADDRESS_DICT+" where "+ ADDRESS_DICT_FIELD_CODE+"=?", new String[]{provinceCode}); 168 | if(cursor!=null && cursor.moveToFirst()){ 169 | Province province = new Province(); 170 | province.id = cursor.getInt(cursor.getColumnIndex(ADDRESS_DICT_FIELD_ID)); 171 | province.code = cursor.getString(cursor.getColumnIndex(ADDRESS_DICT_FIELD_CODE)); 172 | province.name = cursor.getString(cursor.getColumnIndex(TableField.ADDRESS_DICT_FIELD_NAME)); 173 | cursor.close(); 174 | return province; 175 | }else{ 176 | return null; 177 | } 178 | } 179 | /** 180 | * 获取省份对应的城市列表 181 | * @return 182 | */ 183 | public List getCityList(int provinceId){ 184 | List cityList = new ArrayList<>(); 185 | Cursor cursor = db.rawQuery("select * from " + TableField.TABLE_ADDRESS_DICT+" where "+ ADDRESS_DICT_FIELD_PARENTID+"=?", new String[]{String.valueOf(provinceId)}); 186 | while (cursor.moveToNext()){ 187 | City city = new City(); 188 | city.id = cursor.getInt(cursor.getColumnIndex(ADDRESS_DICT_FIELD_ID)); 189 | city.code = cursor.getString(cursor.getColumnIndex(ADDRESS_DICT_FIELD_CODE)); 190 | city.name = cursor.getString(cursor.getColumnIndex(TableField.ADDRESS_DICT_FIELD_NAME)); 191 | cityList.add(city); 192 | } 193 | cursor.close(); 194 | return cityList; 195 | } 196 | 197 | /** 198 | * 获取城市 199 | * @return 200 | */ 201 | public String getCity(String cityCode){ 202 | Cursor cursor = db.rawQuery("select * from " + TableField.TABLE_ADDRESS_DICT+" where "+ ADDRESS_DICT_FIELD_CODE+"=?", new String[]{cityCode}); 203 | if(cursor!=null && cursor.moveToFirst()){ 204 | City city = new City(); 205 | city.id = cursor.getInt(cursor.getColumnIndex(ADDRESS_DICT_FIELD_ID)); 206 | city.code = cursor.getString(cursor.getColumnIndex(ADDRESS_DICT_FIELD_CODE)); 207 | city.name = cursor.getString(cursor.getColumnIndex(TableField.ADDRESS_DICT_FIELD_NAME)); 208 | cursor.close(); 209 | return city.name; 210 | }else{ 211 | return ""; 212 | } 213 | } 214 | /** 215 | * 获取城市 216 | * @return 217 | */ 218 | public City getCityBean(String cityCode){ 219 | Cursor cursor = db.rawQuery("select * from " + TableField.TABLE_ADDRESS_DICT+" where "+ ADDRESS_DICT_FIELD_CODE+"=?", new String[]{cityCode}); 220 | if(cursor!=null && cursor.moveToFirst()){ 221 | City city = new City(); 222 | city.id = cursor.getInt(cursor.getColumnIndex(ADDRESS_DICT_FIELD_ID)); 223 | city.code = cursor.getString(cursor.getColumnIndex(ADDRESS_DICT_FIELD_CODE)); 224 | city.name = cursor.getString(cursor.getColumnIndex(TableField.ADDRESS_DICT_FIELD_NAME)); 225 | cursor.close(); 226 | return city; 227 | }else{ 228 | return null; 229 | } 230 | } 231 | 232 | /** 233 | * 获取城市对应的区,乡镇列表 234 | * @return 235 | */ 236 | public List getCountyList(int cityId){ 237 | List countyList = new ArrayList<>(); 238 | Cursor cursor = db.rawQuery("select * from " + TableField.TABLE_ADDRESS_DICT+" where "+ ADDRESS_DICT_FIELD_PARENTID+"=?", new String[]{String.valueOf(cityId)}); 239 | while (cursor.moveToNext()){ 240 | County county = new County(); 241 | county.id = cursor.getInt(cursor.getColumnIndex(ADDRESS_DICT_FIELD_ID)); 242 | county.code = cursor.getString(cursor.getColumnIndex(ADDRESS_DICT_FIELD_CODE)); 243 | county.name = cursor.getString(cursor.getColumnIndex(TableField.ADDRESS_DICT_FIELD_NAME)); 244 | countyList.add(county); 245 | } 246 | cursor.close(); 247 | return countyList; 248 | } 249 | public String getCounty(String countyCode){ 250 | Cursor cursor = db.rawQuery("select * from " + TableField.TABLE_ADDRESS_DICT+" where "+ ADDRESS_DICT_FIELD_CODE+"=?", new String[]{countyCode}); 251 | if(cursor!=null && cursor.moveToFirst()){ 252 | County county = new County(); 253 | county.id = cursor.getInt(cursor.getColumnIndex(ADDRESS_DICT_FIELD_ID)); 254 | county.code = cursor.getString(cursor.getColumnIndex(ADDRESS_DICT_FIELD_CODE)); 255 | county.name = cursor.getString(cursor.getColumnIndex(TableField.ADDRESS_DICT_FIELD_NAME)); 256 | cursor.close(); 257 | return county.name; 258 | }else{ 259 | return ""; 260 | } 261 | } 262 | public County getCountyBean(String countyCode){ 263 | Cursor cursor = db.rawQuery("select * from " + TableField.TABLE_ADDRESS_DICT+" where "+ ADDRESS_DICT_FIELD_CODE+"=?", new String[]{countyCode}); 264 | if(cursor!=null && cursor.moveToFirst()){ 265 | County county = new County(); 266 | county.id = cursor.getInt(cursor.getColumnIndex(ADDRESS_DICT_FIELD_ID)); 267 | county.code = cursor.getString(cursor.getColumnIndex(ADDRESS_DICT_FIELD_CODE)); 268 | county.name = cursor.getString(cursor.getColumnIndex(TableField.ADDRESS_DICT_FIELD_NAME)); 269 | cursor.close(); 270 | return county; 271 | }else{ 272 | return null; 273 | } 274 | } 275 | /** 276 | * 获取区,乡镇对应的街道列表 277 | * @return 278 | */ 279 | public List getStreetList(int countyId){ 280 | List streetList = new ArrayList<>(); 281 | Cursor cursor = db.rawQuery("select * from " + TableField.TABLE_ADDRESS_DICT+" where "+ ADDRESS_DICT_FIELD_PARENTID+"=?", new String[]{String.valueOf(countyId)}); 282 | while (cursor.moveToNext()){ 283 | Street street = new Street(); 284 | street.id = cursor.getInt(cursor.getColumnIndex(ADDRESS_DICT_FIELD_ID)); 285 | street.code = cursor.getString(cursor.getColumnIndex(ADDRESS_DICT_FIELD_CODE)); 286 | street.name = cursor.getString(cursor.getColumnIndex(TableField.ADDRESS_DICT_FIELD_NAME)); 287 | streetList.add(street); 288 | } 289 | cursor.close(); 290 | return streetList; 291 | } 292 | 293 | public String getStreet(String streetCode){ 294 | Cursor cursor = db.rawQuery("select * from " + TableField.TABLE_ADDRESS_DICT+" where "+ ADDRESS_DICT_FIELD_CODE+"=?", new String[]{streetCode}); 295 | if(cursor!=null && cursor.moveToFirst()){ 296 | Street street = new Street(); 297 | street.id = cursor.getInt(cursor.getColumnIndex(ADDRESS_DICT_FIELD_ID)); 298 | street.code = cursor.getString(cursor.getColumnIndex(ADDRESS_DICT_FIELD_CODE)); 299 | street.name = cursor.getString(cursor.getColumnIndex(TableField.ADDRESS_DICT_FIELD_NAME)); 300 | cursor.close(); 301 | return street.name; 302 | }else{ 303 | return ""; 304 | } 305 | } 306 | public Street getStreetBean(String streetCode){ 307 | Cursor cursor = db.rawQuery("select * from " + TableField.TABLE_ADDRESS_DICT+" where "+ ADDRESS_DICT_FIELD_CODE+"=?", new String[]{streetCode}); 308 | if(cursor!=null && cursor.moveToFirst()){ 309 | Street street = new Street(); 310 | street.id = cursor.getInt(cursor.getColumnIndex(ADDRESS_DICT_FIELD_ID)); 311 | street.code = cursor.getString(cursor.getColumnIndex(ADDRESS_DICT_FIELD_CODE)); 312 | street.name = cursor.getString(cursor.getColumnIndex(TableField.ADDRESS_DICT_FIELD_NAME)); 313 | cursor.close(); 314 | return street; 315 | }else{ 316 | return null; 317 | } 318 | } 319 | /** 320 | * 查找消息临时列表中是否存在这一条记录 321 | * @param bannerInfo banner数据 322 | * @return 323 | */ 324 | public int isExist(AdressBean.ChangeRecordsBean bannerInfo){ 325 | int count = 0; 326 | Cursor cursor = db.rawQuery("select count(*) from " + TableField.TABLE_ADDRESS_DICT+" where "+TableField.FIELD_ID+"=?", new String[]{String.valueOf(bannerInfo.id)}); 327 | if (cursor.moveToFirst()) { 328 | count = cursor.getInt(0); 329 | } 330 | cursor.close(); 331 | return count; 332 | } 333 | 334 | } 335 | -------------------------------------------------------------------------------- /library/src/main/java/com/smarttop/library/utils/Dev.java: -------------------------------------------------------------------------------- 1 | package com.smarttop.library.utils; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * Created by smartTop on 2016/10/19. 7 | */ 8 | 9 | public class Dev { 10 | public Dev() { 11 | } 12 | 13 | public static int dp2px(Context context, float dp) { 14 | return (int) Math.ceil((double)(context.getResources().getDisplayMetrics().density * dp)); 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /library/src/main/java/com/smarttop/library/utils/GlobalParams.java: -------------------------------------------------------------------------------- 1 | package com.smarttop.library.utils; 2 | 3 | public class GlobalParams { 4 | /** 是否开启调试模式(调试的模式,吐司提示错误信息、log打开) */ 5 | public static boolean isDebug =true ; 6 | 7 | } 8 | -------------------------------------------------------------------------------- /library/src/main/java/com/smarttop/library/utils/Lists.java: -------------------------------------------------------------------------------- 1 | package com.smarttop.library.utils; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Created by smartTop on 2016/10/19. 7 | * list的工具类 8 | */ 9 | 10 | public class Lists { 11 | public Lists() { 12 | } 13 | 14 | public static boolean isEmpty(List list) { 15 | return list == null || list.size() == 0; 16 | } 17 | 18 | public static boolean notEmpty(List list) { 19 | return list != null && list.size() > 0; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /library/src/main/java/com/smarttop/library/utils/LogUtil.java: -------------------------------------------------------------------------------- 1 | package com.smarttop.library.utils; 2 | 3 | import android.content.Context; 4 | import android.os.Environment; 5 | import android.util.Log; 6 | 7 | import java.io.BufferedReader; 8 | import java.io.File; 9 | import java.io.FileInputStream; 10 | import java.io.FileNotFoundException; 11 | import java.io.FileOutputStream; 12 | import java.io.IOException; 13 | import java.io.InputStreamReader; 14 | import java.io.OutputStream; 15 | import java.util.ArrayList; 16 | import java.util.Calendar; 17 | import java.util.zip.ZipEntry; 18 | import java.util.zip.ZipOutputStream; 19 | 20 | /** 21 | * 日志工具 1.添加日志输出选项.控制日志输出位置 2.添加文件日志功能. 22 | * 3.控制单个日志文件最大限制.由LOG_MAXSIZE常量控制,保留两个最新日志文件 4.文件日志输出目标 23 | * 24 | * @author smartTop 25 | * @data 2010-5-26 26 | */ 27 | public class LogUtil { 28 | 29 | public static final int TO_CONSOLE = 0x1; 30 | public static final int TO_SCREEN = 0x10; 31 | public static final int TO_FILE = 0x100; 32 | public static final int FROM_LOGCAT = 0x1000; 33 | 34 | public static final int DEBUG_ALL = TO_CONSOLE | TO_FILE; /* 35 | * | FROM_LOGCAT | 36 | * TO_SCREEN | 37 | * TO_FILE | 38 | * FROM_LOGCAT 39 | */ 40 | 41 | private static final String LOG_TEMP_FILE = "log.temp"; 42 | private static final String LOG_LAST_FILE = "log_last.txt"; 43 | private static final String LOG_NOW_FILE = "log_now.txt"; 44 | 45 | private static final int LOG_MAXSIZE = 2 * 1024 * 1024; // double the size 46 | // temporarily 47 | 48 | public final static boolean isDebug = GlobalParams.isDebug; 49 | 50 | int LOG_LEVEL = Log.VERBOSE; 51 | 52 | private final Object lockObj = new Object(); 53 | 54 | PaintLogThread mPaintLogThread = null; 55 | 56 | OutputStream mLogStream; 57 | 58 | long mFileSize; 59 | 60 | Context mContext; 61 | 62 | private final static LogUtil mLog = new LogUtil(); 63 | private static final String DEFAULT_FILE_DIR = "com.yz.faith"; 64 | 65 | private LogUtil() { 66 | } 67 | 68 | public static LogUtil getInstance() { 69 | return mLog; 70 | } 71 | 72 | /** 73 | * 设置context 74 | * 75 | * @param context 76 | */ 77 | public void setContext(Context context) { 78 | mContext = context; 79 | } 80 | 81 | public static void d(String tag, String msg) { 82 | getInstance().log(tag, msg, DEBUG_ALL, Log.DEBUG); 83 | } 84 | 85 | public static void v(String tag, String msg) { 86 | getInstance().log(tag, msg, DEBUG_ALL, Log.VERBOSE); 87 | } 88 | 89 | public static void e(String tag, String msg) { 90 | getInstance().log(tag, msg, DEBUG_ALL, Log.ERROR); 91 | } 92 | 93 | public static void i(String tag, String msg) { 94 | getInstance().log(tag, msg, DEBUG_ALL, Log.INFO); 95 | } 96 | 97 | public static void w(String tag, String msg) { 98 | getInstance().log(tag, msg, DEBUG_ALL, Log.WARN); 99 | } 100 | 101 | protected void log(String tag, String msg, int outdest, int level) { 102 | if (!isDebug) { 103 | return; 104 | } 105 | 106 | if (tag == null) 107 | tag = "TAG_NULL"; 108 | if (msg == null) 109 | msg = "MSG_NULL"; 110 | 111 | if (level >= LOG_LEVEL) { 112 | 113 | if ((outdest & TO_CONSOLE) != 0) { 114 | LogToConsole(tag, msg, level); 115 | } 116 | 117 | if ((outdest & TO_SCREEN) != 0) { 118 | LogToScreen(tag, msg, level); 119 | } 120 | 121 | if ((outdest & TO_FILE) != 0) { 122 | LogToFile(tag, msg, level); 123 | } 124 | 125 | if ((outdest & FROM_LOGCAT) != 0) { 126 | 127 | if (mPaintLogThread == null) { 128 | mPaintLogThread = new PaintLogThread(); 129 | mPaintLogThread.start(); 130 | } 131 | } 132 | } 133 | 134 | } 135 | 136 | Calendar mDate = Calendar.getInstance(); 137 | StringBuffer mBuffer = new StringBuffer(); 138 | 139 | /** 140 | * 组成Log字符串.添加时间信息. 141 | * 142 | * @param tag 143 | * @param msg 144 | * @return 145 | */ 146 | private String getLogStr(String tag, String msg) { 147 | 148 | mDate.setTimeInMillis(System.currentTimeMillis()); 149 | 150 | mBuffer.setLength(0); 151 | mBuffer.append("["); 152 | mBuffer.append(tag); 153 | mBuffer.append(" : "); 154 | mBuffer.append(mDate.get(Calendar.MONTH) + 1); 155 | mBuffer.append("-"); 156 | mBuffer.append(mDate.get(Calendar.DATE)); 157 | mBuffer.append(" "); 158 | mBuffer.append(mDate.get(Calendar.HOUR_OF_DAY)); 159 | mBuffer.append(":"); 160 | mBuffer.append(mDate.get(Calendar.MINUTE)); 161 | mBuffer.append(":"); 162 | mBuffer.append(mDate.get(Calendar.SECOND)); 163 | mBuffer.append(":"); 164 | mBuffer.append(mDate.get(Calendar.MILLISECOND)); 165 | mBuffer.append("] "); 166 | mBuffer.append(msg); 167 | 168 | return mBuffer.toString(); 169 | } 170 | 171 | /** 172 | * 将log打到控制台 173 | * 174 | * @param tag 175 | * @param msg 176 | * @param level 177 | */ 178 | private void LogToConsole(String tag, String msg, int level) { 179 | switch (level) { 180 | case Log.DEBUG: 181 | Log.d(tag, msg); 182 | break; 183 | case Log.ERROR: 184 | Log.e(tag, msg); 185 | break; 186 | case Log.INFO: 187 | Log.i(tag, msg); 188 | break; 189 | case Log.VERBOSE: 190 | Log.v(tag, msg); 191 | break; 192 | case Log.WARN: 193 | Log.w(tag, msg); 194 | break; 195 | default: 196 | break; 197 | } 198 | } 199 | 200 | /** 201 | * 将log打到文件日志 202 | * 203 | * @param tag 204 | * @param msg 205 | * @param level 206 | */ 207 | private void LogToFile(String tag, String msg, int level) { 208 | synchronized (lockObj) { 209 | OutputStream outStream = openLogFileOutStream(); 210 | if (outStream != null) { 211 | try { 212 | byte[] d = getLogStr(tag, msg).getBytes("utf-8"); 213 | // byte[] d = msg.getBytes("utf-8"); 214 | if (mFileSize < LOG_MAXSIZE) { 215 | outStream.write(d); 216 | outStream.write("\r\n".getBytes()); 217 | outStream.flush(); 218 | mFileSize += d.length; 219 | } else { 220 | closeLogFileOutStream(); 221 | if (renameLogFile()) { 222 | LogToFile(tag, msg, level); 223 | } 224 | } 225 | } catch (Exception e) { 226 | // TODO: handle exception 227 | e.printStackTrace(); 228 | } 229 | 230 | } 231 | } 232 | } 233 | 234 | private void LogToScreen(String tag, String msg, int level) { 235 | 236 | } 237 | 238 | /** 239 | * back now log file 240 | */ 241 | public void backLogFile() { 242 | if (mContext == null) { 243 | return; 244 | } 245 | File cacheFolder = getLogFolder(); 246 | synchronized (lockObj) { 247 | try { 248 | closeLogFileOutStream(); 249 | 250 | File destFile = new File(cacheFolder, LOG_NOW_FILE); 251 | if (destFile.exists()) { 252 | destFile.delete(); 253 | } 254 | 255 | try { 256 | destFile.createNewFile(); 257 | } catch (IOException e1) { 258 | e1.printStackTrace(); 259 | return; 260 | } 261 | 262 | File srcfile1 = new File(cacheFolder, LOG_TEMP_FILE); 263 | File srcfile2 = new File(cacheFolder, LOG_LAST_FILE); 264 | copyFile(srcfile1, destFile, false); 265 | copyFile(srcfile2, destFile, true); 266 | 267 | openLogFileOutStream(); 268 | 269 | } catch (IOException e) { 270 | // TODO: handle exception 271 | e.printStackTrace(); 272 | } 273 | } 274 | } 275 | 276 | /** 277 | * 获取日志临时文件输入流 278 | * 279 | * @return 280 | */ 281 | private OutputStream openLogFileOutStream() { 282 | if (mLogStream == null && mContext != null) { 283 | try { 284 | 285 | File file = new File(getLogFolder(), LOG_TEMP_FILE); 286 | if (file.exists()) { 287 | mLogStream = new FileOutputStream(file, true); 288 | mFileSize = file.length(); 289 | } else { 290 | // file.createNewFile(); 291 | mLogStream = new FileOutputStream(file); 292 | mFileSize = 0; 293 | } 294 | } catch (FileNotFoundException e) { 295 | e.printStackTrace(); 296 | } 297 | } 298 | return mLogStream; 299 | } 300 | 301 | /** 302 | * 获得日志目录 303 | * 304 | * @return 305 | * @author houmiao.xiong 306 | */ 307 | protected File getLogFolder() { 308 | 309 | File folder; 310 | 311 | if (Environment.getExternalStorageState().equals( 312 | Environment.MEDIA_MOUNTED)) { 313 | File sdcard = Environment.getExternalStorageDirectory(); 314 | folder = new File(sdcard, DEFAULT_FILE_DIR); 315 | if (!folder.exists()) { 316 | folder.mkdirs(); 317 | } 318 | } else { 319 | folder = mContext.getFilesDir(); 320 | if (!folder.exists()) { 321 | folder.mkdirs(); 322 | } 323 | } 324 | 325 | return folder; 326 | } 327 | 328 | /** 329 | * 关闭日志输出流 330 | */ 331 | private void closeLogFileOutStream() { 332 | try { 333 | if (mLogStream != null) { 334 | mLogStream.close(); 335 | mLogStream = null; 336 | mFileSize = 0; 337 | } 338 | } catch (Exception e) { 339 | // TODO: handle exception 340 | e.printStackTrace(); 341 | } 342 | } 343 | 344 | /** 345 | * 文件复制 346 | * 347 | * @param src 348 | * @param dest 349 | * @throws IOException 350 | */ 351 | private void copyFile(File src, File dest, boolean destAppend) 352 | throws IOException { 353 | 354 | if (!destAppend && dest.exists()) { 355 | dest.delete(); 356 | } 357 | long total = src.length(); 358 | FileOutputStream out = new FileOutputStream(dest, destAppend); 359 | FileInputStream in = new FileInputStream(src); 360 | long count = 0; 361 | byte[] temp = new byte[1024 * 10]; 362 | while (count < total) { 363 | int size = in.read(temp); 364 | out.write(temp, 0, size); 365 | count += size; 366 | } 367 | in.close(); 368 | out.close(); 369 | 370 | } 371 | 372 | /** 373 | * rename log file 374 | * 375 | * @return 重命名成功或失败 376 | */ 377 | private boolean renameLogFile() { 378 | 379 | synchronized (lockObj) { 380 | 381 | File file = new File(getLogFolder(), LOG_TEMP_FILE); 382 | File destFile = new File(getLogFolder(), LOG_LAST_FILE); 383 | if (destFile.exists()) { 384 | destFile.delete(); 385 | } 386 | file.renameTo(destFile); 387 | // 重命名失败. 原文件还存在 388 | // 清除原文件 389 | return !file.exists() || file.delete(); 390 | } 391 | } 392 | 393 | public boolean zipLogFile(String zipFileName) { 394 | if (mContext == null) { 395 | return false; 396 | } 397 | 398 | backLogFile(); 399 | File zipfile = new File(zipFileName); 400 | if (zipfile.exists()) { 401 | zipfile.delete(); 402 | } 403 | File srcfile = new File(getLogFolder(), LOG_NOW_FILE); 404 | 405 | return zip(srcfile, zipfile); 406 | } 407 | 408 | public void close() { 409 | 410 | if (mPaintLogThread != null) { 411 | mPaintLogThread.shutdown(); 412 | mPaintLogThread = null; 413 | } 414 | closeLogFileOutStream(); 415 | 416 | } 417 | 418 | class PaintLogThread extends Thread { 419 | 420 | Process mProcess; 421 | boolean mStop = false; 422 | 423 | public void shutdown() { 424 | Log.i("PaintLogThread", "shutdown"); 425 | mStop = true; 426 | if (mProcess != null) { 427 | mProcess.destroy(); 428 | mProcess = null; 429 | } 430 | } 431 | 432 | public void run() { 433 | // TODO Auto-generated method stub 434 | try { 435 | Log.i("PaintLogThread", "shutdown"); 436 | ArrayList commandLine = new ArrayList(); 437 | commandLine.add("logcat"); 438 | // commandLine.add( "-d"); 439 | 440 | commandLine.add("-v"); 441 | commandLine.add("time"); 442 | 443 | // commandLine.add( "-s"); 444 | // commandLine.add( "tag:W"); 445 | // commandLine.add( "-f"); 446 | // commandLine.add("/sdcard/log.txt"); 447 | 448 | mProcess = Runtime.getRuntime().exec( 449 | commandLine.toArray(new String[commandLine.size()])); 450 | 451 | BufferedReader bufferedReader = new BufferedReader 452 | // ( new InputStreamReader(mProcess.getInputStream()), 1024); 453 | (new InputStreamReader(mProcess.getInputStream())); 454 | 455 | String line; 456 | while (!mStop) { 457 | line = bufferedReader.readLine(); 458 | if (line != null) { 459 | LogToFile("SysLog", line, Log.VERBOSE); 460 | } else { 461 | if (line == null) { 462 | Log.i("PaintLogThread:", "readLine==null"); 463 | break; 464 | // Log.i("PaintLogThread:","PaintLogThread sleep 465 | // 1000second" 466 | // ); 467 | // Thread.sleep(1000); 468 | } 469 | // Thread.sleep(1000); 470 | 471 | } 472 | } 473 | 474 | bufferedReader.close(); 475 | if (mProcess != null) 476 | mProcess.destroy(); 477 | mProcess = null; 478 | mPaintLogThread = null; 479 | Log.i("PaintLogThread:", "end PaintLogThread:"); 480 | 481 | } catch (Exception e) { 482 | e.printStackTrace(); 483 | Log.d("NeteaseLog", "logcatToFile Exception:" + e.toString()); 484 | } 485 | } 486 | } 487 | 488 | private boolean zip(File unZip, File zip) { 489 | if (!unZip.exists()) 490 | return false; 491 | if (!zip.getParentFile().exists()) 492 | zip.getParentFile().mkdir(); 493 | 494 | try { 495 | FileInputStream in = new FileInputStream(unZip); 496 | FileOutputStream out = new FileOutputStream(zip); 497 | 498 | ZipOutputStream zipOut = new ZipOutputStream(out); 499 | 500 | // for buffer 501 | byte[] buf = new byte[1024]; 502 | 503 | int readCnt; 504 | 505 | zipOut.putNextEntry(new ZipEntry(unZip.getName())); 506 | while ((readCnt = in.read(buf)) > 0) { 507 | zipOut.write(buf, 0, readCnt); 508 | } 509 | zipOut.closeEntry(); 510 | 511 | in.close(); 512 | zipOut.close(); 513 | 514 | } catch (Exception e) { 515 | e.printStackTrace(); 516 | return false; 517 | } 518 | 519 | return true; 520 | } 521 | 522 | } 523 | -------------------------------------------------------------------------------- /library/src/main/java/com/smarttop/library/widget/AddressSelector.java: -------------------------------------------------------------------------------- 1 | package com.smarttop.library.widget; 2 | 3 | import android.animation.AnimatorSet; 4 | import android.animation.ObjectAnimator; 5 | import android.animation.ValueAnimator; 6 | import android.content.Context; 7 | import android.graphics.Color; 8 | import android.os.Handler; 9 | import android.os.Message; 10 | import android.support.v4.view.animation.FastOutSlowInInterpolator; 11 | import android.text.TextUtils; 12 | import android.view.LayoutInflater; 13 | import android.view.View; 14 | import android.view.ViewGroup; 15 | import android.widget.AdapterView; 16 | import android.widget.BaseAdapter; 17 | import android.widget.ImageView; 18 | import android.widget.LinearLayout; 19 | import android.widget.ListAdapter; 20 | import android.widget.ListView; 21 | import android.widget.ProgressBar; 22 | import android.widget.TextView; 23 | 24 | import com.smarttop.library.R; 25 | import com.smarttop.library.bean.City; 26 | import com.smarttop.library.bean.County; 27 | import com.smarttop.library.bean.Province; 28 | import com.smarttop.library.bean.Street; 29 | import com.smarttop.library.db.manager.AddressDictManager; 30 | import com.smarttop.library.utils.Lists; 31 | import com.smarttop.library.utils.LogUtil; 32 | 33 | import java.util.List; 34 | 35 | 36 | /** 37 | * Created by smartTop on 2016/10/19. 38 | */ 39 | 40 | public class AddressSelector implements AdapterView.OnItemClickListener { 41 | private static final int INDEX_TAB_PROVINCE = 0;//省份标志 42 | private static final int INDEX_TAB_CITY = 1;//城市标志 43 | private static final int INDEX_TAB_COUNTY = 2;//乡镇标志 44 | private static final int INDEX_TAB_STREET = 3;//街道标志 45 | private int tabIndex = INDEX_TAB_PROVINCE; //默认是省份 46 | 47 | private static final int INDEX_INVALID = -1; 48 | private int provinceIndex = INDEX_INVALID; //省份的下标 49 | private int cityIndex = INDEX_INVALID;//城市的下标 50 | private int countyIndex = INDEX_INVALID;//乡镇的下标 51 | private int streetIndex = INDEX_INVALID;//街道的下标 52 | 53 | private Context context; 54 | private final LayoutInflater inflater; 55 | private View view; 56 | 57 | private View indicator; 58 | 59 | private LinearLayout layout_tab; 60 | private TextView textViewProvince; 61 | private TextView textViewCity; 62 | private TextView textViewCounty; 63 | private TextView textViewStreet; 64 | 65 | private ProgressBar progressBar; 66 | 67 | private ListView listView; 68 | private ProvinceAdapter provinceAdapter; 69 | private CityAdapter cityAdapter; 70 | private CountyAdapter countyAdapter; 71 | private StreetAdapter streetAdapter; 72 | private List provinces; 73 | private List cities; 74 | private List counties; 75 | private List streets; 76 | private OnAddressSelectedListener listener; 77 | private OnDialogCloseListener dialogCloseListener; 78 | private onSelectorAreaPositionListener selectorAreaPositionListener; 79 | 80 | private static final int WHAT_PROVINCES_PROVIDED = 0; 81 | private static final int WHAT_CITIES_PROVIDED = 1; 82 | private static final int WHAT_COUNTIES_PROVIDED = 2; 83 | private static final int WHAT_STREETS_PROVIDED = 3; 84 | private AddressDictManager addressDictManager; 85 | private ImageView iv_colse; 86 | private int selectedColor; 87 | private int unSelectedColor; 88 | public int provincePostion; 89 | public int cityPosition; 90 | public int countyPosition; 91 | public int streetPosition; 92 | @SuppressWarnings("unchecked") 93 | private Handler handler = new Handler(new Handler.Callback() { 94 | @Override 95 | public boolean handleMessage(Message msg) { 96 | switch (msg.what) { 97 | case WHAT_PROVINCES_PROVIDED: //更新省份列表 98 | provinces = (List) msg.obj; 99 | provinceAdapter.notifyDataSetChanged(); 100 | listView.setAdapter(provinceAdapter); 101 | 102 | break; 103 | 104 | case WHAT_CITIES_PROVIDED: //更新城市列表 105 | cities = (List) msg.obj; 106 | cityAdapter.notifyDataSetChanged(); 107 | if (Lists.notEmpty(cities)) { 108 | // 以次级内容更新列表 109 | listView.setAdapter(cityAdapter); 110 | // 更新索引为次级 111 | tabIndex = INDEX_TAB_CITY; 112 | } else { 113 | // 次级无内容,回调 114 | callbackInternal(); 115 | } 116 | 117 | break; 118 | 119 | case WHAT_COUNTIES_PROVIDED://更新乡镇列表 120 | counties = (List) msg.obj; 121 | countyAdapter.notifyDataSetChanged(); 122 | if (Lists.notEmpty(counties)) { 123 | listView.setAdapter(countyAdapter); 124 | tabIndex = INDEX_TAB_COUNTY; 125 | } else { 126 | callbackInternal(); 127 | } 128 | 129 | break; 130 | 131 | case WHAT_STREETS_PROVIDED://更新街道列表 132 | streets = (List) msg.obj; 133 | streetAdapter.notifyDataSetChanged(); 134 | if (Lists.notEmpty(streets)) { 135 | listView.setAdapter(streetAdapter); 136 | tabIndex = INDEX_TAB_STREET; 137 | } else { 138 | callbackInternal(); 139 | } 140 | 141 | break; 142 | } 143 | 144 | updateTabsVisibility(); 145 | updateProgressVisibility(); 146 | updateIndicator(); 147 | 148 | return true; 149 | } 150 | }); 151 | 152 | 153 | public AddressSelector(Context context) { 154 | this.context = context; 155 | inflater = LayoutInflater.from(context); 156 | addressDictManager = new AddressDictManager(context); 157 | initViews(); 158 | initAdapters(); 159 | retrieveProvinces(); 160 | } 161 | 162 | /** 163 | * 得到数据库管理者 164 | * @return 165 | */ 166 | public AddressDictManager getAddressDictManager(){ 167 | return addressDictManager; 168 | } 169 | /** 170 | * 初始化布局 171 | */ 172 | private void initViews() { 173 | view = inflater.inflate(R.layout.address_selector, null); 174 | this.progressBar = (ProgressBar) view.findViewById(R.id.progressBar);//进度条 175 | this.iv_colse = (ImageView) view.findViewById(R.id.iv_colse); 176 | this.listView = (ListView) view.findViewById(R.id.listView);//listview 177 | this.indicator = view.findViewById(R.id.indicator); //指示器 178 | this.layout_tab = (LinearLayout) view.findViewById(R.id.layout_tab); 179 | this.textViewProvince = (TextView) view.findViewById(R.id.textViewProvince);//省份 180 | this.textViewCity = (TextView) view.findViewById(R.id.textViewCity);//城市 181 | this.textViewCounty = (TextView) view.findViewById(R.id.textViewCounty);//区 乡镇 182 | this.textViewStreet = (TextView) view.findViewById(R.id.textViewStreet);//街道 183 | 184 | this.textViewProvince.setOnClickListener(new OnProvinceTabClickListener()); 185 | this.textViewCity.setOnClickListener(new OnCityTabClickListener()); 186 | this.textViewCounty.setOnClickListener(new onCountyTabClickListener()); 187 | this.textViewStreet.setOnClickListener(new OnStreetTabClickListener()); 188 | 189 | this.listView.setOnItemClickListener(this); 190 | this.iv_colse.setOnClickListener(new onCloseClickListener()); 191 | updateIndicator(); 192 | } 193 | 194 | /** 195 | *设置字体选中的颜色 196 | */ 197 | public void setTextSelectedColor(int selectedColor){ 198 | this.selectedColor = selectedColor; 199 | } 200 | 201 | /** 202 | *设置字体没有选中的颜色 203 | */ 204 | public void setTextUnSelectedColor(int unSelectedColor){ 205 | this.unSelectedColor = unSelectedColor; 206 | } 207 | /** 208 | * 设置字体的大小 209 | */ 210 | public void setTextSize(float dp){ 211 | textViewProvince.setTextSize(dp); 212 | textViewCity.setTextSize(dp); 213 | textViewCounty.setTextSize(dp); 214 | textViewStreet.setTextSize(dp); 215 | } 216 | 217 | /** 218 | * 设置字体的背景 219 | */ 220 | public void setBackgroundColor(int colorId){ 221 | layout_tab.setBackgroundColor(context.getResources().getColor(colorId)); 222 | } 223 | 224 | /** 225 | * 设置指示器的背景 226 | */ 227 | public void setIndicatorBackgroundColor(int colorId){ 228 | indicator.setBackgroundColor(context.getResources().getColor(colorId)); 229 | } 230 | /** 231 | * 设置指示器的背景 232 | */ 233 | public void setIndicatorBackgroundColor(String color){ 234 | indicator.setBackgroundColor(Color.parseColor(color)); 235 | } 236 | /** 237 | * 初始化adapter 238 | */ 239 | private void initAdapters() { 240 | provinceAdapter = new ProvinceAdapter(); 241 | cityAdapter = new CityAdapter(); 242 | countyAdapter = new CountyAdapter(); 243 | streetAdapter = new StreetAdapter(); 244 | } 245 | 246 | /** 247 | * 更新tab 指示器 248 | */ 249 | private void updateIndicator() { 250 | view.post(new Runnable() { 251 | @Override 252 | public void run() { 253 | switch (tabIndex) { 254 | case INDEX_TAB_PROVINCE: //省份 255 | buildIndicatorAnimatorTowards(textViewProvince).start(); 256 | break; 257 | case INDEX_TAB_CITY: //城市 258 | buildIndicatorAnimatorTowards(textViewCity).start(); 259 | break; 260 | case INDEX_TAB_COUNTY: //乡镇 261 | buildIndicatorAnimatorTowards(textViewCounty).start(); 262 | break; 263 | case INDEX_TAB_STREET: //街道 264 | buildIndicatorAnimatorTowards(textViewStreet).start(); 265 | break; 266 | } 267 | } 268 | }); 269 | } 270 | 271 | /** 272 | * tab 来回切换的动画 273 | * 274 | * @param tab 275 | * @return 276 | */ 277 | private AnimatorSet buildIndicatorAnimatorTowards(TextView tab) { 278 | ObjectAnimator xAnimator = ObjectAnimator.ofFloat(indicator, "X", indicator.getX(), tab.getX()); 279 | 280 | final ViewGroup.LayoutParams params = indicator.getLayoutParams(); 281 | ValueAnimator widthAnimator = ValueAnimator.ofInt(params.width, tab.getMeasuredWidth()); 282 | widthAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 283 | @Override 284 | public void onAnimationUpdate(ValueAnimator animation) { 285 | params.width = (int) animation.getAnimatedValue(); 286 | indicator.setLayoutParams(params); 287 | } 288 | }); 289 | 290 | AnimatorSet set = new AnimatorSet(); 291 | set.setInterpolator(new FastOutSlowInInterpolator()); 292 | set.playTogether(xAnimator, widthAnimator); 293 | 294 | return set; 295 | } 296 | 297 | /** 298 | * 更新tab显示 299 | */ 300 | private void updateTabsVisibility() { 301 | textViewProvince.setVisibility(Lists.notEmpty(provinces) ? View.VISIBLE : View.GONE); 302 | textViewCity.setVisibility(Lists.notEmpty(cities) ? View.VISIBLE : View.GONE); 303 | textViewCounty.setVisibility(Lists.notEmpty(counties) ? View.VISIBLE : View.GONE); 304 | textViewStreet.setVisibility(Lists.notEmpty(streets) ? View.VISIBLE : View.GONE); 305 | //按钮能不能点击 false 不能点击 true 能点击 306 | textViewProvince.setEnabled(tabIndex != INDEX_TAB_PROVINCE); 307 | textViewCity.setEnabled(tabIndex != INDEX_TAB_CITY); 308 | textViewCounty.setEnabled(tabIndex != INDEX_TAB_COUNTY); 309 | textViewStreet.setEnabled(tabIndex != INDEX_TAB_STREET); 310 | if(selectedColor!=0 && unSelectedColor!=0){ 311 | updateTabTextColor(); 312 | } 313 | } 314 | 315 | /** 316 | * 更新字体的颜色 317 | */ 318 | private void updateTabTextColor(){ 319 | if(tabIndex != INDEX_TAB_PROVINCE){ 320 | textViewProvince.setTextColor(context.getResources().getColor(selectedColor)); 321 | }else{ 322 | textViewProvince.setTextColor(context.getResources().getColor(unSelectedColor)); 323 | } 324 | if(tabIndex != INDEX_TAB_CITY){ 325 | textViewCity.setTextColor(context.getResources().getColor(selectedColor)); 326 | }else{ 327 | textViewCity.setTextColor(context.getResources().getColor(unSelectedColor)); 328 | } 329 | if(tabIndex != INDEX_TAB_COUNTY){ 330 | textViewCounty.setTextColor(context.getResources().getColor(selectedColor)); 331 | }else{ 332 | textViewCounty.setTextColor(context.getResources().getColor(unSelectedColor)); 333 | } 334 | if(tabIndex != INDEX_TAB_STREET){ 335 | textViewStreet.setTextColor(context.getResources().getColor(selectedColor)); 336 | }else{ 337 | textViewStreet.setTextColor(context.getResources().getColor(unSelectedColor)); 338 | } 339 | 340 | } 341 | 342 | /** 343 | * 点击省份的监听 344 | */ 345 | class OnProvinceTabClickListener implements View.OnClickListener { 346 | 347 | @Override 348 | public void onClick(View v) { 349 | tabIndex = INDEX_TAB_PROVINCE; 350 | listView.setAdapter(provinceAdapter); 351 | 352 | if (provinceIndex != INDEX_INVALID) { 353 | listView.setSelection(provinceIndex); 354 | } 355 | 356 | updateTabsVisibility(); 357 | updateIndicator(); 358 | } 359 | } 360 | 361 | /** 362 | * 点击城市的监听 363 | */ 364 | class OnCityTabClickListener implements View.OnClickListener { 365 | @Override 366 | public void onClick(View v) { 367 | tabIndex = INDEX_TAB_CITY; 368 | listView.setAdapter(cityAdapter); 369 | 370 | if (cityIndex != INDEX_INVALID) { 371 | listView.setSelection(cityIndex); 372 | } 373 | 374 | updateTabsVisibility(); 375 | updateIndicator(); 376 | } 377 | } 378 | 379 | /** 380 | * 点击区 乡镇的监听 381 | */ 382 | class onCountyTabClickListener implements View.OnClickListener { 383 | @Override 384 | public void onClick(View v) { 385 | tabIndex = INDEX_TAB_COUNTY; 386 | listView.setAdapter(countyAdapter); 387 | 388 | if (countyIndex != INDEX_INVALID) { 389 | listView.setSelection(countyIndex); 390 | } 391 | 392 | updateTabsVisibility(); 393 | updateIndicator(); 394 | } 395 | } 396 | 397 | /** 398 | * 点击街道的监听 399 | */ 400 | class OnStreetTabClickListener implements View.OnClickListener { 401 | @Override 402 | public void onClick(View v) { 403 | tabIndex = INDEX_TAB_STREET; 404 | listView.setAdapter(streetAdapter); 405 | 406 | if (streetIndex != INDEX_INVALID) { 407 | listView.setSelection(streetIndex); 408 | } 409 | 410 | updateTabsVisibility(); 411 | updateIndicator(); 412 | } 413 | } 414 | 415 | /** 416 | * 点击右边关闭dialog监听 417 | */ 418 | class onCloseClickListener implements View.OnClickListener{ 419 | 420 | @Override 421 | public void onClick(View view) { 422 | if(dialogCloseListener!=null){ 423 | dialogCloseListener.dialogclose(); 424 | } 425 | } 426 | } 427 | @Override 428 | public void onItemClick(AdapterView parent, View view, int position, long id) { 429 | switch (tabIndex) { 430 | case INDEX_TAB_PROVINCE: //省份 431 | Province province = provinceAdapter.getItem(position); 432 | provincePostion = position; 433 | // 更新当前级别及子级标签文本 434 | textViewProvince.setText(province.name); 435 | textViewCity.setText("请选择"); 436 | textViewCounty.setText("请选择"); 437 | textViewStreet.setText("请选择"); 438 | //根据省份的id,从数据库中查询城市列表 439 | retrieveCitiesWith(province.id); 440 | 441 | // 清空子级数据 442 | cities = null; 443 | counties = null; 444 | streets = null; 445 | cityAdapter.notifyDataSetChanged(); 446 | countyAdapter.notifyDataSetChanged(); 447 | streetAdapter.notifyDataSetChanged(); 448 | // 更新已选中项 449 | this.provinceIndex = position; 450 | this.cityIndex = INDEX_INVALID; 451 | this.countyIndex = INDEX_INVALID; 452 | this.streetIndex = INDEX_INVALID; 453 | // 更新选中效果 454 | provinceAdapter.notifyDataSetChanged(); 455 | break; 456 | case INDEX_TAB_CITY://城市 457 | City city = cityAdapter.getItem(position); 458 | cityPosition = position; 459 | textViewCity.setText(city.name); 460 | textViewCounty.setText("请选择"); 461 | textViewStreet.setText("请选择"); 462 | //根据城市的id,从数据库中查询城市列表 463 | retrieveCountiesWith(city.id); 464 | // 清空子级数据 465 | counties = null; 466 | streets = null; 467 | countyAdapter.notifyDataSetChanged(); 468 | streetAdapter.notifyDataSetChanged(); 469 | // 更新已选中项 470 | this.cityIndex = position; 471 | this.countyIndex = INDEX_INVALID; 472 | this.streetIndex = INDEX_INVALID; 473 | // 更新选中效果 474 | cityAdapter.notifyDataSetChanged(); 475 | break; 476 | case INDEX_TAB_COUNTY: 477 | County county = countyAdapter.getItem(position); 478 | countyPosition = position; 479 | textViewCounty.setText(county.name); 480 | textViewStreet.setText("请选择"); 481 | retrieveStreetsWith(county.id); 482 | 483 | streets = null; 484 | streetAdapter.notifyDataSetChanged(); 485 | 486 | this.countyIndex = position; 487 | this.streetIndex = INDEX_INVALID; 488 | 489 | countyAdapter.notifyDataSetChanged(); 490 | break; 491 | case INDEX_TAB_STREET: 492 | Street street = streetAdapter.getItem(position); 493 | streetPosition = position; 494 | textViewStreet.setText(street.name); 495 | 496 | this.streetIndex = position; 497 | 498 | streetAdapter.notifyDataSetChanged(); 499 | 500 | callbackInternal(); 501 | if(selectorAreaPositionListener!=null){ 502 | selectorAreaPositionListener.selectorAreaPosition(provincePostion,cityPosition,countyPosition,streetPosition); 503 | } 504 | 505 | break; 506 | } 507 | } 508 | 509 | 510 | /** 511 | * 查询省份列表 512 | */ 513 | private void retrieveProvinces() { 514 | progressBar.setVisibility(View.VISIBLE); 515 | List provinceList = addressDictManager.getProvinceList(); 516 | handler.sendMessage(Message.obtain(handler, WHAT_PROVINCES_PROVIDED, provinceList)); 517 | 518 | } 519 | 520 | /** 521 | * 根据省份id查询城市列表 522 | * @param provinceId 省份id 523 | */ 524 | private void retrieveCitiesWith(int provinceId) { 525 | progressBar.setVisibility(View.VISIBLE); 526 | List cityList = addressDictManager.getCityList(provinceId); 527 | handler.sendMessage(Message.obtain(handler, WHAT_CITIES_PROVIDED, cityList)); 528 | } 529 | 530 | /** 531 | * 根据城市id查询乡镇列表 532 | * @param cityId 城市id 533 | */ 534 | private void retrieveCountiesWith(int cityId){ 535 | progressBar.setVisibility(View.VISIBLE); 536 | List countyList = addressDictManager.getCountyList(cityId); 537 | handler.sendMessage(Message.obtain(handler, WHAT_COUNTIES_PROVIDED, countyList)); 538 | } 539 | /** 540 | * 根据乡镇id查询乡镇列表 541 | * @param countyId 乡镇id 542 | */ 543 | private void retrieveStreetsWith(int countyId) { 544 | progressBar.setVisibility(View.VISIBLE); 545 | List streetList = addressDictManager.getStreetList(countyId); 546 | handler.sendMessage(Message.obtain(handler, WHAT_STREETS_PROVIDED, streetList)); 547 | } 548 | 549 | /** 550 | * 省份 城市 乡镇 街道 都选中完 后的回调 551 | */ 552 | private void callbackInternal() { 553 | if (listener != null) { 554 | Province province = provinces == null || provinceIndex == INDEX_INVALID ? null : provinces.get(provinceIndex); 555 | City city = cities == null || cityIndex == INDEX_INVALID ? null : cities.get(cityIndex); 556 | County county = counties == null || countyIndex == INDEX_INVALID ? null : counties.get(countyIndex); 557 | Street street = streets == null || streetIndex == INDEX_INVALID ? null : streets.get(streetIndex); 558 | 559 | listener.onAddressSelected(province, city, county, street); 560 | } 561 | } 562 | 563 | /** 564 | * 更新进度条 565 | */ 566 | private void updateProgressVisibility() { 567 | ListAdapter adapter = listView.getAdapter(); 568 | int itemCount = adapter.getCount(); 569 | progressBar.setVisibility(itemCount > 0 ? View.GONE : View.VISIBLE); 570 | } 571 | 572 | /** 573 | * 获得view 574 | * @return 575 | */ 576 | public View getView() { 577 | return view; 578 | } 579 | /** 580 | * 省份的adapter 581 | */ 582 | class ProvinceAdapter extends BaseAdapter { 583 | 584 | @Override 585 | public int getCount() { 586 | return provinces == null ? 0 : provinces.size(); 587 | } 588 | 589 | @Override 590 | public Province getItem(int position) { 591 | return provinces.get(position); 592 | } 593 | 594 | @Override 595 | public long getItemId(int position) { 596 | return getItem(position).id; 597 | } 598 | 599 | @Override 600 | public View getView(int position, View convertView, ViewGroup parent) { 601 | Holder holder; 602 | 603 | if (convertView == null) { 604 | convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_area, parent, false); 605 | 606 | holder = new Holder(); 607 | holder.textView = (TextView) convertView.findViewById(R.id.textView); 608 | holder.imageViewCheckMark = (ImageView) convertView.findViewById(R.id.imageViewCheckMark); 609 | 610 | convertView.setTag(holder); 611 | } else { 612 | holder = (Holder) convertView.getTag(); 613 | } 614 | 615 | Province item = getItem(position); 616 | holder.textView.setText(item.name); 617 | 618 | boolean checked = provinceIndex != INDEX_INVALID && provinces.get(provinceIndex).id == item.id; 619 | holder.textView.setEnabled(!checked); 620 | holder.imageViewCheckMark.setVisibility(checked ? View.VISIBLE : View.GONE); 621 | 622 | return convertView; 623 | } 624 | 625 | class Holder { 626 | TextView textView; 627 | ImageView imageViewCheckMark; 628 | } 629 | } 630 | 631 | /** 632 | * 城市的adaoter 633 | */ 634 | class CityAdapter extends BaseAdapter { 635 | 636 | @Override 637 | public int getCount() { 638 | return cities == null ? 0 : cities.size(); 639 | } 640 | 641 | @Override 642 | public City getItem(int position) { 643 | return cities.get(position); 644 | } 645 | 646 | @Override 647 | public long getItemId(int position) { 648 | return getItem(position).id; 649 | } 650 | 651 | @Override 652 | public View getView(int position, View convertView, ViewGroup parent) { 653 | Holder holder; 654 | 655 | if (convertView == null) { 656 | convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_area, parent, false); 657 | 658 | holder = new Holder(); 659 | holder.textView = (TextView) convertView.findViewById(R.id.textView); 660 | holder.imageViewCheckMark = (ImageView) convertView.findViewById(R.id.imageViewCheckMark); 661 | 662 | convertView.setTag(holder); 663 | } else { 664 | holder = (Holder) convertView.getTag(); 665 | } 666 | 667 | City item = getItem(position); 668 | holder.textView.setText(item.name); 669 | 670 | boolean checked = cityIndex != INDEX_INVALID && cities.get(cityIndex).id == item.id; 671 | holder.textView.setEnabled(!checked); 672 | holder.imageViewCheckMark.setVisibility(checked ? View.VISIBLE : View.GONE); 673 | 674 | return convertView; 675 | } 676 | 677 | class Holder { 678 | TextView textView; 679 | ImageView imageViewCheckMark; 680 | } 681 | } 682 | 683 | /** 684 | * 乡镇的adapter 685 | */ 686 | class CountyAdapter extends BaseAdapter { 687 | 688 | @Override 689 | public int getCount() { 690 | return counties == null ? 0 : counties.size(); 691 | } 692 | 693 | @Override 694 | public County getItem(int position) { 695 | return counties.get(position); 696 | } 697 | 698 | @Override 699 | public long getItemId(int position) { 700 | return getItem(position).id; 701 | } 702 | 703 | @Override 704 | public View getView(int position, View convertView, ViewGroup parent) { 705 | Holder holder; 706 | 707 | if (convertView == null) { 708 | convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_area, parent, false); 709 | 710 | holder = new Holder(); 711 | holder.textView = (TextView) convertView.findViewById(R.id.textView); 712 | holder.imageViewCheckMark = (ImageView) convertView.findViewById(R.id.imageViewCheckMark); 713 | 714 | convertView.setTag(holder); 715 | } else { 716 | holder = (Holder) convertView.getTag(); 717 | } 718 | 719 | County item = getItem(position); 720 | holder.textView.setText(item.name); 721 | 722 | boolean checked = countyIndex != INDEX_INVALID && counties.get(countyIndex).id == item.id; 723 | holder.textView.setEnabled(!checked); 724 | holder.imageViewCheckMark.setVisibility(checked ? View.VISIBLE : View.GONE); 725 | 726 | return convertView; 727 | } 728 | 729 | class Holder { 730 | TextView textView; 731 | ImageView imageViewCheckMark; 732 | } 733 | } 734 | 735 | /** 736 | * 街道的adapter 737 | */ 738 | class StreetAdapter extends BaseAdapter { 739 | 740 | @Override 741 | public int getCount() { 742 | return streets == null ? 0 : streets.size(); 743 | } 744 | 745 | @Override 746 | public Street getItem(int position) { 747 | return streets.get(position); 748 | } 749 | 750 | @Override 751 | public long getItemId(int position) { 752 | return getItem(position).id; 753 | } 754 | 755 | @Override 756 | public View getView(int position, View convertView, ViewGroup parent) { 757 | Holder holder; 758 | 759 | if (convertView == null) { 760 | convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_area, parent, false); 761 | 762 | holder = new Holder(); 763 | holder.textView = (TextView) convertView.findViewById(R.id.textView); 764 | holder.imageViewCheckMark = (ImageView) convertView.findViewById(R.id.imageViewCheckMark); 765 | 766 | convertView.setTag(holder); 767 | } else { 768 | holder = (Holder) convertView.getTag(); 769 | } 770 | 771 | Street item = getItem(position); 772 | holder.textView.setText(item.name); 773 | 774 | boolean checked = streetIndex != INDEX_INVALID && streets.get(streetIndex).id == item.id; 775 | holder.textView.setEnabled(!checked); 776 | holder.imageViewCheckMark.setVisibility(checked ? View.VISIBLE : View.GONE); 777 | 778 | return convertView; 779 | } 780 | 781 | class Holder { 782 | TextView textView; 783 | ImageView imageViewCheckMark; 784 | } 785 | } 786 | 787 | 788 | public OnAddressSelectedListener getOnAddressSelectedListener() { 789 | return listener; 790 | } 791 | 792 | /** 793 | * 设置地址监听 794 | * @param listener 795 | */ 796 | public void setOnAddressSelectedListener(OnAddressSelectedListener listener) { 797 | this.listener = listener; 798 | } 799 | public interface OnDialogCloseListener{ 800 | void dialogclose(); 801 | } 802 | /** 803 | * 设置close监听 804 | */ 805 | public void setOnDialogCloseListener(OnDialogCloseListener listener) { 806 | this.dialogCloseListener = listener; 807 | } 808 | public interface onSelectorAreaPositionListener{ 809 | void selectorAreaPosition(int provincePosition,int cityPosition,int countyPosition,int streetPosition); 810 | } 811 | public void setOnSelectorAreaPositionListener(onSelectorAreaPositionListener listener){ 812 | this.selectorAreaPositionListener = listener; 813 | } 814 | 815 | /** 816 | * 根据code 来显示选择过的地区 817 | */ 818 | public void getSelectedArea(String provinceCode,int provincePostion,String cityCode,int cityPosition,String countyCode,int countyPosition,String streetCode,int streetPosition){ 819 | LogUtil.d("数据", "getSelectedArea省份id=" + provinceCode); 820 | LogUtil.d("数据", "getSelectedArea城市id=" + cityCode); 821 | LogUtil.d("数据", "getSelectedArea乡镇id=" + countyCode); 822 | LogUtil.d("数据", "getSelectedArea 街道id=" + streetCode); 823 | if(!TextUtils.isEmpty(provinceCode)){ 824 | Province province = addressDictManager.getProvinceBean(provinceCode); 825 | textViewProvince.setText(province.name); 826 | LogUtil.d("数据", "省份=" + province); 827 | // 更新当前级别及子级标签文本 828 | //根据省份的id,从数据库中查询城市列表 829 | retrieveCitiesWith(province.id); 830 | 831 | // 清空子级数据 832 | cities = null; 833 | counties = null; 834 | streets = null; 835 | cityAdapter.notifyDataSetChanged(); 836 | countyAdapter.notifyDataSetChanged(); 837 | streetAdapter.notifyDataSetChanged(); 838 | // 更新已选中项 839 | this.provinceIndex = provincePostion; 840 | this.cityIndex = INDEX_INVALID; 841 | this.countyIndex = INDEX_INVALID; 842 | this.streetIndex = INDEX_INVALID; 843 | // 更新选中效果 844 | provinceAdapter.notifyDataSetChanged(); 845 | } 846 | if(!TextUtils.isEmpty(cityCode)){ 847 | City city = addressDictManager.getCityBean(cityCode); 848 | textViewCity.setText(city.name); 849 | LogUtil.d("数据", "城市=" + city.name); 850 | //根据城市的id,从数据库中查询城市列表 851 | retrieveCountiesWith(city.id); 852 | // 清空子级数据 853 | counties = null; 854 | streets = null; 855 | countyAdapter.notifyDataSetChanged(); 856 | streetAdapter.notifyDataSetChanged(); 857 | // 更新已选中项 858 | this.cityIndex = cityPosition; 859 | this.countyIndex = INDEX_INVALID; 860 | this.streetIndex = INDEX_INVALID; 861 | // 更新选中效果 862 | cityAdapter.notifyDataSetChanged(); 863 | 864 | } 865 | if(!TextUtils.isEmpty(countyCode)){ 866 | County county = addressDictManager.getCountyBean(countyCode); 867 | textViewCounty.setText(county.name); 868 | LogUtil.d("数据", "乡镇=" + county.name); 869 | retrieveStreetsWith(county.id); 870 | 871 | streets = null; 872 | streetAdapter.notifyDataSetChanged(); 873 | 874 | this.countyIndex = countyPosition; 875 | this.streetIndex = INDEX_INVALID; 876 | 877 | countyAdapter.notifyDataSetChanged(); 878 | } 879 | if(!TextUtils.isEmpty(streetCode)){ 880 | Street street = addressDictManager.getStreetBean(streetCode); 881 | textViewStreet.setText(street.name); 882 | LogUtil.d("数据", "街道=" + street.name); 883 | 884 | this.streetIndex = streetPosition; 885 | 886 | streetAdapter.notifyDataSetChanged(); 887 | 888 | 889 | 890 | } 891 | callbackInternal(); 892 | } 893 | 894 | } 895 | -------------------------------------------------------------------------------- /library/src/main/java/com/smarttop/library/widget/BottomDialog.java: -------------------------------------------------------------------------------- 1 | package com.smarttop.library.widget; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.view.Gravity; 6 | import android.view.Window; 7 | import android.view.WindowManager; 8 | 9 | import com.smarttop.library.R; 10 | import com.smarttop.library.utils.Dev; 11 | 12 | 13 | /** 14 | * Created by smartTop on 2016/10/19. 15 | */ 16 | 17 | public class BottomDialog extends Dialog { 18 | private AddressSelector selector; 19 | 20 | public BottomDialog(Context context) { 21 | super(context, R.style.bottom_dialog); 22 | init(context); 23 | } 24 | 25 | public BottomDialog(Context context, int themeResId) { 26 | super(context, themeResId); 27 | init(context); 28 | } 29 | 30 | public BottomDialog(Context context, boolean cancelable, OnCancelListener cancelListener) { 31 | super(context, cancelable, cancelListener); 32 | init(context); 33 | } 34 | 35 | /** 36 | * 初始化 37 | * 38 | * @param context 39 | */ 40 | private void init(Context context) { 41 | selector = new AddressSelector(context); 42 | setContentView(selector.getView()); 43 | 44 | Window window = getWindow(); 45 | WindowManager.LayoutParams params = window.getAttributes(); 46 | params.width = WindowManager.LayoutParams.MATCH_PARENT; 47 | params.height = Dev.dp2px(context, 256); 48 | window.setAttributes(params); 49 | 50 | window.setGravity(Gravity.BOTTOM); 51 | } 52 | 53 | public void setOnAddressSelectedListener(OnAddressSelectedListener listener) { 54 | this.selector.setOnAddressSelectedListener(listener); 55 | } 56 | public static BottomDialog show(Context context) { 57 | return show(context, null); 58 | } 59 | 60 | public static BottomDialog show(Context context, OnAddressSelectedListener listener) { 61 | BottomDialog dialog = new BottomDialog(context, R.style.bottom_dialog); 62 | dialog.selector.setOnAddressSelectedListener(listener); 63 | dialog.show(); 64 | 65 | return dialog; 66 | } 67 | public void setDialogDismisListener(AddressSelector.OnDialogCloseListener listener){ 68 | this.selector.setOnDialogCloseListener(listener); 69 | } 70 | 71 | /** 72 | * 设置选中位置的监听 73 | * @param listener 74 | */ 75 | public void setSelectorAreaPositionListener(AddressSelector.onSelectorAreaPositionListener listener){ 76 | this.selector.setOnSelectorAreaPositionListener(listener); 77 | } 78 | /** 79 | *设置字体选中的颜色 80 | */ 81 | public void setTextSelectedColor(int selectedColor){ 82 | this.selector.setTextSelectedColor(selectedColor); 83 | } 84 | /** 85 | *设置字体没有选中的颜色 86 | */ 87 | public void setTextUnSelectedColor(int unSelectedColor){ 88 | this.selector.setTextUnSelectedColor(unSelectedColor); 89 | } 90 | /** 91 | * 设置字体的大小 92 | */ 93 | public void setTextSize(float dp){ 94 | this.selector.setTextSize(dp); 95 | } 96 | /** 97 | * 设置字体的背景 98 | */ 99 | public void setBackgroundColor(int colorId){ 100 | this.selector.setBackgroundColor(colorId); 101 | } 102 | /** 103 | * 设置指示器的背景 104 | */ 105 | public void setIndicatorBackgroundColor(int colorId){ 106 | this.selector.setIndicatorBackgroundColor(colorId); 107 | } 108 | /** 109 | * 设置指示器的背景 110 | */ 111 | public void setIndicatorBackgroundColor(String color){ 112 | this.selector.setIndicatorBackgroundColor(color); 113 | } 114 | 115 | /** 116 | * 设置已选中的地区 117 | * @param provinceCode 省份code 118 | * @param provinPosition 省份所在的位置 119 | * @param cityCode 城市code 120 | * @param cityPosition 城市所在的位置 121 | * @param countyCode 乡镇code 122 | * @param countyPosition 乡镇所在的位置 123 | * @param streetCode 街道code 124 | * @param streetPosition 街道所在位置 125 | */ 126 | public void setDisplaySelectorArea(String provinceCode,int provinPosition,String cityCode,int cityPosition,String countyCode,int countyPosition,String streetCode,int streetPosition){ 127 | this.selector.getSelectedArea(provinceCode,provinPosition,cityCode,cityPosition,countyCode,countyPosition,streetCode,streetPosition); 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /library/src/main/java/com/smarttop/library/widget/OnAddressSelectedListener.java: -------------------------------------------------------------------------------- 1 | package com.smarttop.library.widget; 2 | 3 | 4 | import com.smarttop.library.bean.City; 5 | import com.smarttop.library.bean.County; 6 | import com.smarttop.library.bean.Province; 7 | import com.smarttop.library.bean.Street; 8 | 9 | public interface OnAddressSelectedListener { 10 | void onAddressSelected(Province province, City city, County county, Street street); 11 | } 12 | -------------------------------------------------------------------------------- /library/src/main/java/com/smarttop/library/widget/UninterceptableListView.java: -------------------------------------------------------------------------------- 1 | package com.smarttop.library.widget; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.MotionEvent; 6 | import android.widget.ListView; 7 | 8 | /** 9 | * Created by smartTop on 2016/10/19. 10 | */ 11 | public class UninterceptableListView extends ListView { 12 | public UninterceptableListView(Context context) { 13 | super(context); 14 | } 15 | 16 | public UninterceptableListView(Context context, AttributeSet attrs) { 17 | super(context, attrs); 18 | } 19 | 20 | public UninterceptableListView(Context context, AttributeSet attrs, int defStyleAttr) { 21 | super(context, attrs, defStyleAttr); 22 | } 23 | 24 | @Override 25 | public boolean onTouchEvent(MotionEvent ev) { 26 | getParent().requestDisallowInterceptTouchEvent(true); 27 | return super.onTouchEvent(ev); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /library/src/main/res/anim/bottom_dialog_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /library/src/main/res/anim/bottom_dialog_exit.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /library/src/main/res/color/selector_text_color_tab.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/icon_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartTop/AddressSelector/76bc0f153623d0347b16f16afbfea5d7480c6e16/library/src/main/res/drawable-xxhdpi/icon_close.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxxhdpi/ic_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartTop/AddressSelector/76bc0f153623d0347b16f16afbfea5d7480c6e16/library/src/main/res/drawable-xxxhdpi/ic_check.png -------------------------------------------------------------------------------- /library/src/main/res/layout/address_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 20 | 21 | 27 | 28 | 29 | 30 | 31 | 34 | 35 | 40 | 41 | 44 | 45 | 48 | 49 | 52 | 53 | 56 | 57 | 58 | 59 | 65 | 66 | 67 | 68 | 72 | 73 | 77 | 78 | 83 | 84 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /library/src/main/res/layout/item_area.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 29 | 30 | -------------------------------------------------------------------------------- /library/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Library 3 | 4 | -------------------------------------------------------------------------------- /library/src/main/res/values/style.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 17 | 21 | 26 | 37 | -------------------------------------------------------------------------------- /screenshots/screenshort2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartTop/AddressSelector/76bc0f153623d0347b16f16afbfea5d7480c6e16/screenshots/screenshort2.png -------------------------------------------------------------------------------- /screenshots/screenshort3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartTop/AddressSelector/76bc0f153623d0347b16f16afbfea5d7480c6e16/screenshots/screenshort3.png -------------------------------------------------------------------------------- /screenshots/screenshort4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartTop/AddressSelector/76bc0f153623d0347b16f16afbfea5d7480c6e16/screenshots/screenshort4.png -------------------------------------------------------------------------------- /screenshots/screenshort5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartTop/AddressSelector/76bc0f153623d0347b16f16afbfea5d7480c6e16/screenshots/screenshort5.png -------------------------------------------------------------------------------- /screenshots/screenshot1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smartTop/AddressSelector/76bc0f153623d0347b16f16afbfea5d7480c6e16/screenshots/screenshot1.gif -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':library' 2 | --------------------------------------------------------------------------------