Android-PickerView完全解析:仿iOS滚轮选择器的设计与实现

Android-PickerView完全解析:仿iOS滚轮选择器的设计与实现

【免费下载链接】Android-PickerView 【免费下载链接】Android-PickerView 项目地址: https://gitcode.com/gh_mirrors/and/Android-PickerView

还在为Android原生选择器样式丑陋、交互生硬而烦恼?是否想让你的App拥有iOS般丝滑的滚轮选择体验?本文将带你全面掌握Android-PickerView的设计原理与实战技巧,从基础使用到高级定制,让你轻松实现高颜值选择器。

读完本文你将获得:

  • 掌握时间选择器(TimePickerView)的三种常见配置方案
  • 学会多级联动选项选择器(OptionsPickerView)的数据绑定技巧
  • 解锁自定义布局与主题样式的实现方法
  • 规避Calendar月份陷阱等常见问题

项目概述与核心价值

Android-PickerView是一款高度模仿iOS滚轮选择器的开源控件库,提供时间选择器和选项选择器两大核心功能。相比系统原生控件,它具有以下优势:

  • 支持三级联动选择,满足省市区选择等复杂场景
  • 内置循环滚动模式,提供流畅的选择体验
  • 丰富的自定义选项,包括文字大小、颜色、间距等样式调整
  • 支持农历显示、自定义单位标签等特色功能
  • 轻量级设计,核心模块仅依赖WheelView基础控件

时间选择器默认样式

项目核心代码结构采用模块化设计,主要包含三大模块:

  • pickerview:核心实现模块,包含TimePickerView和OptionsPickerView
  • wheelview:基础滚轮控件,提供底层滚动与选择功能
  • app:示例代码模块,包含各种使用场景的演示

核心类关系如下: mermaid

快速集成与基础使用

环境准备与依赖添加

项目已停止JCenter更新,推荐直接下载源码引入module。通过GitCode仓库获取最新代码:

git clone https://gitcode.com/gh_mirrors/and/Android-PickerView.git

在Android Studio中导入项目后,在settings.gradle中确保包含以下模块:

include ':app', ':pickerview', ':wheelview'

时间选择器(TimePickerView)基础实现

时间选择器支持年月日时分秒等多种组合格式,最基础的实现仅需5行代码:

// 时间选择器基础用法
TimePickerView pvTime = new TimePickerBuilder(this, new OnTimeSelectListener() {
    @Override
    public void onTimeSelect(Date date, View v) {
        Toast.makeText(MainActivity.this, getTime(date), Toast.LENGTH_SHORT).show();
    }
}).build();
pvTime.show(); // 显示时间选择器

核心实现类TimePickerView.java通过WheelTime组件处理时间逻辑,支持自定义显示格式:

// 设置显示格式示例(年月日时分)
.setType(new boolean[]{true, true, true, true, true, false})

夜间模式时间选择器

选项选择器(OptionsPickerView)基础实现

选项选择器支持多级联动,以城市选择为例:

// 城市选择器实现
OptionsPickerView pvOptions = new OptionsPickerBuilder(this, new OnOptionsSelectListener() {
    @Override
    public void onOptionsSelect(int options1, int option2, int options3, View v) {
        String tx = options1Items.get(options1).getPickerViewText()
                  + options2Items.get(options1).get(option2);
        btn_Options.setText(tx);
    }
})
.setTitleText("城市选择")
.setSelectOptions(0, 1) // 默认选中项
.build();

// 设置数据源
pvOptions.setPicker(options1Items, options2Items);
pvOptions.show();

OptionsPickerView.java通过WheelOptions处理多级联动逻辑,支持非联动模式设置:

// 非联动模式设置不同数据源
pvNoLinkOptions.setNPicker(food, clothes, computer);

高级特性与定制方案

时间选择器的三种典型配置

1. 带范围限制的时间选择器

适用于出生日期选择等需要限制时间范围的场景:

Calendar startDate = Calendar.getInstance();
startDate.set(1990, 0, 1); // 注意月份从0开始
Calendar endDate = Calendar.getInstance();
endDate.set(2023, 11, 31);

TimePickerView pvTime = new TimePickerBuilder(this, listener)
    .setRangDate(startDate, endDate) // 设置范围
    .setTitleText("选择出生日期")
    .setLabel("年", "月", "日", "", "", "")
    .setType(new boolean[]{true, true, true, false, false, false})
    .build();
2. 农历时间选择器

支持公历/农历切换,满足传统节日选择需求:

// 农历选择器实现
initLunarPicker() {
    pvCustomLunar = new TimePickerBuilder(this, listener)
        .setLayoutRes(R.layout.pickerview_custom_lunar, new CustomListener() {
            @Override
            public void customLayout(View v) {
                // 公农历切换复选框
                CheckBox cb_lunar = v.findViewById(R.id.cb_lunar);
                cb_lunar.setOnCheckedChangeListener((buttonView, isChecked) -> {
                    pvCustomLunar.setLunarCalendar(isChecked);
                });
            }
        })
        .setType(new boolean[]{true, true, true, false, false, false})
        .build();
}

农历选择器

3. 时分秒计时器

适用于倒计时、闹钟设置等场景:

// 时分秒选择器配置
.setType(new boolean[]{false, false, false, true, true, true})
.setLabel("", "", "", "时", "分", "秒")
.setTextXOffset(0, 0, 0, 40, 0, -40) // 调整文字偏移

多级联动选择器实现

三级联动是地址选择的常见需求,正确的数据结构至关重要:

// 三级联动数据源结构
private ArrayList<ProvinceBean> options1Items = new ArrayList<>();
private ArrayList<ArrayList<String>> options2Items = new ArrayList<>();
private ArrayList<ArrayList<ArrayList<String>>> options3Items = new ArrayList<>();

