2

I have an app that is available in 4 languages, which can be chosen within the app. On Android, the DatePicker has a title. This title, even after setting the locale, always seems to favor the devices set locale. Only the title does this, as the functional part of the DatePicker is in the app-chosen language.

Here is what it looks like when the app is set to Korean.

enter image description here

How do I go about Changing that Thu, Aug 24 to Korean? I've set both Xamarin and Android locale to Korean. Is there an attribute in the Date Picker renderer I can set?

Thanks.

SushiHangover
  • 73,120
  • 10
  • 106
  • 165
Will Nasby
  • 1,068
  • 2
  • 16
  • 39

1 Answers1

4

If you are doing something like this to apply a new locale context base configuration:

protected override void AttachBaseContext(Android.Content.Context @base)
{
    Locale locale = Locale.Korean;
    Locale.SetDefault(Locale.Category.Format, locale);
    @base.Resources.Configuration.SetLocale(locale);
    var newContext = @base.CreateConfigurationContext(@base.Resources.Configuration);
    base.AttachBaseContext(newContext);
}

The Material-design CalendarView does not honor the context's locale correctly from the one that is passed to its .ctor and you end up with the wrong Title localization as shown in your question ;-(

One option is to subclass DatePicker and re-implement DatePickerCalendarDelegate and apply that to a sub-classed AlertDialog, but that is a bit crazy amount of coding to correctly address the issue.

So this is a fix (hack) that I have been using (simplified for SO, so you will need to API the various API level checks, etc..):

Material Design Fix (including Oreo beta):

// globals/cached
bool headerChangeFlag = true;
TextView headerTextView;
string headerDatePatternLocale;
SimpleDateFormat monthDayFormatLocale;

void SetHeaderMonthDay(DatePickerDialog dialog, Locale locale)
{
    if (headerTextView == null)
    {
        // Material Design formatted CalendarView being used, need to do API level check and skip on older APIs
        var id = base.Resources.GetIdentifier("date_picker_header_date", "id", "android");
        headerTextView = dialog.DatePicker.FindViewById<TextView>(id);
        headerDatePatternLocale = Android.Text.Format.DateFormat.GetBestDateTimePattern(locale, "EMMMd");
        monthDayFormatLocale = new SimpleDateFormat(headerDatePatternLocale, locale);
        headerTextView.SetTextColor(Android.Graphics.Color.Red);
        headerTextView.TextChanged += (sender, e) =>
        {
            headerChangeFlag = !headerChangeFlag;
            if (!headerChangeFlag)
                return;
            SetHeaderMonthDay(dialog, locale);
        };
    }
    var selectedDateLocale = monthDayFormatLocale.Format(new Date((long)dialog.DatePicker.DateTime.ToUniversalTime().Subtract(
              new System.DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc)).TotalMilliseconds));
    headerTextView.Text = selectedDateLocale;
}

Usage:

var dialog = new DatePickerDialog(this);
dialog.Show();
SetHeaderMonthDay(dialog, Locale.Korean); // Call once, the text change event will update it when user changes date...

Results:

enter image description here

SushiHangover
  • 73,120
  • 10
  • 106
  • 165
  • 1
    This worked for me. Just to help anyone else avoid confusion, `SimpleDateFormat` is from the namespace `Android.Icu.Text`. It won't work if you use the one from the namespace `Java.Text` – Drake Sep 25 '20 at 17:56
  • Been looking for this for weeks. Thank you very much – nichtwer Mar 13 '21 at 17:32