goolgle keep appのような、時間と日付の選択ダイアログを作成して、将来イベントが思い出されるようにしたいときに表示します。スピナー項目のOnItemClickListener、setOnItemSelectedListenerの問題
ダイアログには、日付と時刻の2つのスピナーフィールドがあります。 最初の数フィールドは、今日、明日などのような言葉の説明です。最後の要素は、日付のマニュアル選択です。クリックすると、時間/日付ピッカーが開きます。
私の現在のソリューションは、これらのスピナーのそれぞれについて、2つのカスタムアダプタを使用しています。アダプターは類似しているので、さらに時間選択部分についてのみ説明します。
My TimeSelectionの例では、getView
とgetDropDownView
の両方のメソッドが実装されています。 getDropDownView
メソッドは興味深いことではありません。通常この状況でスピンナアイテムに表示される値を設定します。
@Override
public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
ViewHolderDropDown holder;
TimeSelectionModel model = getItem(position);
if (convertView == null) {
holder = new ViewHolderDropDown();
convertView = inflater.inflate(R.layout.time_spinner_drop_down_item, parent, false);
holder.verbalTimeTextView = (TextView) convertView.findViewById(R.id.verbal_time_text_view);
holder.timeTextView = (TextView) convertView.findViewById(R.id.time_text_view);
convertView.setTag(R.layout.time_spinner_drop_down_item, holder);
} else {
holder = (ViewHolderDropDown) convertView.getTag(R.layout.time_spinner_drop_down_item);
}
holder.timeTextView.setText(model.time);
holder.verbalTimeTextView.setText(model.verbalTime);
return convertView;
}
唯一の非標準的なことは、2つのTextViewに言語、午後、夕方などの正確な1つの8:00を入力することです。
getView
のメソッドは、通常のデータ配列を使用してメンバを作成する代わりに、フィールドselectedTime
から値を取得します。しばらくして、このフィールドがどのように設定されているかに戻ってきます。これらのビューの両方を保持
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.time_spinner_item, parent, false);
holder.timeTextView = (TextView) convertView.findViewById(R.id.time_text_view);
convertView.setTag(R.layout.time_spinner_item, holder);
} else {
holder = (ViewHolder) convertView.getTag(R.layout.time_spinner_item);
}
holder.timeTextView.setText(selectedTime);
return convertView;
}
DateTimeSelectionDialog
再び類似しているこれらのスピナー両方に対するsetOnItemSelectedListener
を実現します。
timeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Log.d(TAG, "onItemSelected");
if (position == POSITION_MORNING) {
timeAdpater.setTime(8, 0);
} else if (position == POSITION_AFTERNOON) {
timeAdpater.setTime(13, 0);
} else if (position == POSITION_EVENING) {
timeAdpater.setTime(18, 0);
} else if (position == POSITION_NIGHT) {
timeAdpater.setTime(20, 0);
} else {
dateTimeDialogCallbacks.selectTimeManually();
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
ここでラベルを設定します。 1つの例外は、私がdateTimeDialogCallbacks.selectTimeManually();
と呼んでいる最後のフィールドです。 TimePickerから時刻を選択した後、私はこのメソッドをDateTimeSelectionDialogで実装します。
public void setTime(int hour, int minute) {
this.hour = hour;
this.minute = minute;
timeAdpater.setTime(hour, minute);
}
timeAdapter.setTime(hour, minute)
は、フィールドを設定し、データ変更についてアダプタに通知します。
すべてがうまくいっていたようです。 問題はsetOnItemSelectedListener
は、通常のクリックリスナのようなものではありません。クリックされたフィールドが以前選択されたフィールドと異なる場合にのみ呼び出されるためです。 したがって、ユーザーが手動で時刻を選択すると、手動でもう一度選択することはできません。これはもちろんバグです。
私の質問は、これの回避策は何ですか? Googleの人々は明らかに方法を見つけたので、それを行うことができます。
[こちら](https://stackoverflow.com/a/11323043/7482319)リンクをクリックしてください。それが役に立てば幸い。 –
@CagriYalcin素晴らしいもの。 AppComapatSpinerをオーバーライドするためにそれを変更するだけでした。 – Lukasz