版权声明:本文为HaiyuKing原创文章,转载请注明出处!

前言

本文主要演示Android-PickerView的选项选择器、时间选择器的简单运用。由于每一个版本略有不用,所以实际使用方式以github项目wiki文档为准。

效果图

    

代码分析

本文使用的版本是compile 'com.contrarywind:Android-PickerView:4.1.4';

时间选择器搭配DateTimeHelper使用;

需要执行setDecorView方法,否则底部虚拟导航栏会显示在弹出的选择器区域;

使用步骤

一、项目组织结构图

注意事项:

1、  导入类文件后需要change包名以及重新import R文件路径

2、  Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖

二、导入步骤

在APP中的bundle.gradle文件中添加以下代码,引入Android-PickerView控件

apply plugin: 'com.android.application'

android {
compileSdkVersion 27
defaultConfig {
applicationId "com.why.project.pickerviewdemo"
minSdkVersion 16
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
} dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' //PickerView
compile 'com.contrarywind:Android-PickerView:4.1.4'
}

三、使用方法

在colors.xml文件中添加以下代码

<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color> <!-- **************************pickerview选择器常用颜色值********************************** -->
<color name="pickerview_divider_color">#9D9D9D</color>
<color name="pickerview_cancel_text_color">#979696</color>
<color name="pickerview_submit_text_color">#FAA359</color>
<color name="pickerview_title_text_color">#1A78EC</color>
<color name="pickerview_center_text_color">#333333</color>
</resources>

布局文件

需要以RelativeLayout为根布局(LinearLayout不合适,其他的比如FrameLayout可能可以,需要尝试),主要用于setDecorView方法。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_rootview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"> <LinearLayout
android:id="@+id/optionsPickerLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_margin="10dp"> <!-- 选择爱好 -->
<TextView
android:id="@+id/hobbyTv"
android:layout_width="0.0dp"
android:layout_weight="1"
android:layout_height="38dp"
android:gravity="center_vertical"
android:text="选择爱好"
android:textSize="16sp"
android:textColor="#3090d9"
android:drawableRight="@drawable/pickerview_jiantou"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:background="#E7E7E7"
android:layout_marginRight="10dp"
/> <!-- 选择地址 -->
<TextView
android:id="@+id/addressTv"
android:layout_width="0.0dp"
android:layout_weight="1"
android:layout_height="38dp"
android:gravity="center_vertical"
android:text="选择地址"
android:textSize="16sp"
android:textColor="#3090d9"
android:drawableRight="@drawable/pickerview_jiantou"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:background="#E7E7E7"
/> </LinearLayout> <!-- 开始时间 -->
<TextView
android:id="@+id/startdateTv"
android:layout_alignLeft="@+id/optionsPickerLayout"
android:layout_below="@+id/optionsPickerLayout"
android:layout_width="wrap_content"
android:layout_height="38dp"
android:gravity="center_vertical"
android:text="开始日期"
android:textSize="16sp"
android:textColor="#3090d9"
android:drawableLeft="@drawable/date_icon"
android:drawablePadding="5dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:layout_marginTop="10dp"
android:background="#E7E7E7"
/> </RelativeLayout>

MainActivity

黄色标记的是选项选择器常规写法;

橙色标记的是选项选择器常规之外的实现文本滑动的效果;

