<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 8469字,需瀏覽 17分鐘

           ·

          2021-11-23 20:47

          效果圖:



          一、簡介


          由于近期項目中要做選擇收貨地址的三級聯(lián)動滾動選擇的效果,所以選擇了Numberpicker來做。下面就來講講我的實現(xiàn)辦法。

          二、實現(xiàn)步驟


          1、由于收貨地址需要用到“省市區(qū)”的數(shù)據(jù)源,所以我先把一個已經(jīng)做好了的數(shù)據(jù)庫文件放在project下的assets目錄下,然后在app初始化的的時候,把assets下的數(shù)據(jù)庫文件拷貝到真機的本地的data/data/包名/databases目錄下。(數(shù)據(jù)庫文件放在github地址的assets目錄下,有需要的自?。?/span>
          /**     * 將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(); }


          2、讀取拷貝在真機本地的數(shù)據(jù)庫文件,用于初始化NumberPicker
          //打開數(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();        }


          別急,完整的查詢代碼放在后面的AddressManager 這個類中


          3、設(shè)置3個NumberPicker的數(shù)據(jù)(帶聯(lián)動效果)


          布局文件
              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"/>


          MainActivity :
          實現(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; //自定義的地址管理器
          @Override protected 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(); }
          //初始化View private 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() { List provinceList = 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() { @Override public void onValueChange(NumberPicker picker, int oldVal, int newVal) { Log.i("tag", "newVal--->" + newVal); showCityByProvince(provinces[newVal]); } }); }
          //根據(jù)選擇的省份名來顯示城市名 private void showCityByProvince(String province) { List cityList = 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() { @Override public void onValueChange(NumberPicker picker, int oldVal, int newVal) { showAreaByCity(cities[newVal]); } }); }
          //根據(jù)選擇的城市名來顯示區(qū)名 private void showAreaByCity(String city) { List areaList = 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); }}


          AddressManager?
          /** * "省市區(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 List getProvinces() {
          String sql = "select distinct " + PROVINCE + " from " + TABLE_NAME; Cursor cursor = database.rawQuery(sql, null); List provinceList = 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 List getCities(String province) { String sql = "select distinct " + CITY + " from " + TABLE_NAME + " where " + PROVINCE + " = ?"; Cursor cursor = database.rawQuery(sql, new String[]{province}); List addressList = 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 List getAreas(String city) { //獲取指定市的所有區(qū)的列表的sql語句 String sql = "select distinct " + AREA + " from " + TABLE_NAME + " where " + CITY + " = ?"; Cursor cursor = database.rawQuery(sql, new String[]{city}); List addressList = 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; }}


          遇到的問題和坑


          一、NumberPicker通常是只能顯示數(shù)字,如何讓它顯示文字呢?
          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ù)

          二、關(guān)于NumberPicker滑動選擇時出現(xiàn)數(shù)組下標越界的問題

          解決方案一

          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);}

          源碼地址:
          https://github.com/zhouxu88/AddressPicker.git

          到這里就結(jié)束啦。
          瀏覽 57
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  狠狠爱网站 | 亚洲国产精品18久久久久久 | 美女考逼网站 | 国产一区二区三区免费播放 | 一级片精品 |