关闭

Android 实现自定义时间间隔,文字颜色的TimePicker

标签: TimePicker时间间隔自定义样式文字颜色
2906人阅读 评论(0) 收藏 举报
分类:

最近项目中有个要求,要求实现一个时间设置控件,要求可以设置的时间间隔为15分钟。怎么实现呢?

首先,Android自带了一个TimePicker控件,但是其默认时间间隔为1分钟,而且没有提供修改间隔的接口。

一、怎么解决自定义时间间隔的问题呢?

从网上找到了办法,代码参考的是http://download.csdn.net/download/asdlai/6860699
下面的setNumberPickerTextSize(ViewGroup viewGroup)方法就是设置时间间隔的方法,传入的参数为要设置时间间隔的TimePicker。在合适的地方,一般是onCreate()里调用它即可。

String[] minuts = new String[]{"00","15", "30", "45"};//间隔15的数组,用来表示可设置的分钟值

    /**
     * 得到timePicker里面的android.widget.NumberPicker组件 (有两个android.widget.NumberPicker组件--hour,minute)
     * @param viewGroup
     * @return
     */
    private List<NumberPicker> findNumberPicker(ViewGroup viewGroup)
    {
        List<NumberPicker> npList = new ArrayList<NumberPicker>();
        View child = null;

        if (null != viewGroup)
        {
            for (int i = 0; i < viewGroup.getChildCount(); i++)
            {
                child = viewGroup.getChildAt(i);
                if (child instanceof NumberPicker)
                {
                    npList.add((NumberPicker)child);
                }
                else if (child instanceof LinearLayout)
                {
                    List<NumberPicker> result = findNumberPicker((ViewGroup)child);
                    if (result.size() > 0)
                    {
                        return result;
                    }
                }
            }
        }

        return npList;
    }

    /**
     * 查找timePicker里面的android.widget.NumberPicker组件 ,并对其进行时间间隔设置
     * @param viewGroup  TimePicker timePicker
     */
    private void setNumberPickerTextSize(ViewGroup viewGroup){
        List<NumberPicker> npList = findNumberPicker(viewGroup);
        if (null != npList)
        {
            for (NumberPicker mMinuteSpinner : npList)
            {
//              System.out.println("mMinuteSpinner.toString()="+mMinuteSpinner.toString());
                if(mMinuteSpinner.toString().contains("id/minute")){//对分钟进行间隔设置

                    mMinuteSpinner.setMinValue(0);
                    mMinuteSpinner.setMaxValue(minuts.length-1);
                    mMinuteSpinner.setDisplayedValues(minuts);  //这里的minuts是一个String数组,就是要显示的分钟值
                }
                //对小时进行间隔设置 使用 if(mMinuteSpinner.toString().contains("id/hour")){}即可
            }
        }
    }

这样是不是就完成了呢?我们对这个控件进行操作,取出它的值看看:

        timePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {

            @Override
            //这里传入的hourOfDay为小时值,minute为原分钟值
            public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
                textView.setText("开始时间: "+ hourOfDay +" 时 "+minute + "分");
            }
        });

textView是布局中的一个文本,是为了查看处理结果的,代码就不贴了。
结果:
这里写图片描述
发现值不对,当控件显示为15:30的时候,我们拿到的值却为15:2,这是为什么呢?因为我们修改了时间间隔为15,而原本间隔为1,所以如今我们设置的00相当于原来的00, 15是原来的1, 30是原来的2, 45是原来的3。

那解决办法也简单了,在拿到设置的时间后,分钟值乘以15就可以:

        timePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {

            @Override
            //这里传入的hourOfDay为小时值,minute为原分钟值
            public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
                //在获取设置的时间的地方对分钟值进行处理,乘以15
                textView.setText("开始时间: "+ hourOfDay +" 时 "+minute*15 + "分");
            }
        });

最后效果:
这里写图片描述

二、注意,TimePicker在不同Anddroid版本上运行,其样式是不一样的,

原因见源码TimePicker的构造方法:

    public TimePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);

        final TypedArray a = context.obtainStyledAttributes(
                attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes);
        final int mode = a.getInt(R.styleable.TimePicker_timePickerMode, MODE_SPINNER);
        a.recycle();

        switch (mode) {
            case MODE_CLOCK://这是其中一种样式
                mDelegate = new TimePickerClockDelegate(
                        this, context, attrs, defStyleAttr, defStyleRes);
                break;
            case MODE_SPINNER://这是另一种样式
            default:
                mDelegate = new TimePickerSpinnerDelegate(
                        this, context, attrs, defStyleAttr, defStyleRes);
                break;
        }
    }

其实就是和使用的主题有关,我们应该可以指定Activity或者Application的主题以使得其样式在不同安卓版本上保持一致,但是我在测试的时候发现有些主题和安卓版本不兼容,这就尴尬了。