// 数据初始化示例
options1Items.add(new ProvinceBean(0, "广东省", "", ""));
ArrayList<String> city = new ArrayList<>();
city.add("广州市");
city.add("深圳市");
options2Items.add(city);

JsonDataActivity.java展示了从JSON文件解析省市区数据的完整实现,使用GetJsonDataUtil.java读取assets目录下的province.json文件。

JSON数据选择演示

深度定制与主题样式

自定义布局实现

通过setLayoutRes方法自定义选择器界面,以自定义选项选择器为例:

pvCustomOptions = new OptionsPickerBuilder(this, listener)
    .setLayoutRes(R.layout.pickerview_custom_options, new CustomListener() {
        @Override
        public void customLayout(View v) {
            // 自定义布局控件初始化
            TextView tvSubmit = v.findViewById(R.id.tv_finish);
            ImageView ivCancel = v.findViewById(R.id.iv_cancel);
            tvSubmit.setOnClickListener(v1 -> {
                pvCustomOptions.returnData();
                pvCustomOptions.dismiss();
            });
            ivCancel.setOnClickListener(v1 -> pvCustomOptions.dismiss());
        }
    })
    .isDialog(true)
    .build();

自定义布局需包含id为optionspicker或timepicker的容器,具体可参考:

自定义布局选择器

主题样式定制

通过Builder模式可全面定制选择器样式:

// 夜间主题配置示例
.setBgColor(Color.BLACK)
.setTitleBgColor(Color.DKGRAY)
.setTitleColor(Color.LTGRAY)
.setCancelColor(Color.YELLOW)
.setSubmitColor(Color.YELLOW)
.setTextColorCenter(Color.LTGRAY)
.setDividerColor(Color.LTGRAY)

关键样式参数说明:

参数作用推荐值
setContentTextSize滚轮文字大小18-22sp
setLineSpacingMultiplier行间距倍数1.2-1.6f
setItemVisibleCount可见item数量3-7(奇数)
setDividerType分割线样式DividerType.CIRCLE

常见问题与解决方案

Calendar月份陷阱

Android中Calendar的月份从0开始(0-11代表1-12月),设置日期范围时需特别注意:

// 错误示例(会导致月份越界)
startDate.set(2023, 12, 1); // 12月实际应为11
// 正确示例
startDate.set(2023, 11, 1); // 12月
数据加载时机

确保数据加载完成后再初始化选择器,避免空指针异常:

// 正确流程
getOptionData(); // 先加载数据
initOptionPicker(); // 再初始化选择器
自定义布局注意事项

自定义布局中必须保留id为optionspicker或timepicker的容器视图,否则会报空指针异常。

实战案例与最佳实践

电商地址选择实现

在电商App中,省市区三级联动选择是必备功能。使用Android-PickerView实现这一功能的步骤:

  1. 准备JSON格式的地区数据文件province.json
  2. 使用GetJsonDataUtil.java解析JSON数据
  3. 构建三级联动数据源
  4. 初始化OptionsPickerView并设置联动数据源

电商地址选择效果

出生日期选择器

结合农历功能实现的出生日期选择器:

// 农历出生日期选择器
private void initLunarPicker() {
    pvCustomLunar = new TimePickerBuilder(this, new OnTimeSelectListener() {
        @Override
        public void onTimeSelect(Date date, View v) {
            Toast.makeText(MainActivity.this, getTime(date), Toast.LENGTH_SHORT).show();
        }
    })
    .setLayoutRes(R.layout.pickerview_custom_lunar, new CustomListener() {
        @Override
        public void customLayout(View v) {
            // 公农历切换逻辑
            CheckBox cb_lunar = v.findViewById(R.id.cb_lunar);
            cb_lunar.setOnCheckedChangeListener((buttonView, isChecked) -> {
                pvCustomLunar.setLunarCalendar(isChecked);
            });
        }
    })
    .setType(new boolean[]{true, true, true, false, false, false})
    .build();
}

农历选择器

性能优化与扩展

WheelView基础控件扩展

如需自定义滚轮行为,可直接使用基础WheelView控件:

<com.contrarywind.view.WheelView
    android:id="@+id/wheelview"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:wheel_cyclic="true"
    app:wheel_item_text_size="16sp"/>

Java代码设置:

WheelView wheelView = findViewById(R.id.wheelview);
wheelView.setAdapter(new ArrayWheelAdapter(mOptionsItems));
wheelView.setOnItemSelectedListener(index -> {
    Toast.makeText(this, mOptionsItems.get(index), Toast.LENGTH_SHORT).show();
});

性能优化建议

  1. 避免在滚动监听中执行复杂计算
  2. 大数据集时考虑分页加载
  3. 适当使用setItemVisibleCount减少绘制项
  4. 自定义布局时避免过度嵌套

总结与未来展望

Android-PickerView通过优雅的Builder模式和模块化设计,为Android开发者提供了高质量的滚轮选择解决方案。本文详细介绍了其核心功能、高级定制及最佳实践,涵盖了从基础使用到性能优化的各个方面。

项目虽已停止更新,但现有功能稳定可靠,建议下载源码后根据需求进行定制。未来可考虑扩展的方向:

  • Kotlin扩展与协程支持
  • Jetpack Compose版本实现
  • 增加更多交互反馈动画
  • 支持数据预加载与缓存

完整示例代码可参考MainActivity.java,包含所有功能的演示实现。希望本文能帮助你打造出更优质的用户体验,让你的App在细节处脱颖而出。

如果觉得本文对你有帮助,请点赞收藏,关注作者获取更多Android UI实战技巧!

【免费下载链接】Android-PickerView 【免费下载链接】Android-PickerView 项目地址: https://gitcode.com/gh_mirrors/and/Android-PickerView

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值