zoukankan      html  css  js  c++  java
  • Android-PickerView【仿iOS的PickerView控件,并封装了时间选择和选项选择这两种选择器】使用

    版权声明:本文为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 

  • 相关阅读:
    不吐不快之EJB演练——开篇概述
    URL重写:RewriteCond指令与RewriteRule 指令格式
    刚到公司有点压力山大,在此希望有大神给点正能量
    053第449题
    选择排序---简单选择排序 堆排序
    bzoj-1492 货币兑换Cash (2)——CDQ分治
    MySQL 提高Insert性能
    Codeforces Round #313 (Div. 2) 560C Gerald&#39;s Hexagon(脑洞)
    Matlab矩阵基础
    Android 带清除功能的输入框控件EditTextWithDel
  • 原文地址:https://www.cnblogs.com/whycxb/p/9163456.html
Copyright © 2011-2022 走看看