Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: Change time separator in standard TimePicker?

How do I change the time separator from the standard . to a : in an android app? I am using minSDK 15, and targetSDK 20.

time separator

like image 372
bjar-bjar Avatar asked Feb 12 '23 17:02

bjar-bjar


1 Answers

This answer talks about the TimePicker class as the OP specifies that as a requirement in the bounty and has additions as the element got a bit of a code rework with the release of Android 5/Lollipop.


How to do it?

The divider text cannot be simply modified using a single simple call. The divider text is internally set in TimePicker.setDividerText() which is a private method meaning it can't be overridden either. To make it even harder, the divider textview variable mDivider is set as private as well meaning we don't have direct access to the divider textview.

A simple solution to the problem is to simply override the value after it gets set by the constructor. To do this, we create our own subclass of TimePicker, try to find the divider and set its value. This will work fine as long as the layout matches the AOSP one. looks at OEM skins and shrugs

See source of the android.widget.TimePicker class as reference. Assuming the android-l-preview_r2 tag is being investigated, check line 91 for the declaration of the mDivider variable and lines 531-553 for the setDividerText() method.

In practice, please?

import android.content.Context;
import android.content.res.Resources;
import android.util.AttributeSet;
import android.widget.TextView;
import android.widget.TimePicker;

public class CustomTimePicker extends TimePicker {
    public CustomTimePicker(Context context) {
        super(context);
        init();
    }

    public CustomTimePicker(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CustomTimePicker(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        TextView divider = (TextView) findViewById(Resources.getSystem()
                .getIdentifier("divider", "id", "android"));
        // the divider doesn't exist in the old-school widget style
        if (divider != null) {
            divider.setText(":");
        }
    }
}

That's not working on Android L!

The described method was valid for KitKat, but is no longer good to use when compiling against L. If you check TimePicker on android-5.0.0_r2, you will find that handling of the style is offloaded to a seperate delegate class. The TimePickerClockDelegate class seems to be the one that resembles the legacy picker.

The issues about private variables and methods still stands on Android 5.0.0 and the new structuring complicates things a bunch more. If you still believe you want to break localization (see the Should you do it? section below), you will probably be best off using a custom TimePicker implementation. A good starting point might be picking the new TimePicker and TimePickerClockDelegate classes, merging them and cutting out the abstraction layer and modifying the divider text setting code as was done in the KitKat version. Regardless, that goes beyond the scope of a simple and helpful answer as taking that route will produce many side effects, such as breaking system-wide themeability, and should really be considered wisely.


Should you do it?

Not really.

The TimePicker is actually going to pick the : character as the default divider in case anything goes wrong, but it will prefer the localized variation above everything.

This means that if the locale you are using prefers to write the time as HH:mm, the picker will automatically use : as the divider, but if your locale uses HH.mm then the picker will simply use . as the divider. If there was a locale that would write the time in the format of HH/mm, the picker would automatically adapt and use / as the divider to provide consistency with the local formatting (aka localization).

If you feel like you must override this behavior, you can use the method described above, but keep in mind doing so goes against localization and even consistency across various applications.

like image 135
Valter Jansons Avatar answered Feb 24 '23 00:02

Valter Jansons