2015-11-04 25 views
8

Il mio obiettivo è trovare una libreria Android che mi consenta di contrassegnare varie date su una vista del calendario basata su un array. Le date possono o non possono essere contigue. Il mio scenario ideale è cambiare il colore di sfondo di ogni data. La complicazione significativa è che non conosco questo colore fino al runtime, poiché verrà da una query del server.material-calendarview set background color of dates

Ho svolto ricerche per tutto questo giorno e la mia migliore speranza sembra essere material-calendarview (github). Tuttavia, sto trovando il loro codice in qualche modo impenetrabile, che è su di me, ma sono completamente bloccato.

Ho aggiunto un calendario come questo nel mio layout XML:

<com.prolificinteractive.materialcalendarview.MaterialCalendarView 
     android:id="@+id/calendar_view" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:layout_marginLeft="20dp" 
     android:layout_marginRight="20dp" 
     xmlns:app="http://schemas.android.com/apk/res-auto" 
     app:mcv_showOtherDates="all" 
     app:mcv_selectionColor="#00F"/> 

E poi nella mia attività, ho questi variabili di istanza:

private MaterialCalendarView calendarView; 
private ArrayList<Date> markedDates; 

e questo codice nel mio onCreateView()

calendarView = (MaterialCalendarView) view.findViewById(R.id.calendar_view); 

Ok, abbastanza facile. Ma non riesco a capire come segnare il calendario dalla mia serie di date. Sto lavorando su questo metodo, ma io non so come procedere al di là di quello che ho qui:

private void initializeCalendar() { 

     calendarView.setOnDateChangedListener(context); 
     calendarView.setShowOtherDates(MaterialCalendarView.SHOW_ALL); 

     Calendar calendar = Calendar.getInstance(); 
     calendarView.setSelectedDate(calendar.getTime()); 

     calendar.set(calendar.get(Calendar.YEAR), Calendar.JANUARY, 1); 
     calendarView.setMinimumDate(calendar.getTime()); 

     calendar.set(calendar.get(Calendar.YEAR), Calendar.DECEMBER, 31); 
     calendarView.setMaximumDate(calendar.getTime()); 

     int bgColor = sharedVisualElements.getPrimaryColor(); 

     calendarView.addDecorators(new EventDecorator(bgColor, ????)); 
} 

L'ultima linea si riferisce a questa classe interna:

private class EventDecorator implements DayViewDecorator { 

     private final int color; 
     private final HashSet<CalendarDay> dates; 

     public EventDecorator(int color, Collection<CalendarDay> dates) { 
      this.color = color; 
      this.dates = new HashSet<>(dates); 
     } 

     @Override 
     public boolean shouldDecorate(CalendarDay day) { 
      return dates.contains(day); 
     } 

     @Override 
     public void decorate(DayViewFacade view) { 
      view.addSpan(new DotSpan(5, color)); 
     } 
    } 

penso che il mio sfida a convertire il mio ArrayList<Date> markedDates in quello che chiamano Collection<CalendarDay> dates. Essere d'accordo? Ma questo è il posto dove mi prendo molto in giro. Questo data structure è bizzarro per me. Quando provo a creare un'istanza chiamando new CalendarDay(), la mia classe si espande immediatamente con circa 10 nuovi metodi che non capisco il loro ruolo o che cosa fare con essi. Chiaramente, sto andando fuori dai binari qui. Non può essere così difficile.

Qualcuno ha utilizzato questa libreria per questo scopo e sa come eseguire questa operazione? Sono a una battuta di arresto. Inoltre, se c'è una libreria più semplice per permettermi di impostare i colori di sfondo usando un colore noto solo in fase di esecuzione, sono tutto orecchie.

Grazie per qualsiasi aiuto. Temo di averlo scritto in modo confuso, il che è il risultato del fatto che sono completamente confuso.

risposta

3

Ho risolto questo, quindi pubblicherò la soluzione nel caso in cui qualcun altro ha la stessa domanda. Se esiste un modo più efficiente, si prega di postare come soluzione.

Ho detto che ho un array con un elenco di date. Quello che devo fare è iterare su quell'array, convertire ogni Date in un oggetto Calendar impostato sull'anno, mese e giorno appropriati, quindi aggiungere quell'oggetto a un altro ArrayList, questa volta uno ArrayList<CalendarDay>. Per esempio:

List<CalendarDay> list = new ArrayList<CalendarDay>(); 
Calendar calendar = Calendar.getInstance(); 

for (Date date : markedDates) { 
    // might be a more elegant way to do this part, but this is very explicit 
    int year = date.getYear(); 
    int month = date.getMonthOfYear() - 1; // months are 0-based in Calendar 
    int day = date.getDayOfMonth(); 

    calendar.set(year, month, day); 
    CalendarDay calendarDay = CalendarDay.from(calendar); 
    list.add(calendarDay); 
} 

Così ora abbiamo questa lista di CalendarDay oggetti, ma non siamo del tutto lì. Il passaggio finale nella creazione della struttura dei dati consiste nel "convertirlo" in ciò che ho menzionato con cui stavo lavorando nell'OP: una struttura Collection<CalendarDay>. Risulta che questo non potrebbe essere più semplice una volta arrivati ​​qui.È sufficiente assegnare in questo modo:

