Android實現(xiàn)省市區(qū)三級聯(lián)動的效果
效果圖:

一、簡介
二、實現(xiàn)步驟
/*** 將assets下的資源復(fù)制到應(yīng)用程序的databases目錄下* @param context 上下文* @param fileName assets下的資源的文件名*/public static void copyAssetsToDB(Context context, String fileName) throws IOException {//數(shù)據(jù)庫的存儲路徑,該路徑在:data/data/包名/databases目錄下,String destPath = context.getDatabasePath("").getPath();Log.i("tag","path---->"+destPath);File file = new File(destPath);if (!file.exists()) {file.mkdirs(); //創(chuàng)建目錄}else {return;}//打開assest文件,獲得輸入流InputStream is = context.getAssets().open(fileName);BufferedInputStream bis = new BufferedInputStream(is);//獲得寫入文件的輸出流FileOutputStream fos = new FileOutputStream(destPath +File.separator + fileName);BufferedOutputStream bos = new BufferedOutputStream(fos);byte[] data = new byte[2 * 1024];int len;while ((len = bis.read(data)) != -1){bos.write(data, 0, len);}bos.flush();bis.close();bos.close();}
//打開數(shù)據(jù)庫文件的完整路徑,來獲得sqlite數(shù)據(jù)庫對象SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(dbPath, null);//數(shù)據(jù)庫查詢操作Cursor cursor = database.rawQuery(sql, null);if (cursor != null) {while (cursor.moveToNext()) {//......查詢結(jié)果的操作}cursor.close();}
xmlns:tools="http://schemas.android.com/tools"android:id="@+id/activity_main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.zx.copydatabase.MainActivity"android:orientation="horizontal"android:gravity="center"android:padding="10dp">android:id="@+id/province_picker"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:focusable="true"android:focusableInTouchMode="true"/>android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="省"android:textColor="#000"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"/>android:id="@+id/city_picker"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:focusable="true"android:focusableInTouchMode="true"/>android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="市"android:textColor="#000"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"/>android:id="@+id/area_picker"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:focusable="true"android:focusableInTouchMode="true"/>android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="區(qū)"android:textColor="#000"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"/>
實現(xiàn)這個功能,遇到了的2個問題和坑,文章最后給出詳細解決
public class MainActivity extends AppCompatActivity {private static final String DB_NAME = "mydb.db"; //數(shù)據(jù)庫名稱private NumberPicker provincePicker, cityPicker, areaPicker; //省市區(qū)選擇器private AddressManager manager; //自定義的地址管理器@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//拷貝assets下的文件"mydb.db"到 應(yīng)用的databases目錄下try {MyUtils.copyAssetsToDB(this, DB_NAME);} catch (IOException e) {e.printStackTrace();}//初始化“地址管理器”對象manager = new AddressManager(getDatabasePath(DB_NAME).getPath());initView();initProvince();}//初始化Viewprivate void initView() {provincePicker = (NumberPicker) findViewById(R.id.province_picker);cityPicker = (NumberPicker) findViewById(R.id.city_picker);areaPicker = (NumberPicker) findViewById(R.id.area_picker);}//設(shè)置“省份”選擇器的數(shù)據(jù)private void initProvince() {ListprovinceList = manager.getProvinces(); //獲取所有的省份 //設(shè)置省份的值final String[] provinces = provinceList.toArray(new String[provinceList.size()]);provincePicker.setDisplayedValues(provinces);provincePicker.setMinValue(0); //設(shè)置第一個值provincePicker.setMaxValue(provinces.length - 1); //設(shè)置最后一個值//默認的省份的位置int defaultProvince = provinces.length / 2 == 0 ? provinces.length / 2 : provinces.length / 2 + 1;provincePicker.setValue(defaultProvince); //設(shè)置當前值//根據(jù)當前默認的省份來設(shè)置對應(yīng)的市showCityByProvince(provinces[provincePicker.getValue()]);//省份的選擇事件provincePicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {@Overridepublic void onValueChange(NumberPicker picker, int oldVal, int newVal) {Log.i("tag", "newVal--->" + newVal);showCityByProvince(provinces[newVal]);}});}//根據(jù)選擇的省份名來顯示城市名private void showCityByProvince(String province) {ListcityList = manager.getCities(province); //設(shè)置城市的值final String[] cities = cityList.toArray(new String[cityList.size()]);cityPicker.setDisplayedValues(null); //清空之前的選擇的數(shù)據(jù)cityPicker.setMinValue(0); //設(shè)置第一個值cityPicker.setMaxValue(cities.length - 1); //設(shè)置最后一個值cityPicker.setDisplayedValues(cities);//根據(jù)當前默認的城市來設(shè)置對應(yīng)的區(qū)showAreaByCity(cities[cityPicker.getValue()]);//城市的選擇事件cityPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {@Overridepublic void onValueChange(NumberPicker picker, int oldVal, int newVal) {showAreaByCity(cities[newVal]);}});}//根據(jù)選擇的城市名來顯示區(qū)名private void showAreaByCity(String city) {ListareaList = manager.getAreas(city); //設(shè)置區(qū)的值String[] areas = areaList.toArray(new String[areaList.size()]);areaPicker.setDisplayedValues(null);areaPicker.setMinValue(0); //設(shè)置第一個值areaPicker.setMaxValue(areas.length - 1); //設(shè)置最后一個值areaPicker.setDisplayedValues(areas);}}
/*** "省市區(qū)"數(shù)據(jù)庫操作類*/public class AddressManager {//ssq表的字段的名字private static final String TABLE_NAME = "ssq"; //表名private static final String PROVINCE = "province"; //省份名稱private static final String CITY = "city"; //市的名稱private static final String AREA = "area"; //區(qū)的名稱private SQLiteDatabase database; //sqlite數(shù)據(jù)庫對象/*** @param dbPath 數(shù)據(jù)庫中“省市區(qū)”表的路徑*/public AddressManager(String dbPath) {database = SQLiteDatabase.openOrCreateDatabase(dbPath, null);}/*** 查詢所有省份** @return 所有的省份名稱*/public ListgetProvinces() { String sql = "select distinct " + PROVINCE + " from " + TABLE_NAME;Cursor cursor = database.rawQuery(sql, null);ListprovinceList = new ArrayList<>(); if (cursor != null) {while (cursor.moveToNext()) {String province = cursor.getString(cursor.getColumnIndex("province"));Log.i("tag", "province----->" + province);provinceList.add(province);}cursor.close();}return provinceList;}/*** 查詢指定省份或直轄市的所有市的集合** @param province 省份名稱* @return 查詢到的所有城市*/public ListgetCities(String province) { String sql = "select distinct " + CITY + " from " + TABLE_NAME + " where " + PROVINCE + " = ?";Cursor cursor = database.rawQuery(sql, new String[]{province});ListaddressList = new ArrayList<>(); while (cursor.moveToNext()) {String city = cursor.getString(cursor.getColumnIndex(CITY));Log.i("tag", "city----->" + city);addressList.add(city);}//關(guān)閉游標cursor.close();return addressList;}/*** 查詢指定市的所有區(qū)的列表的List集合** @param city 市的名稱* @return 查詢到的所有區(qū)*/public ListgetAreas(String city) { //獲取指定市的所有區(qū)的列表的sql語句String sql = "select distinct " + AREA + " from " + TABLE_NAME + " where " + CITY + " = ?";Cursor cursor = database.rawQuery(sql, new String[]{city});ListaddressList = new ArrayList<>(); while (cursor.moveToNext()) {//獲取區(qū)的名稱String area = cursor.getString(cursor.getColumnIndex(AREA));Log.i("tag", "area----->" + area);//把所有的區(qū)添加到List集合addressList.add(area);}//關(guān)閉游標cursor.close();return addressList;}}
遇到的問題和坑
np = (NumberPicker) findViewById(R.id.numberPicker1);String[] city = {"北京","上海","廣州","深圳","成都","天津"};np.setDisplayedValues(city);np.setMinValue(0); //設(shè)置顯示的第一個數(shù)據(jù)np.setMaxValue(city.length - 1); //設(shè)置顯示的最后一個數(shù)據(jù)
1、當前NumberPicker的最大值大于數(shù)組大小時,先setMaxValue再setDisplayedValues。
2、當前NumberPicker的最大值小于數(shù)組大小時,先setDisplayedValues再setMaxValue。
private void updateCitySelector() {int oldMax = cityPicker.getMaxValue();int newMax = mCitys.length - 1;if(newMax > oldMax) {cityPicker.setDisplayedValues(mCitys);cityPicker.setMaxValue(newMax);} else {cityPicker.setMaxValue(newMax);cityPicker.setDisplayedValues(mCitys);}}
解決方案二(推薦):
在設(shè)置最大值和最新數(shù)組數(shù)據(jù)前,先將之前設(shè)置過的數(shù)據(jù)設(shè)為null。
private void updateCitySelector() {cityPicker.setDisplayedValues(null);cityPicker.setMaxValue(mCitys.length - 1);cityPicker.setDisplayedValues(mCitys);}
評論
圖片
表情
