Android自定義WheelView地區(qū)選擇三級(jí)聯(lián)動(dòng)
本文實(shí)例為大家分享了WheelView地區(qū)選擇三級(jí)聯(lián)動(dòng)的具體代碼,供大家參考,具體內(nèi)容如下
1. 效果
最近需要做一個(gè)地區(qū)選擇的功能,但是在網(wǎng)上和github上找了很久都沒(méi)找到滿意的,然后朋友推薦了一個(gè)給我,我花了點(diǎn)時(shí)間把代碼大致看懂并改成我想要的,并寫上我的理解。效果如圖:

2. 注意
a. 首先我們要明白,網(wǎng)上這寫三級(jí)聯(lián)動(dòng)的demo,不管是把數(shù)據(jù)庫(kù)文件放在raw還是assets中,我們都要進(jìn)行復(fù)制,將這個(gè)文件復(fù)制到app目錄下,即
/data/data/"+context.getPackageName()+"/databases/
至于到底放在raw還是assets中哪里好些,我也在網(wǎng)上查了下,見(jiàn)這篇博客這里點(diǎn)擊 ,但是按照這里面說(shuō)的好像.db文件最好放在assets中,但是這個(gè)demo中拿過(guò)來(lái),原來(lái)的.db文件就是放在raw中,所以我也沒(méi)改了。
b. 最重要的一點(diǎn),因?yàn)槲覀円话愣际菍⑦x擇完以后的數(shù)據(jù)都要上傳到服務(wù)器中,但是因?yàn)槊總€(gè)后臺(tái)要求的不一樣,所以對(duì)于這個(gè)地區(qū)的.db文件也要求不一樣,所以我們最主要的是學(xué)會(huì)讀取數(shù)據(jù)庫(kù)文件然后通過(guò)代碼形成聯(lián)動(dòng),舉個(gè)例子,比如美團(tuán)有自己的一個(gè)數(shù)據(jù)庫(kù),我們定位湖南長(zhǎng)沙芙蓉區(qū),然后進(jìn)行地區(qū)選擇,將岳麓區(qū)上傳服務(wù)器并且請(qǐng)求數(shù)據(jù)下來(lái),但是我們一般不會(huì)直接上傳文字,一個(gè)是怕重名,還有一個(gè)就是文字不會(huì)絕對(duì)的準(zhǔn)確,比如兩個(gè)字的地名黃山 和 黃 山,看起來(lái)都對(duì),但是你們的后臺(tái)服務(wù)器接受的參數(shù)是黃山,而且使用別人的數(shù)據(jù)庫(kù)中使黃 山,那就出事了,所以我們一般都是傳編碼,但是每個(gè)數(shù)據(jù)庫(kù)中城市編碼一般都是不一樣,所以我們需要找后臺(tái)拿匹配的數(shù)據(jù)庫(kù)文件或者js文件。如圖所示,兩份數(shù)據(jù)庫(kù),一份是朋友推薦自帶的,例外一份是我們的。