calendarDays = list; 

E poi, quando si desidera aggiungere il decoratore, siete tutti insieme in su. Basta fare questo:

calendarView.addDecorators(new EventDecorator(myColor, calendarDays)); 

Un altra cosa la pena menzionare, e questa è stata una delle principali fonti di mia confusione. Non ho capito come istanziare questo oggetto Collection<CalendarDay>. Way up nella sezione variabile di istanza (prima del costruttore), ho aggiunto questo codice, la quasi totalità dei quali Android Studio compilato per me:

private Collection<CalendarDay> calendarDays = new Collection<CalendarDay>() { 
     @Override 
     public boolean add(CalendarDay object) { 
      return false; 
     } 

     @Override 
     public boolean addAll(Collection<? extends CalendarDay> collection) { 
      return false; 
     } 

     @Override 
     public void clear() { 

     } 

     @Override 
     public boolean contains(Object object) { 
      return false; 
     } 

     @Override 
     public boolean containsAll(Collection<?> collection) { 
      return false; 
     } 

     @Override 
     public boolean isEmpty() { 
      return false; 
     } 

     @NonNull 
     @Override 
     public Iterator<CalendarDay> iterator() { 
      return null; 
     } 

     @Override 
     public boolean remove(Object object) { 
      return false; 
     } 

     @Override 
     public boolean removeAll(Collection<?> collection) { 
      return false; 
     } 

     @Override 
     public boolean retainAll(Collection<?> collection) { 
      return false; 
     } 

     @Override 
     public int size() { 
      return 0; 
     } 

     @NonNull 
     @Override 
     public Object[] toArray() { 
      return new Object[0]; 
     } 

     @NonNull 
     @Override 
     public <T> T[] toArray(T[] array) { 
      return null; 
     } 
    }; 

Spero che questo aiuta qualcuno. Di nuovo, se c'è una soluzione migliore, per favore pubblica e io cancellerò il mio.

+0

bro quando faccio che il getYear() è deprecato cosa posso fare per la sostituzione –

2

Perché hai utilizzato ArrayList invece di HashSet? Il motivo per cui non è possibile creare un'istanza di Collection è perché è un'interfaccia, quindi è necessario creare una classe anonima e sovrascrivere i metodi.

Ecco come ho fatto qualcosa di simile:

Questo metodo prende in due oggetti Calendario e aggiunge tutti i giorni tra le due date di calendario in un HashSet di CalendarDays.

private HashSet<CalendarDay> getCalendarDaysSet(Calendar cal1, Calendar cal2) { 
    HashSet<CalendarDay> setDays = new HashSet<>(); 
    while (cal1.getTime().before(cal2.getTime())) { 
     CalendarDay calDay = CalendarDay.from(cal1); 
     setDays.add(calDay); 
     cal1.add(Calendar.DATE, 1); 
    } 

    return setDays; 
} 

sul metodo onCreateView (...), ho dinamicamente impostare le due date del calendario, la differenza tra che saranno memorizzati nel HashSet. Tuttavia, puoi passare il tuo set casuale di date in HashSet.

Calendar cal1 = Calendar.getInstance(); 
    cal1.set(2016, 8, 1); 
    Calendar cal2 = Calendar.getInstance(); 
    cal2.set(2016, 9, 1); 

    HashSet<CalendarDay> setDays = getCalendarDaysSet(cal1, cal2); 
    int myColor = R.color.red; 
    mCalendarView.addDecorator(new BookingDecorator(myColor, setDays)); 

Nel mio caso BookingDecorator è la classe che implementa l'interfaccia DayViewDecorator.

private class BookingDecorator implements DayViewDecorator { 
    private int mColor; 
    private HashSet<CalendarDay> mCalendarDayCollection; 

    public BookingDecorator(int color, HashSet<CalendarDay> calendarDayCollection) { 
     mColor = color; 
     mCalendarDayCollection = calendarDayCollection; 
    } 

    @Override 
    public boolean shouldDecorate(CalendarDay day) { 
     return mCalendarDayCollection.contains(day); 
    } 

    @Override 
    public void decorate(DayViewFacade view) { 
     view.addSpan(new ForegroundColorSpan(mColor)); 
     //view.addSpan(new BackgroundColorSpan(Color.BLUE)); 
     view.setBackgroundDrawable(ContextCompat.getDrawable(getContext(),R.drawable.greenbox)); 

    } 
} 

Il tuo post è stato molto utile. Spero che il mio aiuti anche qualcuno.

3

Se si desidera cambiare il colore del selezionato sfondo programatically, utilizzare questo metodo: -

MaterialCalendarView materialCalendar = (MaterialCalendarView)findViewById(R.id.materialCalenderView); 
materialCalendar.setSelectionColor(Color.parseColor("#00BCD4")); 

Utilizzando questo codice rende tutti i selettori dello stesso colore, quindi se si vuole avere diversi selettori di colore a seconda le tue condizioni, usa decorator()

Problemi correlati