怎么办呢?
只要在布局文件TimePicker的属性里指定android:timePickerMode属性就可以。
android:timePickerMode=”spinner” 指定TimePicker的样式为上下滑动设置时间。
android:timePickerMode=”clock”指定TimePicker的样式为表盘形状(只在API level 为21以上才行)。下面是表盘形状的TimePicker:
这里写图片描述

另外代码中调用setIs24HourView(true)可以把TimePicker设置为24小时制。

前面处理之后,如果用户想通过键盘输入的方式设置分钟值,就只能输入0,15,30,45了,其它值输入不了。这可能会造成用户困惑,我们可以调用setDescendantFocusability(TimePicker.FOCUS_BLOCK_DESCENDANTS)来禁止用户通过输入的方式设置时间。

三、如果我还想设置这个TimePicker的文字颜色和大小怎么办?


同样在网上找到了方法,亲测可用:
第一种办法:
首先在styles.xml 文件里边加入Theme style,设置所有EditText的颜色(因为TimePicker和DatePicker 使用的基本控件都是EditText)。

    <style name="Theme.picker" parent="android:Theme.Holo.Light">
        <item name="android:editTextStyle">@style/Widget.EditText.White</item>
    </style>

    <style name="Widget.EditText.White" parent="@android:style/Widget.EditText">
        <!--这里是设置颜色和大小的地方-->
        <item name="android:textColor">@color/orange</item>
        <item name="android:textSize">30sp</item>
    </style>

  然后在应用的 AndroidManifest.xml文件中的Activity下边增加属性 android:theme=”@style/Theme.picker”,表示该Acitivity使用该theme. 这样Picker就会显示你设置好的颜色。

    <activity
            android:name="com.example.timewidget.TimeActivity"
            android:label="@string/app_name" 
            android:theme="@style/Theme.picker">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

但是这样设置的话,如果该页面上还有别的EditText,其文字颜色和大小也会被改变。

第二种办法:用下面set_timepicker_text_colour()方法,传入TimePicker对象即可设置文字颜色:

 private void set_timepicker_text_colour(TimePicker time_picker){
        Resources system = Resources.getSystem();
        int hour_numberpicker_id = system.getIdentifier("hour", "id", "android");
        int minute_numberpicker_id = system.getIdentifier("minute", "id", "android");
        int ampm_numberpicker_id = system.getIdentifier("amPm", "id", "android");

        NumberPicker hour_numberpicker = (NumberPicker) time_picker.findViewById(hour_numberpicker_id);
        NumberPicker minute_numberpicker = (NumberPicker) time_picker.findViewById(minute_numberpicker_id);
        NumberPicker ampm_numberpicker = (NumberPicker) time_picker.findViewById(ampm_numberpicker_id);

        set_numberpicker_text_colour(hour_numberpicker);
        set_numberpicker_text_colour(minute_numberpicker);
        set_numberpicker_text_colour(ampm_numberpicker);
    }

    private void set_numberpicker_text_colour(NumberPicker number_picker){
        final int count = number_picker.getChildCount();
        //这里就是要设置的颜色,修改一下作为参数传入会更好
        final int color = getResources().getColor(android.R.color.holo_orange_dark);

        for(int i = 0; i < count; i++){
            View child = number_picker.getChildAt(i);

            try{
                Field wheelpaint_field = number_picker.getClass().getDeclaredField("mSelectorWheelPaint");
                wheelpaint_field.setAccessible(true);

                ((Paint)wheelpaint_field.get(number_picker)).setColor(color);
                ((EditText)child).setTextColor(color);
                number_picker.invalidate();
            }
            catch(NoSuchFieldException e){
                Log.w("setColor", e);
            }
            catch(IllegalAccessException e){
                Log.w("setColor", e);
            }
            catch(IllegalArgumentException e){
                Log.w("setColor", e);
            }
        }
    }

效果:
这里写图片描述

四、如果还觉得这个TimePicker太大了,想改变它大小怎么办?

同样附上代码,只要用之前的方法拿到TimePicker里的每个NumberPicker,然后调用下面的setPickerSize()方法即可:

    //此方法将dp值转换为px值,以保证适配不同分辨率机型
    public static int dp2px(Context context, float dpVal)
    {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, context.getResources().getDisplayMetrics());
    }

    //这个方法是改变NumberPicker大小的方法,传入的参数为要修改的NumberPicker和NumberPicker的宽度值
    private void setPickerSize(NumberPicker np, int widthDpValue) {
        int widthPxValue = dp2px(this, widthDpValue);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(widthPxValue, LinearLayout.LayoutParams.WRAP_CONTENT);
        params.setMargins(0, 0, 0, 0);//这儿参数可根据需要进行更改
        np.setLayoutParams(params);
    }
2
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:52936次
    • 积分:1153
    • 等级:
    • 排名:千里之外
    • 原创:64篇
    • 转载:2篇
    • 译文:0篇
    • 评论:9条
    文章分类
    最新评论