teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

機能改善

2016/11/30 09:23

投稿

Kmassa
Kmassa

スコア161

answer CHANGED
@@ -41,7 +41,10 @@
41
41
 
42
42
  import android.content.Context;
43
43
  import android.content.res.TypedArray;
44
+ import android.support.v7.widget.AppCompatEditText;
44
45
  import android.util.AttributeSet;
46
+ import android.view.View;
47
+ import android.view.ViewGroup;
45
48
  import android.widget.NumberPicker;
46
49
 
47
50
  /**
@@ -75,6 +78,10 @@
75
78
  }
76
79
 
77
80
  private void initialize(Context context, AttributeSet attrs) {
81
+ if (this.isInEditMode()) {
82
+ return;
83
+ }
84
+
78
85
  // レイアウトで指定された値の取得
79
86
  TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomNumberPicker, 0, 0);
80
87
  try {
@@ -119,6 +126,22 @@
119
126
  super.setMinValue(0);
120
127
  super.setMaxValue(value_num);
121
128
 
129
+ // 一旦最大値を設定
130
+ super.setValue(value_num);
131
+
132
+ for (int i = 0; i < getChildCount(); i++) {
133
+ View view = getChildAt(i);
134
+ if (view.getClass().equals(AppCompatEditText.class) == true) {
135
+ // Text部分のサイズを計算
136
+ int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK, MeasureSpec.AT_MOST);
137
+ view.measure(expandSpec, expandSpec);
138
+
139
+ // Text部分の幅を設定
140
+ ViewGroup.LayoutParams params = view.getLayoutParams();
141
+ params.width = view.getMeasuredWidth();
142
+ }
143
+ }
144
+
122
145
  // 初期表示のindex
123
146
  super.setValue(0);
124
147
  }
@@ -129,6 +152,12 @@
129
152
  return super.getValue();
130
153
  }
131
154
 
155
+ @Override
156
+ public void setValue(int value) {
157
+ // スクロール時に使用されているので、ここに変更は加えない
158
+ super.setValue(value);
159
+ }
160
+
132
161
  public int getDisplayedValue() {
133
162
  // 選択されている値を取得するときは、こちらを呼び出す
134
163
  int pos = super.getValue();
@@ -136,7 +165,8 @@
136
165
  }
137
166
 
138
167
  @Override
139
- public void setValue(int value) {
168
+ public void setDisplayedValue(int value) {
169
+ // プログラム中から表示値の設定をするときは、こちらを呼び出す
140
170
  int pos = 0;
141
171
  while (value > Integer.parseInt(mValueSet[pos])) {
142
172
  pos++;

1

カスタムNumberPickerのサンプル追加

2016/11/30 09:23

投稿

Kmassa
Kmassa

スコア161

answer CHANGED
@@ -14,4 +14,181 @@
14
14
 
15
15
  サンプルは必要ないので、図のようにImportのチェックを外してください。
16
16
 
17
- もしくは、Source directoryにAndroidComponentLibrary-master\ComponentLibraryを指定してください。
17
+ もしくは、Source directoryにAndroidComponentLibrary-master\ComponentLibraryを指定してください。
18
+
19
+ -追記-
20
+ カスタムNumberPickerの作り方
21
+
22
+ まず、res/valuesにxmlファイルを追加します。
23
+ ファイル名は「attr.xml」などとします。
24
+ これにより、レイアウトファイルで指定するパラメータを定義します。
25
+ ```xml
26
+ <?xml version="1.0" encoding="utf-8"?>
27
+ <resources>
28
+ <declare-styleable name="CustomNumberPicker">
29
+ <attr name="step" format="integer" />
30
+ <attr name="min" format="integer" />
31
+ <attr name="max" format="integer" />
32
+ </declare-styleable>
33
+ </resources>
34
+ ```
35
+
36
+ 続いてJava Classを追加します。
37
+ 名前はxmlで指定したものと同じ「CustomNumberPicker」で、
38
+ SuperclassとしてNumberPickerを指定します。
39
+ ```Java
40
+ package xxx;
41
+
42
+ import android.content.Context;
43
+ import android.content.res.TypedArray;
44
+ import android.util.AttributeSet;
45
+ import android.widget.NumberPicker;
46
+
47
+ /**
48
+ * Created by massa on 2016/11/15.
49
+ */
50
+
51
+ public class CustomNumberPicker extends NumberPicker {
52
+
53
+ // 表示用の値のリスト
54
+ private String [] mValueSet;
55
+
56
+ // 最大値・最小値
57
+ private int mMaxValue;
58
+ private int mMinValue;
59
+
60
+ // 刻み幅
61
+ private int mStep;
62
+
63
+ public CustomNumberPicker(Context context) {
64
+ super(context);
65
+ }
66
+
67
+ public CustomNumberPicker(Context context, AttributeSet attrs) {
68
+ super(context, attrs);
69
+ initialize(context, attrs);
70
+ }
71
+
72
+ public CustomNumberPicker(Context context, AttributeSet attrs, int defStyleAttr) {
73
+ super(context, attrs, defStyleAttr);
74
+ initialize(context, attrs);
75
+ }
76
+
77
+ private void initialize(Context context, AttributeSet attrs) {
78
+ // レイアウトで指定された値の取得
79
+ TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomNumberPicker, 0, 0);
80
+ try {
81
+ mStep = typedArray.getInteger(R.styleable.CustomNumberPicker_step, 1);
82
+ mMinValue = typedArray.getInteger(R.styleable.CustomNumberPicker_min, 0);
83
+ mMaxValue = typedArray.getInteger(R.styleable.CustomNumberPicker_max, mMinValue);
84
+ }
85
+ finally {
86
+ typedArray.recycle();
87
+ }
88
+
89
+ setValues();
90
+ }
91
+
92
+ private void setValues() {
93
+ int value_num = 0;
94
+
95
+ // minとmaxが逆だったら入れ替える
96
+ if (mMinValue > mMaxValue) {
97
+ int temp = mMinValue;
98
+ mMinValue = mMaxValue;
99
+ mMaxValue = temp;
100
+ }
101
+
102
+ // min ~ maxに値がいくつ入るか算出
103
+ value_num = (mMaxValue - mMinValue + mStep - 1) / mStep;
104
+
105
+ mValueSet = new String[value_num + 1];
106
+
107
+ // 表示値のリストを作る
108
+ for (int i = 0; i < value_num; i++) {
109
+ mValueSet[i] = String.valueOf(mMinValue + mStep * i);
110
+ }
111
+ mValueSet[value_num] = String.valueOf(mMaxValue);
112
+
113
+ // 表示値の数が変わるので、一旦初期化
114
+ super.setMaxValue(0);
115
+
116
+ setDisplayedValues(mValueSet);
117
+
118
+ // 本来のValueはindexとして使用する
119
+ super.setMinValue(0);
120
+ super.setMaxValue(value_num);
121
+
122
+ // 初期表示のindex
123
+ super.setValue(0);
124
+ }
125
+
126
+ @Override
127
+ public int getValue() {
128
+ // setDisplayedValuesでも使用しているので、ここに変更は加えない
129
+ return super.getValue();
130
+ }
131
+
132
+ public int getDisplayedValue() {
133
+ // 選択されている値を取得するときは、こちらを呼び出す
134
+ int pos = super.getValue();
135
+ return Integer.parseInt(mValueSet[pos]);
136
+ }
137
+
138
+ @Override
139
+ public void setValue(int value) {
140
+ int pos = 0;
141
+ while (value > Integer.parseInt(mValueSet[pos])) {
142
+ pos++;
143
+ }
144
+ super.setValue(pos);
145
+ }
146
+
147
+ @Override
148
+ public int getMinValue() {
149
+ return mMinValue;
150
+ }
151
+
152
+ @Override
153
+ public void setMinValue(int minValue) {
154
+ mMinValue = minValue;
155
+ setValues();
156
+ }
157
+
158
+ @Override
159
+ public int getMaxValue() {
160
+ return mMaxValue;
161
+ }
162
+
163
+ @Override
164
+ public void setMaxValue(int maxValue) {
165
+ mMaxValue = maxValue;
166
+ setValues();
167
+ }
168
+ }
169
+ ```
170
+
171
+ 後は、レイアウトファイルから以下のように使用できると思います。
172
+ ```xml
173
+ <xxx.CustomNumberPicker
174
+ xmlns:custom="http://schemas.android.com/apk/res-auto"
175
+ android:layout_width="wrap_content"
176
+ android:layout_height="wrap_content"
177
+ custom:step="5"
178
+ custom:min="10"
179
+ custom:max="100"
180
+ android:id="@+id/numberPicker"/>
181
+ ```
182
+
183
+ 選択されている値は、以下のように取得できます。
184
+ ```Java
185
+ CustomNumberPicker customNumberPicker = (CustomNumberPicker)findViewById(R.id.numberPicker);
186
+
187
+ int value = customNumberPicker.getDisplayedValue();
188
+ ```
189
+ 当初、getValue()をオーバーライドしてみたのですが、
190
+ setDisplayedValuesの中から呼び出されているようで、表示される値がおかしくなってしまいました。
191
+ なので、getValue()はいじらず、getDisplayedValue()というメソッドを追加しています。
192
+
193
+ パッケージ名はxxxとしているので、適宜変更してください。
194
+ 色々なケースを試せてないので、問題あればご指摘ください。