我的數(shù)據(jù)庫(kù)中省市區(qū)只有一個(gè)表,而那份卻有三個(gè)表,省 市 區(qū)三個(gè)表。并且編碼也不一樣,可以明顯看出來(lái)。
3. 干貨
a. 布局就直接貼代碼了,很簡(jiǎn)單,mainactivity中就一個(gè)按鈕,而popupwindow中是三個(gè)wheelview,
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:background="#00000000" android:gravity="bottom" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:id="@+id/ly_myinfo_changeaddress_child" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:background="#ffffff" android:orientation="vertical" > <RelativeLayout android:layout_width="match_parent" android:layout_height="44dp" > <View android:background="@color/silver" android:layout_width="match_parent" android:layout_height="0.5dp" /> <TextView android:id="@+id/btn_myinfo_cancel" android:layout_width="wrap_content" android:layout_height="match_parent" android:paddingLeft="18dp" android:text="取消" android:gravity="center" android:layout_alignParentLeft="true" android:layout_marginRight="15dip" android:textColor="#e84515" android:textSize="14sp" /> <TextView android:id="@+id/btn_myinfo_sure" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentRight="true" android:gravity="center" android:text="完成" android:textColor="#e84515" android:paddingRight="18dp" android:textSize="14sp" /> </RelativeLayout> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#d8d8d8"/> <LinearLayout android:layout_width="match_parent" android:layout_height="190dip" android:orientation="horizontal" android:gravity="center_vertical"> <guozhaohui.com.wlylocationchoose.locationchoose.WheelView android:id="@+id/provinceView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1"/> <guozhaohui.com.wlylocationchoose.locationchoose.WheelView android:id="@+id/cityView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1"/> <guozhaohui.com.wlylocationchoose.locationchoose.WheelView android:id="@+id/districtView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1"/> </LinearLayout> </LinearLayout> </LinearLayout>
b. 因?yàn)樯厦嬲f(shuō)了,需要將文件copy到app目錄下,所以直接最好這代碼在application中寫,
package guozhaohui.com.wlylocationchoose;
import android.app.Application;
import java.io.InputStream;
import guozhaohui.com.wlylocationchoose.locationchoose.CityDataHelper;
/**
* Created by ${GuoZhaoHui} on 2017/2/13.
* Abstract:
*/
public class MyApplication extends Application {
private CityDataHelper dataHelper;
@Override
public void onCreate() {
super.onCreate();
/**
* 放在application中,讓app一啟動(dòng)就把raw中文件copy到 "/data/data/"+context.getPackageName()+"/databases/"
* 這是app讀取數(shù)據(jù)的方法,不管是將數(shù)據(jù)庫(kù)文件放在raw或者assets中都是一樣
*/
dataHelper=CityDataHelper.getInstance(this);
InputStream in = this.getResources().openRawResource(R.raw.city);
dataHelper.copyFile(in,CityDataHelper.DATABASE_NAME,CityDataHelper.DATABASES_DIR);
}
}
c. popupwindow不是本次的重點(diǎn)也直接貼代碼。
View popupView = LayoutInflater.from(this).inflate(R.layout.popup_locationchoose, null); mPopupWindow = new PopupWindow(popupView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true); mPopupWindow.setTouchable(true); mPopupWindow.setFocusable(true); mPopupWindow.setOutsideTouchable(true); mPopupWindow.setAnimationStyle(R.style.popup_locationchoose_bottom); // pickText = (TextView)popupView.findViewById(R.id.tv_pickText); provinceView = (WheelView)popupView.findViewById(R.id.provinceView); cityView = (WheelView)popupView.findViewById(R.id.cityView); districtView = (WheelView)popupView.findViewById(R.id.districtView); //確定或者取消 btn_myinfo_sure = (TextView)popupView.findViewById(R.id.btn_myinfo_sure); btn_myinfo_cancel = (TextView) popupView.findViewById(R.id.btn_myinfo_cancel); btn_myinfo_cancel.setOnClickListener(this); btn_myinfo_sure.setOnClickListener(this);
設(shè)置三個(gè)wheelview的可見(jiàn)條目數(shù)
provinceView.setVisibleItems(7); cityView.setVisibleItems(7); districtView.setVisibleItems(7);
為三個(gè) wheelview添加滑動(dòng)事件
// 添加change事件 provinceView.addChangingListener(this); // 添加change事件 cityView.addChangingListener(this); // 添加change事件 districtView.addChangingListener(this);
c. 拿到操作數(shù)據(jù)的對(duì)象SQLiteDatabase
db = dataHelper.openDataBase();
觀察數(shù)據(jù)庫(kù)文件可知這表中是根據(jù)字段level來(lái)判斷省市區(qū)的,如圖

同時(shí)我們也可知這省市區(qū)三個(gè)模型中的字段都是一樣的,都是
private int cityID; private int parentId; private int level; private String name; private String pinyin;
不清楚的可以自己查下表,如圖,我查一個(gè)省

