[Android]竖直滑动选择器WheelView的实现
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
[Android]竖直滑动选择器WheelView的实现
以下内容为原创,转载请注明:
公司项⽬中有这么⼀个需求,所以需要⾃⼰实现下。
效果类似android4.0以上原⽣的DatePicker这种。
先贴上效果图:
讲下思路吧,因为这是⼀个滚动选择器,所以⾸先想到的是可以基于ListView或者ScrollView⾃定义。
刚开始我⽤的是继承ListView来实现,把滑动选择的每个item作为listview中的⼀个item,然后根据FirstVisiblePosition、LastVisiblePosition 来判断某个item是否在选中的区域,但是后来发现偶尔有时候调⽤getFirstVisiblePosition和getLastVisiblePosition的结果跟我看到的界⾯显⽰的item并不⼀致(我是在Adapter中调⽤的这两个⽅法),后来分析可能是因为我调⽤了scrollTo后没有刷新adapter的原因吧。
再后来,就打算使⽤ScrollView来实现了,其中的每个item都是⼀个View(我这⾥使⽤了TextView)。
因为这个选中框是在中间的位置,所以刚启动时第⼀个item应该需要在中间选中框显⽰,所以前⾯应该使⽤空⽩补全。
最后⼀个也是如此,后⾯也需要空⽩补全。
在滑动过程中需要实现这种场景:滑动结束后,必须且只有⼀个item完整显⽰在选择框中。
所以我们必须要监听滚动停⽌的事件,然后在滚动停⽌后判断是不是满⾜前⾯的场景,如果没有,则需要代码中实现滚动到正确位置。
但是,蛋疼的是,sdk中竟然没有提供原⽣的监听滚动停⽌的api,然后在⽹上找了很久,得到的结果是只能另辟蹊径,使⽤了⼀个⽹友的做法通过主动检测是否停⽌滚动的⽅法去实现(总觉得⽅法有点坑,额好吧但是暂时先⽤了这个⽅法)。
思路就讲到这⾥了。
使⽤⽅式:
/**
* Author: wangjie
* Email: tiantian.china.2@
* Date: 7/1/14.
*/
@AILayout(yout.main)
public class MainActivity extends AIActivity {
public static final String TAG = MainActivity.class.getSimpleName();
private static final String[] PLANETS = new String[]{"Mercury", "Venus", "Earth", "Mars", "Jupiter", "Uranus", "Neptune", "Pluto"};
@AIView(R.id.main_wv)
private WheelView wva;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
wva.setOffset(1);
wva.setItems(Arrays.asList(PLANETS));
wva.setOnWheelViewListener(new WheelView.OnWheelViewListener() {
@Override
public void onSelected(int selectedIndex, String item) {
Logger.d(TAG, "selectedIndex: " + selectedIndex + ", item: " + item);
}
});
}
@AIClick({R.id.main_show_dialog_btn})
public void onClickCallbackSample(View view) {
switch (view.getId()) {
case R.id.main_show_dialog_btn:
View outerView = LayoutInflater.from(context).inflate(yout.wheel_view, null);
WheelView wv = (WheelView) outerView.findViewById(R.id.wheel_view_wv);
wv.setOffset(2);
wv.setItems(Arrays.asList(PLANETS));
wv.setSeletion(3);
wv.setOnWheelViewListener(new WheelView.OnWheelViewListener() {
@Override
public void onSelected(int selectedIndex, String item) {
Logger.d(TAG, "[Dialog]selectedIndex: " + selectedIndex + ", item: " + item);
}
});
new AlertDialog.Builder(context)
.setTitle("WheelView in Dialog")
.setView(outerView)
.setPositiveButton("OK", null)
.show();
break;
}
}
}
注意:这个Demo只是⼀个临时解决⽅案,⽐较适合选项较少的时候使⽤,⽐如选择性别、星期等。
因为⾥⾯的买个item都是⼀个单独的View,并没有去实现View的缓存和重⽤,所以⼤家这点需要注意下。
如果有时间我会完善优化这个代码,实现View的复⽤。
关于View的复⽤,⼤家可以fork后⾃⼰尝试改写,我讲下主要的思路(我的思路,当然不能代表是最优的⽅案)是:假设,每页显⽰5个item以供选择,那么刚开始加载时,先⽣成6个item,其中6个是正常的6个选项所new出来的item,注意!因为每页显⽰5个item,所以第6个item不可见,但是却已经new出来了,其实可以正常显⽰。
然后往下滚动时,监听滚动事件,第6个完全显⽰时,这个时候第⼀个item已经不可见了,所以可以重⽤该item的view。
所以如果往下滚要显⽰第7个item时,重⽤第⼀个item的view,作为第7个item的view显⽰数据。
再往下也是⼀样。
总之,重⽤当前不可见的item的view给即将显⽰的item。
注意:项⽬使⽤到了⼀部分注解、⽇志⽅⾯的东西,跟实现WheelView没关系,但是可以简化代码,提⾼编码效率。