最近离职,准备把精力全放在毕设的项目上,做到城市选择这一块,也见识了wheel组件的强大~
先上效果:
模拟器效果有点渣哎~
上主代码:
/**
* 基于数据库的两级wheel,三级wheel同理,用相应Id衔接起来即可~
*
* @author sen
* 一直以为需要三级wheel,做到取数据那一块的时候发现city没数据啊戳~是的,数据库是自己从网站抓取生成的,不保证完整性,
* 完整的省市区三层数据库同分享在assets文件夹了,有需要的哥们可以写写,逻辑简单~
*/
public class MainActivity extends Activity implements OnWheelChangedListener {
private final String DB_NAME = "sen.db";
/**
* 模拟器下测试路径,真机或者genymotion的话记得修改路径~
*/
private final String DB_PATH = "/data/data/com.ob.main/databases/";
private WheelView wheel_province;
private WheelView wheel_district;
/**
* 所有省
*/
private String[] mProvinceDatas;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
}
/**
* 拷贝assets数据库到本地文件夹下
*/
private void initData() {
try {
copyDataBase();
} catch (IOException e) {
e.printStackTrace();
Log.e("写入数据库失败", "~~~~~~~~~");
}
//从数据库获取省一级的数据
mProvinceDatas = new SqlHelper(this).getProvinceData();
initAreaSelect();
}
/**
* 初始化城市选择器
*/
private void initAreaSelect() {
wheel_province = (WheelView) findViewById(R.id.wheel_province);
wheel_district = (WheelView) findViewById(R.id.wheel_district);
wheel_province.addChangingListener(this);
wheel_district.addChangingListener(this);
//设置适配器,数组类型的数据即可~
wheel_province.setViewAdapter(new ArrayWheelAdapter<String>(
MainActivity.this, mProvinceDatas));
// 设置滑动监听和显示的最大条数
wheel_province.setVisibleItems(7);
wheel_district.setVisibleItems(7);
updateDistricts();
}
@Override
public void onChanged(WheelView wheel, int oldValue, int newValue) {
if (wheel == wheel_province) {
// 根据省数据改变市数据
updateDistricts();
}
}
/**
* 根据当前省更新市一级数据
*/
private void updateDistricts() {
// 得到正在展示市级数据的省级Id
int provinceId = wheel_province.getCurrentItem();
String[] districtData = new SqlHelper(this).getDistrictData(String.valueOf(provinceId));
// 设置适配器,与province数组数据相对应的数据即可~
wheel_district.setViewAdapter(new ArrayWheelAdapter<String>(this, districtData));
wheel_district.setCurrentItem(0);
}
/**
* 拷贝assets数据库到本地文件夹下
*
* @throws IOException
*/
private void copyDataBase() throws IOException {
boolean checkDataBase = checkDataBase();
if (checkDataBase) {
Log.e("数据库已存在", "~~~");
} else {
Log.e("开始写入数据库", "~~~");
//创建文件
// File file = new File(DB_PATH);
// if(!file.exists()){
// file.mkdirs();
// }
InputStream myInput = this.getAssets().open(DB_NAME);
String outFileName = DB_PATH + DB_NAME;
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
}
/**
* 检查数据库是否存在
* @return boolean
*/
private boolean checkDataBase() {
SQLiteDatabase checkDB = null;
String myPath = DB_PATH + DB_NAME;
try {
checkDB = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e) {
// database does't exist yet.
}
if (checkDB != null) {
checkDB.close();
}
return checkDB != null ? true : false;
}
}
嗯..逻辑挺简单,把assets下文件夹的数据库写入APP,然后用相应ID读出相应数据,分别和wheel控件绑定,注释很详细~
这里要注意下写入的路径,我用的ADT,genymotion和真机的话需要修改相应的APP下路径.
读出数据的Java类:
public class SqlHelper {
private DBOpenHelper helper;
public SqlHelper(Context context){
//获取数据库连接
helper=new DBOpenHelper(context);
}
/**
* 省级数据
* @return 省级String数组
*/
public String[] getProvinceData(){
SQLiteDatabase db = helper.getReadableDatabase();
Cursor c = db.rawQuery("Select name From province", null);
int count = c.getCount();
String[] proStr = new String[count];
int i = 0;
//-1开始的下标
while(c.moveToNext()){
proStr[i] = c.getString(c.getColumnIndex("name"));
i++;
}
c.close();
db.close();
return proStr;
}
/**
* 得到省级相应的市级数据
* @param provinceId 省级Id
* @return 市级String数组
*/
public String[] getDistrictData(String provinceId){
SQLiteDatabase db = helper.getReadableDatabase();
Cursor c = db.rawQuery("Select name From district where provinceId = ?", new String[]{provinceId});
int count = c.getCount();
String[] disStr = new String [count];
int i =0;
while(c.moveToNext()){
disStr[i] = c.getString(c.getColumnIndex("name"));
i++;
}
c.close();
db.close();
return disStr;
}
}
数据库打开帮助类:
public class DBOpenHelper extends SQLiteOpenHelper {
public DBOpenHelper(Context context) {
super(context, "sen.db", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
// 版本未更新执行的方法
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 版本更新执行的方法,可以用来达到修改数据库的效果
// db.execSQL("Alter Table persen Add ? Integer");
}
// /**
// * 删除数据库
// *
// * @param context
// * @return
// */
//
// public boolean deleteDatabase(Context context) {
// return context.deleteDatabase("sen.db");
// }
}
xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<kankan.wheel.widget.WheelView
android:id="@+id/wheel_province"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1" />
<kankan.wheel.widget.WheelView
android:id="@+id/wheel_district"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
...嗯~~~~~demo~基于数据库的两级省市选择器——wheel选择器的学习使用
用在项目上的一些改变,代码补充在这里,demo就偷个懒了~^_^
wheel组件改变样式有点黑,文字背景什么的还set不出来...
当时有点懵,这么强大的开源组件,不应该啊~
还好组件的包很明显,拓展性本来打算看自己了~
没想到柳暗花明一村美女都藏在里面哎~
AbstractWheelTextAdapter.java 下面找到了set样式,跟踪发现可以改变...难道是我set的方式不对.. = =!
修改为自己需要的,嗯...样式就这样~~~
之后就是双击选中了,这个在网上源码很多,我就放上来做参考~
class onDoubleClickListener implements OnTouchListener {
int count = 0;
int firClick = 0;
int secClick = 0;
@Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEvent.ACTION_DOWN == event.getAction()) {
count++;
if (count == 1) {
firClick = (int) System.currentTimeMillis();
} else if (count == 2) {
secClick = (int) System.currentTimeMillis();
if (secClick - firClick < 1000) {// 第二次点击的间隔小于1s
//逻辑处理
}
count = 0;
firClick = 0;
secClick = 0;
}
}
//返回true则消耗掉其他触摸之类的点击事件 详见郭神or洋神的事件分发机制
return false;
}
}
嗯~最后设置一下监听
wheel_district.setOnTouchListener(new onDoubleClickListener());
ok~有遇到更多的细节再更新..