今天做了一个关于WheelView的控件来选择地区,并且要实现累死淘宝JD等的点击地址,然后选择省市区的,从底部弹出。
这部分,个人整理的时候是分成两部分来实现的,首先,毋庸置疑先实现我们的WheelView的滚动选择效果。
这部分,自己弄的时候是没有关于省市区的xml文件的,所以在网上找了好多,大家也可以参考下面这个来进行,还附带有实现的demo,我自己参考实现了。
实现的效果图:
参考实现省市区的wheelview的链接:
http://blog.csdn.net/wulianghuan/article/details/41549189#comments
因为这个demo的实现是直接一个wheelview的界面,跟我的要求有一定的偏差,所以,我整理了一下popupwindow的简单使用。基本套路都是一样的。
private WheelView mViewProvince; private WheelView mViewCity; private WheelView mViewDistrict; private Button mBtnConfirm; PopupWindow pw;
首先在你需要弹出Popupwindow的地方,声明。然后还有我们弹出以后的是wheelview,所以一并声明,因为后面要说到获取wheelview的资源ID。
View contentview = LayoutInflater.from(this).inflate(R.layout.activity_wheel, null); pw = new PopupWindow(contentview, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT, true); mViewProvince = (WheelView) contentview.findViewById(R.id.id_province); mViewCity = (WheelView) contentview.findViewById(R.id.id_city); mViewDistrict = (WheelView) contentview.findViewById(R.id.id_district); mBtnConfirm = (Button) contentview.findViewById(R.id.btn_confirm);
上面这部分就是我们获取Ppopupwindow的资源ID的方法。利用LayoutInflater中的inflate来加载我们要显示的滚动的布局文件。
这里简单的插入一下LayoutInflater.inflate()的作用: inflate的作用就是将一个xml定义的布局查找出来,inflate是加载一个布局。
我们加载完我们需要的滚动的wheelview的布局后,就要使用我们的PopupWindow,将我们的自定义的activity_wheel的layout添加到从底部弹出的Window。
具体代码上面已经写到,说一下参数,第一个参数就是我们的popupwindow里面要附加的布局xml,第二个则是我们popupwindow的宽度,第三个是高度,第四个参数是否可获取焦点。
然后获取资源的ID就是如上所示。
获取到我们的资源ID,就可以来显示监听我们的wheelview了。
具体代码如下:
public void onClick(View v) { switch (v.getId()) { case R.id.rela_addc: setUpViews(); setUpListener(); setUpData(); pw.showAtLocation(AddAddressActivity.this.findViewById(R.id.rela_address), Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0); break;这是我自己的点击时间,然后弹出popupwindow,并且对popupwindow的位置进行了自定义。
private void setUpListener() { // 添加change事件 mViewProvince.addChangingListener(this); // 添加change事件 mViewCity.addChangingListener(this); // 添加change事件 mViewDistrict.addChangingListener(this); // 添加onclick事件 mBtnConfirm.setOnClickListener(this); } private void setUpData() { initProvinceDatas(); mViewProvince.setViewAdapter(new ArrayWheelAdapter<String>(AddAddressActivity.this, mProvinceDatas)); // 设置可见条目数量 mViewProvince.setVisibleItems(7); mViewCity.setVisibleItems(7); mViewDistrict.setVisibleItems(7); updateCities(); updateAreas(); } @Override public void onChanged(WheelView wheel, int oldValue, int newValue) { // TODO Auto-generated method stub if (wheel == mViewProvince) { updateCities(); } else if (wheel == mViewCity) { updateAreas(); } else if (wheel == mViewDistrict) { mCurrentDistrictName = mDistrictDatasMap.get(mCurrentCityName)[newValue]; mCurrentZipCode = mZipcodeDatasMap.get(mCurrentDistrictName); } } /** * 根据当前的市,更新区WheelView的信息 */ private void updateAreas() { int pCurrent = mViewCity.getCurrentItem(); mCurrentCityName = mCitisDatasMap.get(mCurrentProviceName)[pCurrent]; String[] areas = mDistrictDatasMap.get(mCurrentCityName); if (areas == null) { areas = new String[]{""}; } mViewDistrict.setViewAdapter(new ArrayWheelAdapter<String>(this, areas)); mViewDistrict.setCurrentItem(0); } /** * 根据当前的省,更新市WheelView的信息 */ private void updateCities() { int pCurrent = mViewProvince.getCurrentItem(); mCurrentProviceName = mProvinceDatas[pCurrent]; String[] cities = mCitisDatasMap.get(mCurrentProviceName); if (cities == null) { cities = new String[]{""}; } mViewCity.setViewAdapter(new ArrayWheelAdapter<String>(this, cities)); mViewCity.setCurrentItem(0); updateAreas(); }
这里比较关键的就是initProvinceDatas()的方法。
对于上述的一段代码我要着重说明一下,个人在使用的时候发现了一些小bug,所以赶紧及时更新。
@Override public void onChanged(WheelView wheel, int oldValue, int newValue) { // TODO Auto-generated method stub if (wheel == mViewProvince) { updateCities(); } else if (wheel == mViewCity) { updateAreas(); } else if (wheel == mViewDistrict) { mCurrentDistrictName = mDistrictDatasMap.get(mCurrentCityName)[newValue]; mCurrentZipCode = mZipcodeDatasMap.get(mCurrentDistrictName); } }这段代码,是对wheelview的条目变更的监听,我们在使用的时候会发现,当我滚动省的时候,市区的wheelview会得到更新,但是,区这部分的值虽然看起来变化了,但是当你获取的时候,我们会发现他一直默认显示第一个省第一个市的第一个区的名字,这就需要我们思考一下了。
根据代码,发现这段wheelview的变动,市的滚动,区的值是没有获取的,只是在
mViewDistrict.setViewAdapter(new ArrayWheelAdapter<String>(this, areas)); mViewDistrict.setCurrentItem(0);这段代码中设置了默认的是第一个位置的值。
所以,我们修改过后是这样的。
@Override public void onChanged(WheelView wheel, int oldValue, int newValue) { // TODO Auto-generated method stub if (wheel == mViewProvince) { updateCities(); int pCurrent = mViewDistrict.getCurrentItem(); mCurrentDistrictName = mDistrictDatasMap.get(mCurrentCityName)[pCurrent]; } else if (wheel == mViewCity) { updateAreas(); int pCurrent = mViewDistrict.getCurrentItem(); mCurrentDistrictName = mDistrictDatasMap.get(mCurrentCityName)[pCurrent]; } else if (wheel == mViewDistrict) { mCurrentDistrictName = mDistrictDatasMap.get(mCurrentCityName)[newValue]; mCurrentZipCode = mZipcodeDatasMap.get(mCurrentDistrictName); } }修改成这样,大家仔细理解一下应该就可以理解了,就是当省滚动的时候,市的名字会设置到,但是区的名字还是没有变化的,所以我们的区的名字需要获取到当前的市,然后根据市来获取对应的区的值,不多做解释了。
参考源码下载地址:http://download.csdn.net/detail/wulianghuan/8205211
这个链接里面的demo,希望能够对大家有所帮助。