android-wheel实现省、市、地区联动选择效果

本文介绍了一种基于android-wheel库实现的Android应用中省、市、区联动选择器的详细步骤与技巧。通过定制化的布局与交互逻辑,实现了流畅且符合用户习惯的选择体验。

android-wheel实现省、市、地区联动选择效果

分类: Android 821人阅读 评论(2) 收藏 举报

我们都知道在IOS里面有个滚轮选择器,在Android中有人也实现了一个类似的,叫android-wheel。不过个人感觉实现的还是有点粗糙,这个后面再说。android-wheel给出了好几个不同类型的demo,不过里面的demo有个时间选择器(年月日选择)。没用过的可以去看看里面的demo,应对一般的都没什么大碍。由于公司项目要省、市、地区选择的功能,还要和IOS日期选择器一样,所以就研究了下android-wheel。下面说说我是如何实现省、市、地区选择的功能,还望大家指出其中的不足一起讨论。


首先是xml布局 (Activity_main.xml)

 
<LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android"
     android:layout_height= "fill_parent"
     android:layout_width= "fill_parent"
     android:orientation= "vertical"
     android:background= "@drawable/layout_bg" >
    
     <LinearLayout
         android:layout_height= "wrap_content"
         android:layout_width= "wrap_content"
         android:layout_gravity= "center_horizontal"
         android:paddingTop= "30dp" >
      
         <kankan.wheel.widget.WheelView android:id= "@+id/provice"
             android:layout_height= "wrap_content"
             android:layout_width= "wrap_content"
             android:minWidth= "100dp"
             />
         <kankan.wheel.widget.WheelView android:id= "@+id/city"
             android:layout_height= "wrap_content"
             android:layout_width= "100dp" />
         <kankan.wheel.widget.WheelView android:id= "@+id/area"
             android:layout_height= "wrap_content"
             android:layout_width= "wrap_content" />
     </LinearLayout>
     <Button
         android:id= "@+id/btnOK"
         android:layout_width= "match_parent"
         android:layout_height= "wrap_content"
         android:layout_marginTop= "30dp"
         android:text= "确定"
         />
</LinearLayout>
在Activity_main.xml 文件中布局三个滚轮控件和一个按钮,三个滚轮分别是省、市、地区选择滚轮。最后按下按钮的时候Toast显示选择的省市地区和所选择的地址在数据库中的key。

数据库里面的数据是有一定查询规则的,如图所示:


DQXX03为1,2,3分别代表省(直辖市)、市、地区。所以要获得所有省只需查询DQXX03为1就行了。如果要查询某个省下面的市呢?比如要查询河北省的所有市,可以这么写sql语句 select DQX_DQXX01 from DQXX where DQXX02="河北省"; 这样就查出来了河北省对应的DQX_DQXX01的值为13,然后根据这个值在通过select DQXX01,DQXX02 from DQXX  where DQX_DQXX01=13 就查询出来了每个市的对应键DQXX01的值为1301,1302,1303.......,查询地区也是类似的,这个时候根据DQX_DQXX01=1301或者1302.....查询对应的地区。最后省,市,地区连接起来就是DQXX05列里面的值,我们只要查询下就可以知道唯一地址DQXX01的值。


