回答編集履歴

5

API17以降でクラッシュする問題への対策でコード修正

2019/11/25 23:56

投稿

kakajika
kakajika

スコア3131

test CHANGED
@@ -70,7 +70,11 @@
70
70
 
71
71
  }
72
72
 
73
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
74
+
73
- applyOverrideConfiguration(configuration);
75
+ applyOverrideConfiguration(configuration);
76
+
77
+ }
74
78
 
75
79
 
76
80
 

4

ソースコードの改善

2019/11/25 23:56

投稿

kakajika
kakajika

スコア3131

test CHANGED
@@ -30,47 +30,39 @@
30
30
 
31
31
  public CustomLocaleTimePicker(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
32
32
 
33
- super(getContextForLocale(context, Locale.US), attrs, defStyleAttr);
33
+ super(new ContextLocaleWrapper(context, Locale.US), attrs, defStyleAttr);
34
34
 
35
35
 
36
36
 
37
- // N未満で書き換えたLocaleのデフォルト値を元に戻す
38
-
39
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N && defaultLocale != null) {
40
-
41
- Locale.setDefault(defaultLocale);
37
+ ((ContextLocaleWrapper) getContext()).resetDefaultLocale();
42
-
43
- }
44
38
 
45
39
  }
46
40
 
47
41
 
48
42
 
49
- private static Locale defaultLocale;
43
+ private static class ContextLocaleWrapper extends ContextThemeWrapper {
50
44
 
51
45
 
52
46
 
53
- private static Context getContextForLocale(@NonNull Context context, @NonNull Locale locale) {
47
+ @Nullable
54
48
 
55
- // N未満ではLocaleのデフォルト値を参照してしまうので対策
56
-
57
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
58
-
59
- defaultLocale = Locale.getDefault();
49
+ private Locale defaultLocale = null;
60
-
61
- Locale.setDefault(locale);
62
-
63
- }
64
50
 
65
51
 
66
52
 
67
- Configuration configuration = new Configuration(context.getResources().getConfiguration());
53
+ private ContextLocaleWrapper(Context context, Locale locale) {
68
54
 
55
+ super(context, context.getTheme());
56
+
57
+
58
+
69
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
59
+ Configuration configuration = new Configuration(context.getResources().getConfiguration());
70
60
 
71
61
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
72
62
 
73
63
  configuration.setLocale(locale);
64
+
65
+ configuration.setLayoutDirection(locale);
74
66
 
75
67
  } else {
76
68
 
@@ -78,24 +70,38 @@
78
70
 
79
71
  }
80
72
 
81
- return new ContextThemeWrapper(context.createConfigurationContext(configuration), context.getTheme());
73
+ applyOverrideConfiguration(configuration);
82
74
 
83
- } else {
84
75
 
85
- Resources res = context.getResources();
86
76
 
87
- configuration.locale = locale;
77
+ // N未満ではLocaleのデフォルト値を参照してしまうので対策
88
78
 
89
- res.updateConfiguration(configuration, res.getDisplayMetrics());
79
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N && !Locale.getDefault().equals(defaultLocale)) {
90
80
 
81
+ defaultLocale = Locale.getDefault();
82
+
83
+ Locale.setDefault(locale);
84
+
85
+ }
86
+
87
+ }
88
+
89
+
90
+
91
- return new ContextWrapper(context);
91
+ public void resetDefaultLocale() {
92
+
93
+ // N未満で書き換えたLocaleのデフォルト値を元に戻す
94
+
95
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N && defaultLocale != null) {
96
+
97
+ Locale.setDefault(defaultLocale);
98
+
99
+ }
92
100
 
93
101
  }
94
102
 
95
103
  }
96
104
 
97
-
98
-
99
105
  }
100
106
 