package com.why.project.pickerviewdemo;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.method.ScrollingMovementMethod;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast; import com.bigkoo.pickerview.builder.OptionsPickerBuilder;
import com.bigkoo.pickerview.builder.TimePickerBuilder;
import com.bigkoo.pickerview.listener.OnOptionsSelectListener;
import com.bigkoo.pickerview.listener.OnTimeSelectListener;
import com.bigkoo.pickerview.view.OptionsPickerView;
import com.bigkoo.pickerview.view.TimePickerView;
import com.why.project.pickerviewdemo.bean.SpinnearBean;
import com.why.project.pickerviewdemo.util.DateTimeHelper; import org.json.JSONArray;
import org.json.JSONObject; import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date; public class MainActivity extends AppCompatActivity { private TextView hobbyTv;//选择爱好
/**爱好列表集合*/
private ArrayList<SpinnearBean> mHobbyList;
private ArrayList<String> mHobbyNameList;//用于选择器显示
private OptionsPickerView mHobbyPickerView;//选择器 private TextView addressTv;//选择地址
/**地址列表集合*/
private ArrayList<SpinnearBean> mAddressList;
private ArrayList<String> mAddressNameList;//用于选择器显示
private OptionsPickerView mAddressPickerView;//选择器 private TextView startdateTv;//开始日期
private TimePickerView mStartDatePickerView; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); initViews();
initDatas();
initEvents();
} private void initViews() {
hobbyTv = findViewById(R.id.hobbyTv);
addressTv = (TextView) findViewById(R.id.addressTv);
//实现文本区域可滑动的效果,用于当显示的文本过长时
addressTv.setMovementMethod(ScrollingMovementMethod.getInstance());//实现可滑动,但是和ScrollView滑动冲突,需要处理下
//https://blog.csdn.net/qq_36070190/article/details/70053228
addressTv.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if(event.getAction()==MotionEvent.ACTION_DOWN){
//通知父控件不要干扰
v.getParent().requestDisallowInterceptTouchEvent(true);
}
if(event.getAction()==MotionEvent.ACTION_MOVE){
//通知父控件不要干扰
v.getParent().requestDisallowInterceptTouchEvent(true);
}
if(event.getAction()==MotionEvent.ACTION_UP){
v.getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
}
});
startdateTv = findViewById(R.id.startdateTv);
} private void initDatas() {
//========================================初始化爱好列表集合========================================
mHobbyList = new ArrayList<SpinnearBean>();
mHobbyNameList = new ArrayList<String>(); //模拟获取数据集合
try{
mHobbyList = parseJsonArray("spinners.txt");
}catch (Exception e) {
e.printStackTrace();
}
for(SpinnearBean spinnearBean : mHobbyList){
mHobbyNameList.add(spinnearBean.getParaName());
} //============初始化选择器============
initHobbyOptionPicker();
//如果想要直接赋值的话,这样写
/*if(mHobbyNameList.size() > 0){
hobbyTv.setText(mHobbyNameList.get(0));//默认展现第一个
}*/ //========================================初始化地址列表集合========================================
mAddressList = new ArrayList<SpinnearBean>();
mAddressNameList = new ArrayList<String>();
//模拟获取数据集合
try{
mAddressList = parseJsonArray("spinners2.txt");
}catch (Exception e) {
e.printStackTrace();
}
for(SpinnearBean spinnearBean : mAddressList){
mAddressNameList.add(spinnearBean.getParaName());
}
//============初始化选择器============
initAddressOptionPicker();
//当选择器列表项文本过长时,直接赋值的话,会有问题:高度变小了。不太明白什么原因,所以需要延迟设置文本,实际过程中因为有网络请求,所以一般没有问题
/*new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if(mAddressNameList.size() > 0){
addressTv.setText(mAddressNameList.get(0));//默认展现第一个
}
}
}, 500);*/ //========================================初始化开始日期选择器控件========================================
initStartTimePicker();//初始化开始日期选择器控件
} //初始化爱好选择器
private void initHobbyOptionPicker() {
mHobbyPickerView = new OptionsPickerBuilder(MainActivity.this, new OnOptionsSelectListener() {
@Override
public void onOptionsSelect(int options1, int option2, int options3, View v) {
//返回的分别是三个级别的选中位置
String tx = mHobbyNameList.get(options1);
hobbyTv.setText(tx);
}
})
.setDecorView((RelativeLayout)findViewById(R.id.activity_rootview))//必须是RelativeLayout,不设置setDecorView的话,底部虚拟导航栏会显示在弹出的选择器区域
.setTitleText("选择爱好")//标题文字
.setTitleSize(20)//标题文字大小
.setTitleColor(getResources().getColor(R.color.pickerview_title_text_color))//标题文字颜色
.setCancelText("取消")//取消按钮文字
.setCancelColor(getResources().getColor(R.color.pickerview_cancel_text_color))//取消按钮文字颜色
.setSubmitText("确定")//确认按钮文字
.setSubmitColor(getResources().getColor(R.color.pickerview_submit_text_color))//确定按钮文字颜色
.setContentTextSize(20)//滚轮文字大小
.setTextColorCenter(getResources().getColor(R.color.pickerview_center_text_color))//设置选中文本的颜色值
.setLineSpacingMultiplier(1.8f)//行间距
.setDividerColor(getResources().getColor(R.color.pickerview_divider_color))//设置分割线的颜色
.setSelectOptions(0)//设置选择的值
.build(); mHobbyPickerView.setPicker(mHobbyNameList);//添加数据
} //初始化地址选择器
private void initAddressOptionPicker() {
mAddressPickerView = new OptionsPickerBuilder(MainActivity.this, new OnOptionsSelectListener() {
@Override
public void onOptionsSelect(int options1, int option2, int options3, View v) {
//返回的分别是三个级别的选中位置
String tx = mAddressNameList.get(options1);
addressTv.setText(tx);
}
})
.setDecorView((RelativeLayout)findViewById(R.id.activity_rootview))//必须是RelativeLayout,不设置setDecorView的话,底部虚拟导航栏会显示在弹出的选择器区域
.setTitleText("选择地址")//标题文字
.setTitleSize(20)//标题文字大小
.setTitleColor(getResources().getColor(R.color.pickerview_title_text_color))//标题文字颜色
.setCancelText("取消")//取消按钮文字
.setCancelColor(getResources().getColor(R.color.pickerview_cancel_text_color))//取消按钮文字颜色
.setSubmitText("确定")//确认按钮文字
.setSubmitColor(getResources().getColor(R.color.pickerview_submit_text_color))//确定按钮文字颜色
.setContentTextSize(20)//滚轮文字大小
.setTextColorCenter(getResources().getColor(R.color.pickerview_center_text_color))//设置选中文本的颜色值
.setLineSpacingMultiplier(1.8f)//行间距
.setDividerColor(getResources().getColor(R.color.pickerview_divider_color))//设置分割线的颜色
.setSelectOptions(0)//设置选择的值
.build(); mAddressPickerView.setPicker(mAddressNameList);//添加数据
} /**初始化开始日期选择器控件*/
private void initStartTimePicker() {
//控制时间范围(如果不设置范围,则使用默认时间1900-2100年,此段代码可注释)
//因为系统Calendar的月份是从0-11的,所以如果是调用Calendar的set方法来设置时间,月份的范围也要是从0-11
Calendar selectedDate = Calendar.getInstance();
//设置最小日期和最大日期
Calendar startDate = Calendar.getInstance();
try {
startDate.setTime(DateTimeHelper.parseStringToDate("1970-01-01"));//设置为2006年4月28日
} catch (ParseException e) {
e.printStackTrace();
}
Calendar endDate = Calendar.getInstance();//最大日期是今天 //时间选择器
mStartDatePickerView = new TimePickerBuilder(MainActivity.this, new OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date, View v) {//选中事件回调
// 这里回调过来的v,就是show()方法里面所添加的 View 参数,如果show的时候没有添加参数,v则为null
startdateTv.setText(DateTimeHelper.formatToString(date,"yyyy-MM-dd"));
}
})
.setDecorView((RelativeLayout)findViewById(R.id.activity_rootview))//必须是RelativeLayout,不设置setDecorView的话,底部虚拟导航栏会显示在弹出的选择器区域
//年月日时分秒 的显示与否,不设置则默认全部显示
.setType(new boolean[]{true, true, true, false, false, false})
.setLabel("", "", "", "", "", "")
.isCenterLabel(false)//是否只显示中间选中项的label文字,false则每项item全部都带有label。
.setTitleText("开始日期")//标题文字
.setTitleSize(20)//标题文字大小
.setTitleColor(getResources().getColor(R.color.pickerview_title_text_color))//标题文字颜色
.setCancelText("取消")//取消按钮文字
.setCancelColor(getResources().getColor(R.color.pickerview_cancel_text_color))//取消按钮文字颜色
.setSubmitText("确定")//确认按钮文字
.setSubmitColor(getResources().getColor(R.color.pickerview_submit_text_color))//确定按钮文字颜色
.setContentTextSize(20)//滚轮文字大小
.setTextColorCenter(getResources().getColor(R.color.pickerview_center_text_color))//设置选中文本的颜色值
.setLineSpacingMultiplier(1.8f)//行间距
.setDividerColor(getResources().getColor(R.color.pickerview_divider_color))//设置分割线的颜色
.setRangDate(startDate, endDate)//设置最小和最大日期
.setDate(selectedDate)//设置选中的日期
.build();
} private void initEvents() {
//选择爱好的下拉菜单点击事件
hobbyTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mHobbyPickerView.show();
}
}); //选择地址的下拉菜单点击事件
addressTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mAddressPickerView.show();
}
}); //开始日期的下拉菜单点击事件
startdateTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mStartDatePickerView.show();
}
});
} /*===========读取assets目录下的js字符串文件(js数组和js对象),然后生成List集合===========*/
public static final String LISTROOTNODE = "spinnerList";
public static final String KEY_LISTITEM_NAME = "paraName";
public static final String KEY_LISTITEM_VALUE = "paraValue";
public static final String KEY_LISTITEM_CHECKCOLOR = "checkColor"; /**
* 解析JSON文件的简单数组
*/
private ArrayList<SpinnearBean> parseJsonArray(String fileName) throws Exception{ ArrayList<SpinnearBean> itemsList = new ArrayList<SpinnearBean>(); String jsonStr = getStringFromAssert(MainActivity.this, fileName);
if(jsonStr.equals("")){
return null;
}
JSONObject allData = new JSONObject(jsonStr); //全部内容变为一个项
JSONArray jsonArr = allData.getJSONArray(LISTROOTNODE); //取出数组
for(int x = 0;x<jsonArr.length();x++){
SpinnearBean model = new SpinnearBean();
JSONObject jsonobj = jsonArr.getJSONObject(x);
model.setParaName(jsonobj.getString(KEY_LISTITEM_NAME));
model.setParaValue(jsonobj.getString(KEY_LISTITEM_VALUE));
if(jsonobj.has(KEY_LISTITEM_CHECKCOLOR)){
model.setCheckColor(jsonobj.getString(KEY_LISTITEM_CHECKCOLOR));
}
model.setSelectedState(false);
itemsList.add(model);
model = null;
}
return itemsList;
} /**
* 访问assets目录下的资源文件,获取文件中的字符串
* @param filePath - 文件的相对路径,例如:"listdata.txt"或者"/www/listdata.txt"
* @return 内容字符串
* */
public String getStringFromAssert(Context mContext, String filePath) { String content = ""; // 结果字符串
try {
InputStream is = mContext.getResources().getAssets().open(filePath);// 打开文件
int ch = 0;
ByteArrayOutputStream out = new ByteArrayOutputStream(); // 实现了一个输出流
while ((ch = is.read()) != -1) {
out.write(ch); // 将指定的字节写入此 byte 数组输出流
}
byte[] buff = out.toByteArray();// 以 byte 数组的形式返回此输出流的当前内容
out.close(); // 关闭流
is.close(); // 关闭流
content = new String(buff, "UTF-8"); // 设置字符串编码
} catch (Exception e) {
Toast.makeText(mContext, "对不起,没有找到指定文件!", Toast.LENGTH_SHORT)
.show();
}
return content;
}
}

