0

goolgle keep appのような、時間と日付の選択ダイアログを作成して、将来イベントが思い出されるようにしたいときに表示します。スピナー項目のOnItemClickListener、setOnItemSelectedListenerの問題

ダイアログには、日付と時刻の2つのスピナーフィールドがあります。 最初の数フィールドは、今日、明日などのような言葉の説明です。最後の要素は、日付のマニュアル選択です。クリックすると、時間/日付ピッカーが開きます。

A date and time selection dialog

私の現在のソリューションは、これらのスピナーのそれぞれについて、2つのカスタムアダプタを使用しています。アダプターは類似しているので、さらに時間選択部分についてのみ説明します。

My TimeSelectionの例では、getViewgetDropDownViewの両方のメソッドが実装されています。 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の人々は明らかに方法を見つけたので、それを行うことができます。

+1

[こちら](https://stackoverflow.com/a/11323043/7482319)リンクをクリックしてください。それが役に立てば幸い。 –

+0

@CagriYalcin素晴らしいもの。 AppComapatSpinerをオーバーライドするためにそれを変更するだけでした。 – Lukasz

答えて

0

まあ、あなたのコードのコンテキスト内では、理想的ではないが回避策であるonNothingSelected(AdapterView親)のチェックを追加することができます!

+0

私はまったくフォローしません。 'onNothingSelected'は、ビューから選択が消えるときに呼び出されます。これはどうやって私にとって役に立ちますか?私はこれがどこに呼ばれるのか分かりません。 – Lukasz

+0

この回答は間違っています。 –

+0

申し訳ありませんが私の悪い、私はあなたの質問を理解できなかった。 –

関連する問題