Android-PickerView【仿iOS的PickerView控件,並封裝了時間選擇和選項選擇這兩種選擇器】使用

版權聲明:本文爲HaiyuKing原創文章,轉載請註明出處!html

前言

本文主要演示Android-PickerView的選項選擇器、時間選擇器的簡單運用。因爲每個版本略有不用,因此實際使用方式以github項目wiki文檔爲準。java

效果圖

     

代碼分析

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

時間選擇器搭配DateTimeHelper使用;git

須要執行setDecorView方法,不然底部虛擬導航欄會顯示在彈出的選擇器區域;github

使用步驟

1、項目組織結構圖

注意事項:json

一、  導入類文件後須要change包名以及從新import R文件路徑數組

二、  Values目錄下的文件(strings.xml、dimens.xml、colors.xml等),若是項目中存在,則複製裏面的內容,不要整個覆蓋網絡

2、導入步驟

在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'
}

3、使用方法

在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方法。app

<?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

黃色標記的是選項選擇器常規寫法;ide

橙色標記的是選項選擇器常規以外的實現文本滑動的效果;

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 

相關文章
相關標籤/搜索