混淆配置

参考资料

Android-PickerView

Android项目总结(二)仿IOS效果的日期选择器和省市县三级联动

完美解决ScrollView与内部嵌套的TextView滚动冲突

项目demo下载地址

https://github.com/haiyuKing/PickerViewDemo

Android-PickerView【仿iOS的PickerView控件,并封装了时间选择和选项选择这两种选择器】使用的更多相关文章

  1. android 开发进阶 自定义控件-仿ios自动清除控件

    先上图: 开发中经常需要自定义view控件或者组合控件,某些控件可能需要一些额外的配置.比如自定义一个标题栏,你可能需要根据不同尺寸的手机定制不同长度的标题栏,或者更常见的你需要配置标题栏的背景,这时 ...

  2. Qt如何去掉按钮等控件的虚线框(焦点框)(两种方法)

    方法1:可以通过代码ui->pushButton->setFocusPolicy(Qt::NoFocus)或在Qt Creator的属性列表中设置. 方法2:如果在嵌入式设备中需要通过按键 ...

  3. 处理事件的方式:两种类的覆盖处理(自己管理,覆盖专用事件函数;自己统一管理,覆盖QWidget::Event通用函数),一种对象的处理(父控件统一管理,即安装过滤器),两种全局处理(QCoreApplication安装过滤器;覆盖notify方法)

    虽然只有一句话,但却是我自己的心得. 特别注意,bool QCoreApplication::notify(QObject *receiver, QEvent *event) 明确指明了要发送的对象, ...

  4. Android——spinner控件实现读取xml资源,省、市两级互动

    (1)首先在res文件夹下面的values中创建一个省市arrays.xml文件夹,如下 <?xml version="1.0" encoding="utf-8&q ...

  5. (转载) Android 带清除功能的输入框控件ClearEditText,仿IOS的输入框

    Android 带清除功能的输入框控件ClearEditText,仿IOS的输入框 标签: Android清除功能EditText仿IOS的输入框 2013-09-04 17:33 70865人阅读  ...

  6. Android开发技巧——定制仿微信图片裁剪控件

    拍照--裁剪,或者是选择图片--裁剪,是我们设置头像或上传图片时经常需要的一组操作.上篇讲了Camera的使用,这篇讲一下我对图片裁剪的实现. 背景 下面的需求都来自产品. 裁剪图片要像微信那样,拖动 ...

  7. (转载)Android UI设计之AlertDialog弹窗控件

    Android UI设计之AlertDialog弹窗控件 作者:qq_27630169 字体:[增加 减小] 类型:转载 时间:2016-08-18我要评论 这篇文章主要为大家详细介绍了Android ...

  8. iOS基础UI控件介绍-Swift版

    iOS基础UI控件总结 iOS基础控件包括以下几类: 1.继承自NSObject:(暂列为控件) UIColor //颜色 UIImage //图像 2.继承自UIView: 只能相应手势UIGest ...

  9. 从0到1搭建移动App功能自动化测试平台(2):操作iOS应用的控件

    转自:http://debugtalk.com/post/build-app-automated-test-platform-from-0-to-1-Appium-interrogate-iOS-UI ...