下面是主Activity文件

  1. package com.wheeltest;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.Map;  
  5.   
  6. import kankan.wheel.widget.OnWheelScrollListener;  
  7. import kankan.wheel.widget.WheelView;  
  8. import kankan.wheel.widget.adapters.ArrayWheelAdapter;  
  9. import android.os.Bundle;  
  10. import android.os.Handler;  
  11. import android.app.Activity;  
  12. import android.content.Context;  
  13. import android.database.sqlite.SQLiteDatabase;  
  14. import android.graphics.Typeface;  
  15. import android.view.View;  
  16. import android.view.ViewGroup;  
  17. import android.widget.TextView;  
  18. import android.widget.Toast;  
  19.   
  20. public class MainActivity extends Activity {  
  21.     private static final String TAG = "MainActivity";  
  22.     private static final String DBNAME = "dqxx.sqlite";  
  23.     private static final String TABLE_NAME = "dqxx";  
  24.     private SQLiteDatabase db;  
  25.     private Map<String, Integer> provinceMap;  
  26.     private Map<String, Integer> cityMap;  
  27.     private Map<String, Integer> areaMap;  
  28.   
  29.     private String[] provinceArray;  
  30.     private String[] cityArray;  
  31.     private String[] areaArray;  
  32.   
  33.     private WheelView provinceWheelView;  
  34.     private WheelView cityWheelView;  
  35.     private WheelView areaWheelView;  
  36.   
  37.     private ProviceCityAreaAdapter provinceAdapter;  
  38.     private ProviceCityAreaAdapter cityAdapter;  
  39.     private ProviceCityAreaAdapter areaAdapter;  
  40.     private Handler mHandler = new Handler();  
  41.     @Override  
  42.     protected void onCreate(Bundle savedInstanceState) {  
  43.         super.onCreate(savedInstanceState);  
  44.         setContentView(R.layout.activity_main);  
  45.   
  46.         initWheelView();  
  47.   
  48.         findViewById(R.id.btnOK).setOnClickListener(new View.OnClickListener() {  
  49.   
  50.             @Override  
  51.             public void onClick(View arg0) {  
  52.                 mHandler.postDelayed(new Runnable() {  
  53.   
  54.                     @Override  
  55.                     public void run() {  
  56.                         StringBuilder sb = new StringBuilder();  
  57.                         sb.append(provinceArray[provinceWheelView.getCurrentItem()]);  
  58.                         if (provinceArray[provinceWheelView.getCurrentItem()].endsWith("市")) {  
  59.                             sb.append("市辖区");  
  60.                         }else {  
  61.                             sb.append(cityArray[cityWheelView.getCurrentItem()]);  
  62.                         }  
  63.                         sb.append(areaArray[areaWheelView.getCurrentItem()]);  
  64.   
  65.                         Toast.makeText(MainActivity.this, sb.toString()+" key:"+DqxxUtils.findPrimaryKey(db, TABLE_NAME, sb.toString()), Toast.LENGTH_SHORT).show();  
  66.                     }  
  67.                 }, 400);  
  68.   
  69.             }  
  70.         });  
  71.     }  
  72.   
  73.     public void initWheelView() {  
  74.         provinceWheelView = (WheelView)findViewById(R.id.provice);  
  75.         cityWheelView = (WheelView)findViewById(R.id.city);  
  76.         areaWheelView = (WheelView)findViewById(R.id.area);  
  77.   
  78.         //初始化省滚轮列表选择器  
  79.         initProviceMap();  
  80.         provinceAdapter = new ProviceCityAreaAdapter(MainActivity.this, provinceArray, 0);  
  81.         provinceWheelView.setViewAdapter(provinceAdapter);  
  82.         provinceWheelView.setCurrentItem(0);  
  83.         provinceWheelView.addScrollingListener(privinceScrollListener);  
  84.   
  85.         //初始化城市滚轮列表选择器  
  86.         String provinceName = provinceArray[0];  
  87.         int dqx_dqxx01 = provinceMap.get(provinceName);  
  88.         if (provinceName.endsWith("市")) {  
  89.             initCityMap(dqx_dqxx01, false);  
  90.         }else {  
  91.             initCityMap(dqx_dqxx01, true);  
  92.         }  
  93.         cityAdapter = new ProviceCityAreaAdapter(MainActivity.this, cityArray, 0);  
  94.         cityWheelView.setViewAdapter(cityAdapter);  
  95.         cityWheelView.setCurrentItem(0);  
  96.         cityWheelView.addScrollingListener(cityScrollListener);  
  97.   
  98.         //初始化地区滚轮列表选择器  
  99.         String cityName = cityArray[0];  
  100.         int dqx_dqxx01_2 = cityMap.get(cityName);  
  101.         provinceName = cityArray[0];  
  102.         if (provinceName.endsWith("市")) {  
  103.             dqx_dqxx01_2 = dqx_dqxx01_2 * 100 +1;  
  104.         }  
  105.         initAreaMap(dqx_dqxx01_2);  
  106.         areaAdapter = new ProviceCityAreaAdapter(MainActivity.this, areaArray, 0);  
  107.         areaWheelView.setViewAdapter(areaAdapter);  
  108.         areaWheelView.setCurrentItem(0);  
  109.   
  110.     }  
  111.   
  112.   
  113.     OnWheelScrollListener privinceScrollListener = new OnWheelScrollListener() {  
  114.   
  115.         @Override  
  116.         public void onScrollingStarted(WheelView wheel) {  
  117.         }  
  118.   
  119.         @Override  
  120.         public void onScrollingFinished(WheelView wheel) {  
  121.             int currentItem = wheel.getCurrentItem();  
  122.             String provinceName = provinceArray[currentItem];  
  123.             int dqxx01 = provinceMap.get(provinceName);  
  124.             if (provinceName.endsWith("市")) {  
  125.                 initCityMap(dqxx01, false);  
  126.             }else {  
  127.                 initCityMap(dqxx01, true);  
  128.             }  
  129.   
  130.             cityAdapter = new ProviceCityAreaAdapter(MainActivity.this, cityArray, 0);  
  131.             cityWheelView.setViewAdapter(cityAdapter);  
  132.             cityWheelView.setCurrentItem(0);  
  133.   
  134.             String cityName = cityArray[0];  
  135.             int dqx_dqxx01_2 = cityMap.get(cityName);  
  136.             if (provinceName.endsWith("市")) {  
  137.                 dqx_dqxx01_2 = dqx_dqxx01_2 * 100 +1;  
  138.             }  
  139.             initAreaMap(dqx_dqxx01_2);  
  140.             areaAdapter = new ProviceCityAreaAdapter(MainActivity.this, areaArray, 0);  
  141.             areaWheelView.setViewAdapter(areaAdapter);  
  142.             areaWheelView.setCurrentItem(0);  
  143.         }  
  144.     };  
  145.   
  146.   
  147.     OnWheelScrollListener cityScrollListener = new OnWheelScrollListener() {  
  148.   
  149.         @Override  
  150.         public void onScrollingStarted(WheelView wheel) {  
  151.         }  
  152.   
  153.         @Override  
  154.         public void onScrollingFinished(WheelView wheel) {  
  155.             String provinceName = provinceArray[provinceWheelView.getCurrentItem()];  
  156.             int dqx_dqxx01 = cityMap.get(cityArray[wheel.getCurrentItem()]);  
  157.             if (provinceName.endsWith("市")) {  
  158.                 dqx_dqxx01 = dqx_dqxx01 * 100 +1;  
  159.             }  
  160.             initAreaMap(dqx_dqxx01);  
  161.             areaAdapter = new ProviceCityAreaAdapter(MainActivity.this, areaArray, 0);  
  162.             areaWheelView.setViewAdapter(areaAdapter);  
  163.             areaWheelView.setCurrentItem(0);  
  164.         }  
  165.     };  
  166.   
  167.   
  168.     public void initProviceMap() {  
  169.         try {  
  170.             DqxxUtils.copyDB(MainActivity.this, DBNAME);  
  171.             if (db == null) {  
  172.                 db = openOrCreateDatabase(getFilesDir().getAbsolutePath() + "/" +DBNAME, Context.MODE_PRIVATE, null);  
  173.             }  
  174.             provinceMap = DqxxUtils.getProvince(db, TABLE_NAME);  
  175.             provinceArray = provinceMap.keySet().toArray(new String[provinceMap.size()]);  
  176.   
  177.         } catch (IOException e) {  
  178.             e.printStackTrace();  
  179.         }  
  180.     }  
  181.   
  182.     public void initCityMap(int dqx_dqxx01, boolean municipalities) {  
  183.         try {  
  184.             DqxxUtils.copyDB(MainActivity.this, DBNAME);  
  185.             if (db == null) {  
  186.                 db = openOrCreateDatabase(getFilesDir().getAbsolutePath() + "/" +DBNAME, Context.MODE_PRIVATE, null);  
  187.             }  
  188.             cityMap = DqxxUtils.getCity(db, TABLE_NAME, dqx_dqxx01, municipalities);  
  189.             cityArray = cityMap.keySet().toArray(new String[cityMap.size()]);  
  190.   
  191.         } catch (IOException e) {  
  192.             e.printStackTrace();  
  193.         }  
  194.     }  
  195.   
  196.     public void initAreaMap(int dqx_dqxx01) {  
  197.         try {  
  198.             DqxxUtils.copyDB(MainActivity.this, DBNAME);  
  199.             if (db == null) {  
  200.                 db = openOrCreateDatabase(getFilesDir().getAbsolutePath() + "/" +DBNAME, Context.MODE_PRIVATE, null);  
  201.             }  
  202.             areaMap = DqxxUtils.getArea(db, TABLE_NAME, dqx_dqxx01);  
  203.             areaArray = areaMap.keySet().toArray(new String[areaMap.size()]);  
  204.   
  205.         } catch (IOException e) {  
  206.             e.printStackTrace();  
  207.         }  
  208.     }  
  209.   
  210.   
  211.   
  212.     public class ProviceCityAreaAdapter extends ArrayWheelAdapter<String> {  
  213.         private int currentItem;  
  214.         private int currentValue;  
  215.   
  216.         public ProviceCityAreaAdapter(Context context, String[] items, int current) {  
  217.             super(context, items);  
  218.             this.currentValue = current;  
  219.         }  
  220.   
  221.   
  222.         public void setCurrentValue(int value){  
  223.             this.currentValue = value;  
  224.         }  
  225.   
  226.         @Override  
  227.         protected void configureTextView(TextView view) {  
  228.             super.configureTextView(view);  
  229. //          if (currentItem == currentValue) {  
  230. //              view.setTextColor(0xFF0000F0);  
  231. //          }  
  232.             view.setTypeface(Typeface.SANS_SERIF);  
  233.         }  
  234.   
  235.         @Override  
  236.         public View getItem(int index, View convertView, ViewGroup parent) {  
  237.             currentItem = index;  
  238.             return super.getItem(index, convertView, parent);  
  239.         }  
  240.   
  241.     }  
  242.   
  243.     @Override  
  244.     protected void onDestroy() {  
  245.         if (db != null) {  
  246.             db.close();  
  247.             db = null;  
  248.         }  
  249.         super.onDestroy();  
  250.     }  
首先定义了三个数组,分别用来装查询到的省,市和地区,其实在这三个之中,省份是不会动态变得。每次都一样,关键就在于,每次省滚轮改变后要查询到对应的市和市对应的地区数据,要及时查询出来,不然会有卡顿的感觉,流畅性不好。我的数据库起初是放在assert目录下面,然后把它写到应用程序对应的/data/data/包名/files目录下,然后在该目录下打开数据库。这里涉及到一些缓冲和效率方面的东西,我现在是公用全局的SQLiteDatabase对象db,不是每次都打开数据库。然后每次查询都只查询出对用所需要的列的数据来,这个可以加快查询。本来我想实现滚轮选择某个数据的时候该数据行深色显示,但是发现好像挺难实现的,android-wheel好像做的不是很强大,也可能是我愚笨没找到实现的方法吧。有知道的麻烦说句啊,谢了。

最后一个类是工具类,包含一些数据库操作和文件读写的。我就不贴出来了。我已经把这个工程放到Github上去了地址https://github.com/ywenblocker/Provinces-Picker-wheel大家可以看看,有问题也欢迎提出来。最后附上一张效果图。


最后说句,该工程用到的数据库是公司项目的,不好意思,不能开源,还望见谅。除了这个其他东西都有。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值