所以我們建立一樣的模型,雖然三個(gè)字段是一樣的,建一個(gè)就可以了,但是為了標(biāo)準(zhǔn)最好還是建三個(gè)。
package guozhaohui.com.wlylocationchoose.locationchoose.model;
public class ProvinceModel {
private int cityID;
private int parentId;
private int level;
private String name;
private String pinyin;
public int getCityID() {
return cityID;
}
public void setCityID(int cityID) {
this.cityID = cityID;
}
public int getParentId() {
return parentId;
}
public void setParentId(int parentId) {
this.parentId = parentId;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPinyin() {
return pinyin;
}
public void setPinyin(String pinyin) {
this.pinyin = pinyin;
}
}
進(jìn)行sql查詢,將查詢到的結(jié)果保存在cursor中,然后進(jìn)行一行行的循環(huán)遍歷,然后將遍歷一行的對(duì)象添加到這個(gè)對(duì)象的集合中。這里得到省的集合。
public List<ProvinceModel> getProvice(SQLiteDatabase db){
String sql="SELECT * FROM ChooseCityModel where level = 1 ORDER BY cityID";
Cursor cursor = db.rawQuery(sql,null);
List<ProvinceModel> list=new ArrayList<ProvinceModel>();
if (cursor!=null&&cursor.getCount() > 0) {
while (cursor.moveToNext()){
ProvinceModel provinceModel=new ProvinceModel();
provinceModel.setCityID(cursor.getInt(cursor.getColumnIndex("cityID")));
provinceModel.setParentId(cursor.getInt(cursor.getColumnIndex("parentId")));
provinceModel.setLevel(cursor.getInt(cursor.getColumnIndex("level")));
provinceModel.setName(cursor.getString(cursor.getColumnIndex("name")));
provinceModel.setPinyin(cursor.getString(cursor.getColumnIndex("pinyin")));
list.add(provinceModel);
}
}
return list;
}
根據(jù)表的結(jié)構(gòu),得到相應(yīng)的sql語(yǔ)句,希望根據(jù)上一級(jí)省的cityId得到下面的市,其實(shí)換句話說(shuō)本級(jí)市的parentId就是上一級(jí)的cityid,不清楚的可以將sql語(yǔ)句查一遍,驗(yàn)證下對(duì)不對(duì),如圖

得到相應(yīng)省下面市的集合
public List<CityModel> getCityByParentId(SQLiteDatabase db, String code){
String sql="SELECT * FROM ChooseCityModel WHERE level = 2 and parentId = ? ORDER BY cityID";
Cursor cursor = db.rawQuery(sql,new String[][code]);
List<CityModel> list=new ArrayList<CityModel>();
if (cursor!=null&&cursor.getCount() > 0) {
while (cursor.moveToNext()){
CityModel cityModel=new CityModel();
cityModel.setCityID(cursor.getInt(cursor.getColumnIndex("cityID")));
cityModel.setParentId(cursor.getInt(cursor.getColumnIndex("parentId")));
cityModel.setLevel(cursor.getInt(cursor.getColumnIndex("level")));
cityModel.setName(cursor.getString(cursor.getColumnIndex("name")));
cityModel.setPinyin(cursor.getString(cursor.getColumnIndex("pinyin")));
list.add(cityModel);
}
}
return list;
}
區(qū)也是一樣的,直接貼代碼了
public List<DistrictModel> getDistrictById(SQLiteDatabase db, String code){
//注意這里的parentId其實(shí)就是上一級(jí)的cityID
String sql="SELECT * FROM ChooseCityModel WHERE level = 3 and parentId = ? ORDER BY cityID";
Cursor cursor = db.rawQuery(sql,new String[][code]);
List<DistrictModel> list=new ArrayList<DistrictModel>();
if (cursor!=null&&cursor.getCount() > 0) {
while (cursor.moveToNext()){
DistrictModel districtModel=new DistrictModel();
districtModel.setCityID(cursor.getInt(cursor.getColumnIndex("cityID")));
districtModel.setParentId(cursor.getInt(cursor.getColumnIndex("parentId")));
districtModel.setLevel(cursor.getInt(cursor.getColumnIndex("level")));
districtModel.setName(cursor.getString(cursor.getColumnIndex("name")));
districtModel.setPinyin(cursor.getString(cursor.getColumnIndex("pinyin")));
list.add(districtModel);
}
}
return list;
}
d. 對(duì)彈出popuwindow顯示的wheelview進(jìn)行初始化,注釋都寫在代碼里,
private void initpopData() {
//初始化數(shù)據(jù)
dataHelper = CityDataHelper.getInstance(this);
db = dataHelper.openDataBase();
provinceDatas = dataHelper.getProvice(db);
if (provinceDatas.size() > 0) {
//彈出popup時(shí),省wheelview中當(dāng)前的省其實(shí)就是省集合的第一個(gè)
mCurrentProvince = provinceDatas.get(0).getName();
//根據(jù)省cityid查詢到第一個(gè)省下面市的集合
cityDatas = dataHelper.getCityByParentId(db, provinceDatas.get(0).getCityID()+"");
}
if (cityDatas.size() > 0) {
//根據(jù)市cityid查詢到第一個(gè)市集合下面區(qū)的集合
districtDatas = dataHelper.getDistrictById(db, cityDatas.get(0).getCityID()+"");
}
//wheelview的適配器代碼
provinceAdapter = new ProvinceAdapter(this, provinceDatas);
provinceAdapter.setTextSize(TEXTSIZE);//設(shè)置字體大小
provinceView.setViewAdapter(provinceAdapter);
updateCitys();
updateAreas();
}
更新省下面市的wheelview內(nèi)容,注釋很清楚,直接上代碼
private void updateCitys() {
int pCurrent = provinceView.getCurrentItem();
if (provinceDatas.size() > 0) {
//這里是必須的的,上面得到的集合只是第一個(gè)省下面所有市的集合及第一個(gè)市下面所有區(qū)的集合
//這里得到的是相應(yīng)省下面對(duì)應(yīng)市的集合
cityDatas = dataHelper.getCityByParentId(db, provinceDatas.get(pCurrent).getCityID()+"");
} else {
cityDatas.clear();
}
citysAdapter = new CitysAdapter(this, cityDatas);
citysAdapter.setTextSize(TEXTSIZE);
cityView.setViewAdapter(citysAdapter);
if (cityDatas.size() > 0) {
//默認(rèn)省下面 市wheelview滑動(dòng)第一個(gè),顯示第一個(gè)市
cityView.setCurrentItem(0);
mCurrentCity = cityDatas.get(0).getName();
} else {
mCurrentCity = "";
}
updateAreas();
}
第三個(gè)wheelview和第二個(gè)一樣的,代碼直接上
private void updateAreas() {
int cCurrent = cityView.getCurrentItem();
if (cityDatas.size() > 0) {
districtDatas = dataHelper.getDistrictById(db, cityDatas.get(cCurrent).getCityID()+"");
} else {
districtDatas.clear();
}
areaAdapter = new AreaAdapter(this, districtDatas);
areaAdapter.setTextSize(TEXTSIZE);
districtView.setViewAdapter(areaAdapter);
if (districtDatas.size() > 0) {
mCurrentDistrict = districtDatas.get(0).getName();
districtView.setCurrentItem(0);
} else {
mCurrentDistrict = "";
}
}
4. 道友留步
1).因?yàn)槲遗笥岩彩窃诰W(wǎng)上哪里找到的demo,所以這原版是誰(shuí)的也不知道了。
2). 源碼地址這里點(diǎn)擊
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android PickerView實(shí)現(xiàn)三級(jí)聯(lián)動(dòng)效果
- Android實(shí)現(xiàn)省市區(qū)三級(jí)聯(lián)動(dòng)
- 最好用的Android省市區(qū)三級(jí)聯(lián)動(dòng)選擇效果
- Android日期選擇器實(shí)現(xiàn)年月日三級(jí)聯(lián)動(dòng)
- Android中使用開(kāi)源框架Citypickerview實(shí)現(xiàn)省市區(qū)三級(jí)聯(lián)動(dòng)選擇
- Android省市區(qū)三級(jí)聯(lián)動(dòng)控件使用方法實(shí)例講解
- android-wheel控件實(shí)現(xiàn)三級(jí)聯(lián)動(dòng)效果
- Android使用android-wheel實(shí)現(xiàn)省市縣三級(jí)聯(lián)動(dòng)
- Android實(shí)現(xiàn)聯(lián)動(dòng)下拉框 下拉列表spinner的實(shí)例代碼
- Android實(shí)現(xiàn)城市選擇三級(jí)聯(lián)動(dòng)
相關(guān)文章
Android實(shí)現(xiàn)簡(jiǎn)單的文件下載與上傳
今天小編就為大家分享一篇關(guān)于Android實(shí)現(xiàn)簡(jiǎn)單的文件下載與上傳,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12
android 自定義view實(shí)現(xiàn)彩虹進(jìn)度條功能
實(shí)現(xiàn)一個(gè)彩虹色進(jìn)度條功能,不說(shuō)明具體用途大家應(yīng)該能猜到,想找別人造的輪子,但是沒(méi)有合適的,所以決定自己實(shí)現(xiàn)一個(gè),下面小編通過(guò)實(shí)例代碼給大家分享android 自定義view實(shí)現(xiàn)彩虹進(jìn)度條功能,感興趣的朋友一起看看吧2024-06-06
Android實(shí)現(xiàn)View滑動(dòng)效果的6種方法
這篇文章主要介紹了Android實(shí)現(xiàn)View滑動(dòng)的6種方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03
Android應(yīng)用實(shí)踐之?dāng)?shù)獨(dú)游戲開(kāi)發(fā)
這篇文章主要為大家詳細(xì)介紹了Android應(yīng)用實(shí)踐之?dāng)?shù)獨(dú)游戲開(kāi)發(fā),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12
Android編程實(shí)現(xiàn)自定義手勢(shì)的方法詳解
這篇文章主要介紹了Android編程實(shí)現(xiàn)自定義手勢(shì)的方法,結(jié)合實(shí)例形式分析了Android自定義手勢(shì)的功能、相關(guān)函數(shù)與具體實(shí)現(xiàn)步驟,需要的朋友可以參考下2016-10-10
Android 數(shù)據(jù)庫(kù)SQLite 寫入SD卡的方法
如果手機(jī)沒(méi)有root,數(shù)據(jù)庫(kù)文件是無(wú)法查看到的,不方便調(diào)試。最好的辦法是把數(shù)據(jù)庫(kù)寫進(jìn)SD卡。通過(guò)本文給大家介紹Android 數(shù)據(jù)庫(kù)SQLite 寫入SD卡的方法,需要的朋友參考下吧2016-04-04
Android顯示系統(tǒng)SurfaceFlinger詳解
本文詳細(xì)講解了Android顯示系統(tǒng)SurfaceFlinger,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12
Android RetainFragment狀態(tài)保存的方法
本篇文章主要介紹了Android RetainFragment狀態(tài)保存的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-02-02