随机推荐

  1. 【BZOJ 2004】: [Hnoi2010]Bus 公交线路

    题目链接: TP 题解:   所以说,超显眼的数据范围啊. 很显然我们对于每个P的区间都是要有k个站被bus停留,然后考虑转移的话应该是把这k个站里的某个bus往前走,那么转移也很显然了,n的范围很大 ...

  2. bzoj 2820 莫比乌斯反演

    搞了一整个晚自习,只是看懂了dalao们的博客,目前感觉没有思路-.还是要多切题 next day: 刚才又推了一遍,发现顺过来了,hahaha #include<cstdio> #inc ...

  3. BZOJ_4443_[Scoi2015]小凸玩矩阵_二分+二分图匹配

    BZOJ_4443_[Scoi2015]小凸玩矩阵_二分+二分图匹配 Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个 ...

  4. 查询APP Store已发布过的版本记录

    1.国内APP使用 酷传 搜索,即可查询到版本记录 2.国外的APP 无法通过国内软件进行搜索,可在App store中直接查询.步骤如下:

  5. Vue学习小结(一)安装依赖与数据来源

    不多说啥了,生活中都是各种阵痛与惊喜.最近在学习vue框架,刚写完一个小型的后台管理系统(https://github.com/michaelzhengzm/info-manager-systerm_ ...

  6. MySQL 数据库字符集 utf8 和 utf8mb4 的区别

    参考于今日头条上Java芋道源码的-----记住:永远不要在 MySQL 中使用 UTF-8 字符集选择 MySQL 的 utf8 实际上不是真正的 UTF-8.utf8 只支持每个字符最多三个字节, ...

  7. netty 之 telnet HelloWorld 详解

    前言 Netty是 一个异步事件驱动的网络应用程序框架, 用于快速开发可维护的高性能协议服务器和客户端. etty是一个NIO客户端服务器框架,可以快速轻松地开发协议服务器和客户端等网络应用程序.它极 ...

  8. ORM 开发环境之利器:MVC 中间件 FreeSql.AdminLTE

    前言 这是一篇纯技术干货的分享文章,FreeSql 已经基本完成 .NETCore 最方便的 ORM 使命,我们正在筹备生态的建立,比如 ABP 中如何使用 FreeSql 的实现,需要各种各样的扩展 ...

  9. 我们一起来排序——使用Java语言优雅地实现常用排序算法

    破阵子·春景 燕子来时新社,梨花落后清明. 池上碧苔三四点,叶底黄鹂一两声.日长飞絮轻. 巧笑同桌伙伴,上学径里逢迎. 疑怪昨宵春梦好,元是今朝Offer拿.笑从双脸生. 排序算法--最基础的算法,互 ...

  10. python 生成 1900-2100 的二十四节气文件

    [学习笔记] 转载 #!/usr/bin/python3.7# -*- coding:utf-8 -*- '''整体思路1:根据公式算出节气日期 1900 年到 2100  200 年的时间2:特殊的 ...