101
107
  ```

3

styleやthemeを正しく引き継げるようコード修正

2019/08/02 11:42

投稿

kakajika
kakajika

スコア3131

test CHANGED
@@ -22,7 +22,7 @@
22
22
 
23
23
  public CustomLocaleTimePicker(Context context, @Nullable AttributeSet attrs) {
24
24
 
25
- this(context, attrs, 0);
25
+ this(context, attrs, Resources.getSystem().getIdentifier("timePickerStyle", "attr", "android"));
26
26
 
27
27
  }
28
28
 
@@ -32,9 +32,11 @@
32
32
 
33
33
  super(getContextForLocale(context, Locale.US), attrs, defStyleAttr);
34
34
 
35
+
36
+
37
+ // N未満で書き換えたLocaleのデフォルト値を元に戻す
38
+
35
39
  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N && defaultLocale != null) {
36
-
37
- // N未満で書き換えたLocaleのデフォルト値を元に戻す
38
40
 
39
41
  Locale.setDefault(defaultLocale);
40
42
 
@@ -50,9 +52,9 @@
50
52
 
51
53
  private static Context getContextForLocale(@NonNull Context context, @NonNull Locale locale) {
52
54
 
55
+ // N未満ではLocaleのデフォルト値を参照してしまうので対策
56
+
53
57
  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
54
-
55
- // N未満ではLocaleのデフォルト値を参照してしまうので対策
56
58
 
57
59
  defaultLocale = Locale.getDefault();
58
60
 
@@ -76,7 +78,7 @@
76
78
 
77
79
  }
78
80
 
79
- return new ContextWrapper(context.createConfigurationContext(configuration));
81
+ return new ContextThemeWrapper(context.createConfigurationContext(configuration), context.getTheme());
80
82
 
81
83
  } else {
82
84
 

2

説明の修正

2019/07/31 15:52

投稿

kakajika
kakajika

スコア3131

test CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
 
5
- **追記**: Android N以前ではLocale.getDefault()の値を書き換える必要があったので、それに対する対策コードも追記しました。TimePickerの代わりにCustomLocaleTimePickerをxml内に埋め込む等して利用してください。
5
+ **追記**: Android N未満ではLocale.getDefault()の値を書き換える必要があったので、それに対する対策コードも追記しました。TimePickerの代わりにCustomLocaleTimePickerをxml内に埋め込む等して利用してください。
6
6
 
7
7
 
8
8
 
@@ -30,7 +30,7 @@
30
30
 
31
31
  public CustomLocaleTimePicker(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
32
32
 
33
- super(getContextForLocale(context, Locale.JAPAN), attrs, defStyleAttr);
33
+ super(getContextForLocale(context, Locale.US), attrs, defStyleAttr);
34
34
 
35
35
  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N && defaultLocale != null) {
36
36
 

1

N未満でのコードの問題修正、カスタムViewの実装例追加

2019/07/31 03:42

投稿

kakajika
kakajika

スコア3131

test CHANGED
@@ -1,39 +1,99 @@
1
1
  AndroidのViewはContextが保持している [Configuration](https://developer.android.com/reference/android/content/res/Configuration) というクラスからLocaleの設定を読み込んでいます。このLocaleを変更した状態のContextを生成し、TimePickerの生成時に渡すようにすればOKです。
2
+
3
+
4
+
5
+ **追記**: Android N以前ではLocale.getDefault()の値を書き換える必要があったので、それに対する対策コードも追記しました。TimePickerの代わりにCustomLocaleTimePickerをxml内に埋め込む等して利用してください。
2
6
 
3
7
 
4
8
 
5
9
  ```java
6
10
 
7
- // Localeを変更したContextを生成する
11
+ public class CustomLocaleTimePicker extends TimePicker {
8
12
 
9
- public Context getContextForLocale(Context context, Locale locale) {
10
13
 
11
- Configuration configuration = context.getResources().getConfiguration();
12
14
 
13
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
15
+ public CustomLocaleTimePicker(Context context) {
14
16
 
15
- configuration.setLocale(locale);
16
-
17
- return new ContextWrapper(context.createConfigurationContext(configuration));
18
-
19
- } else {
20
-
21
- Resources res = context.getResources();
22
-
23
- configuration.locale = locale;
24
-
25
- res.updateConfiguration(configuration, res.getDisplayMetrics());
26
-
27
- return new ContextWrapper(context);
17
+ this(context, null);
28
18
 
29
19
  }
30
20
 
21
+
22
+
23
+ public CustomLocaleTimePicker(Context context, @Nullable AttributeSet attrs) {
24
+
25
+ this(context, attrs, 0);
26
+
31
- }
27
+ }
32
28
 
33
29
 
34
30
 
35
- // 使用例
31
+ public CustomLocaleTimePicker(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
36
32
 
37
- new TimePicker(getContextForLocale(context, Locale.US));
33
+ super(getContextForLocale(context, Locale.JAPAN), attrs, defStyleAttr);
34
+
35
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N && defaultLocale != null) {
36
+
37
+ // N未満で書き換えたLocaleのデフォルト値を元に戻す
38
+
39
+ Locale.setDefault(defaultLocale);
40
+
41
+ }
42
+
43
+ }
44
+
45
+
46
+
47
+ private static Locale defaultLocale;
48
+
49
+
50
+
51
+ private static Context getContextForLocale(@NonNull Context context, @NonNull Locale locale) {
52
+
53
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
54
+
55
+ // N未満ではLocaleのデフォルト値を参照してしまうので対策
56
+
57
+ defaultLocale = Locale.getDefault();
58
+
59
+ Locale.setDefault(locale);
60
+
61
+ }
62
+
63
+
64
+
65
+ Configuration configuration = new Configuration(context.getResources().getConfiguration());
66
+
67
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
68
+
69
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
70
+
71
+ configuration.setLocale(locale);
72
+
73
+ } else {
74
+
75
+ configuration.locale = locale;
76
+
77
+ }
78
+
79
+ return new ContextWrapper(context.createConfigurationContext(configuration));
80
+
81
+ } else {
82
+
83
+ Resources res = context.getResources();
84
+
85
+ configuration.locale = locale;
86
+
87
+ res.updateConfiguration(configuration, res.getDisplayMetrics());
88
+
89
+ return new ContextWrapper(context);
90
+
91
+ }
92
+
93
+ }
94
+
95
+
96
+
97
+ }
38
98
 
39
99
  ```