There is a vey nice libray(https://github.com/Applandeo/Material-Calendar-View) for customizing the android calenderview . Like for example, for adding events to the calenderview there is class named Eventday.java, which takes calender object and a drawable object as parameters to initialize. I wish it could have take a string value too so that i can also store a descrption of the event, because there is no point in adding events to the calender if one cannot add details about the event(string datatype). Can some one provide a workaround for my problem?
List<EventDay> events = new ArrayList<>();
Calendar calendar = Calendar.getInstance();
//we cannot details about the event(string data) while initializing the EventDay class
events.add(new EventDay(calendar, R.drawable.absentic));
First Make a Custom Class
import com.applandeo.materialcalendarview.EventDay;
import java.util.Calendar;
public class MyEventDay extends EventDay implements Parcelable {
private String mNote;
public MyEventDay(Calendar day, int imageResource, String note) {
super(day, imageResource);
mNote = note;
}
public String getNote() {
return mNote;
}
private MyEventDay(Parcel in) {
super((Calendar) in.readSerializable(), in.readInt());
mNote = in.readString();
}
public static final Creator<MyEventDay> CREATOR = new Creator<MyEventDay>() {
#Override
public MyEventDay createFromParcel(Parcel in) {
return new MyEventDay(in);
}
#Override
public MyEventDay[] newArray(int size) {
return new MyEventDay[size];
}
};
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeSerializable(getCalendar());
parcel.writeInt(getImageResource());
parcel.writeString(mNote);
}
#Override
public int describeContents() {
return 0;
}
}
Adding Event In Calender
mEventDays.add(new MyEventDay(calender, R.drawable.ic_note_sticky, "I am Event");
For Retriving String
calendarView.setOnDayClickListener(new OnDayClickListener() {
#Override
public void onDayClick(EventDay eventDay) {
Log.e("Event",((MyEventDay) eventDay).getNote()+" <--");
}
});
Its Work For me , I Hope its Helpfull to you also
I used this method to display small popup note when user clicks on any date.
Declared: Map<Date,String> eventNotes = new HashMap<>()
While updating calendar events for every date, populated the eventNotes with required notes and date as key
In Calendar setOnDayClickListener retrieved eventNote using the key eventDay.getCalendar().getTime()
Then used a dialog popup to show that note
Related
Hey guys I have no Idea what happen? I add birthdays but if call them with getHashMap for example I cant get the elements in the class swingmenu. I just have thoughts about the Problem. I think its because I call new Event in a class and where I output the hashmap in a different class I call new Event too. But I dont know if I am right?
Maybe any Solution would help me. If you have Question then please ask me. For me its important to learn something new. There are some short coded showen because its not relevant. I debug the class swingFormatFunction and find out that the the instance event is null.
This part dont get added into my HashMap.
public class swingFormatFunction{
private Event event = new Event();
public void geburtstageFormatieren(String content) {
String formatContent = content.replace(';', ' ');
for (String s : formatContent.split("\n")) {
event.addBirthday(s.substring(0, 5).toString(), new Event(s.substring(12).toString()));
}
}
}
That is my menu where I call a Menuitem and click "ok". This function works fine I get the elements outputted.
public class swingMenu{
okBTN.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == okBTN) {
dialog.dispose();
JDialog dialog = new JDialog();
dialog.setModal(true);
dialog.setTitle("Calendar Special Events");
int yearNumber = Integer.parseInt((String) yearCombobox.getSelectedItem());
JTextArea textArea = new JTextArea();
Event event = new Event(yearNumber);
StringBuilder stringBuilder = new StringBuilder();
for (Map.Entry entry : event.getEventMap().entrySet()) {
stringBuilder.append(entry.getKey() + " : " + entry.getValue() + "\n");
}
textArea.setText(stringBuilder.toString());
dialog.setContentPane(textArea);
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setResizable(true);
textArea.setEditable(false);
dialog.setVisible(true);
}
}
});
That is my Event class. This class contains my HashMap where I work with it.
public class Event{
private HashMap<String, Event> eventMap = new HashMap<>();
public Event(String name) {
this.name = name;
}
public Event(int year) {
addStrongMoveableHolidayInMap(year);
}
public Event() {
}
private void addMoveableHoliday(int year) {
/* Bewegliche Feiertage */
/*Rose monday (-48)*/
int daynumberOfEasterSunday = calenderFunction.easterSunday(year) - 48;
String gregorDate = calenderFunction.kalenderDatumFuerJD(daynumberOfEasterSunday);
String day = gregorDate.substring(0, 2);
String month = gregorDate.substring(3, 5);
String date = day + "." + month;
this.eventMap.put(date, new Event("Rosenmontag"));
}
private void addStrongHoliday(int year) {
/* Feste Feiertage */
this.eventMap.put("24.12", new Event("1. Weihnachtstag"));
}
void addStrongMoveableHolidayInMap(int year) {
addStrongHoliday(year);
addMoveableHoliday(year);
}
public void addBirthday(String year, Event event) {
this.eventMap.put(year, event);
}
public HashMap<String, Event> getEventMap() {
return eventMap;
}
}
I hope you guys can help me.
Best Regards
Manuellsen
The two event objects are totally independent.
The first one in swingFormatFunction is a instance attribute and the second one in ActionListener is a local variable.
The Event's eventMap attribute is also an instance attribute, so each Event object has its own map. Maybe you want to share one eventMap accross all events.
Please note: I am new in this subject.
Suppose I have a class Event.
public class Event {
//constructors, etc.
public void pathFollowed(int location) {
//this method could be called at any time
}
}
And a class called EventManager.
public class EventManager {
private int managerLocation;
private ArrayList<Event> events;
public EventManager() {
events = new ArrayList<Event>();
}
public void addEvent(Event e) {
//THIS IS THE AREA OF INTEREST
events.add(e);
}
}
In the "area of interest" comment, is there any way of setting the value of managerLocation whenever the Event e calls upon pathFollowed(int location). My goal is that when any of the Events in the events arraylist calls pathFollowed(int location) that managerLocation would be set to "location" ("location" referring to the input in the pathfollowed method).
I was originally thinking of over-riding the pathFollowed method, but then I realized this can't be done because by the time the event gets to the addEvent method, it is already instantiated and can't be changed in this manner.
Thanks in advance.
Maybe some kind of listener pattern?
public class Event {
private List<PathListener> pls; //Or just one if you know you'll only need one
//constructors, etc.
public void pathFollowed(int location) {
//this method could be called at any time
for(PathListener pl : pls)
pl.notifyLocation(location);
}
public addPathListener(PathListener pl) {
pls.add(pl);
}
}
EventManager:
public class EventManager implements PathListener {
private int managerLocation;
private ArrayList<Event> events;
public EventManager() {
events = new ArrayList<Event>();
}
public void addEvent(Event e) {
e.addPathListener(this);
events.add(e);
}
#Override
public notifyLocation(int location) { //Of the PathListener interface
managerLocation = location;
}
}
This is just a kind-of-generic example, because I don't know what your purpose is, but maybe it will get you thinking.
My goal is to find an Android library that will allow me to mark various dates on a calendar view based on an array. The dates may or may not be contiguous. My ideal scenario is to change the background color of each date. The significant complication is that I don't know this color until runtime, since it will come from a server query.
I've been researching this all day, and my best hope seems to be material-calendarview (github). However, I am finding their code to be somewhat impenetrable, which is on me, but I am completely stuck.
I've added a calendar like this in my XML layout:
<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"/>
And then in my activity, I have these instance variables:
private MaterialCalendarView calendarView;
private ArrayList<Date> markedDates;
and this code in my onCreateView()
calendarView = (MaterialCalendarView) view.findViewById(R.id.calendar_view);
Ok, easy enough. But I cannot figure out how to mark the calendar from my array of dates. I am working on this method, but I just don't know how to proceed beyond what I have here:
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, ????));
}
That last line refers to this inner class:
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));
}
}
I think that my challenge to convert my ArrayList<Date> markedDates to what they call Collection<CalendarDay> dates. Agree? But this is where I really bog down. This data structure is bizarre to me. When I try to instantiate it by calling new CalendarDay() my class immediately expands with about 10 new methods that I don't understand their role or what to do with them. Clearly, I am going off the rails here. It just can't be this tricky.
Has anyone used this library for this purpose and know how to accomplish this task? I'm at a grinding halt. Also, if there is a simpler library to allow me to set background colors using a color only known at run-time, I'm all ears.
Thanks for any help. I fear that I have written this in a confusing manner, which is a result of the fact that I am completely confused.
I solved this, so I'll post that solution in case anyone else has the same question. If there is a more efficient way, please post as a solution.
I mentioned that I have an array with a list of dates. What I need to do is to iterate over that array, converting each Date into a Calendar object set to the appropriate year, month, and day, and then adding that object to a different ArrayList, this time an ArrayList<CalendarDay>. For example:
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);
}
So now we've got this list of CalendarDay objects, but we're not quite there. The final step in creating the data structure is to 'convert' this over to what I mentioned I was struggling with in the OP - a Collection<CalendarDay> structure. Turns out this couldn't be any simpler once we get here. Simply assign it like this:
calendarDays = list;
And then when you want to add the decorator, you're all set up. Just do this:
calendarView.addDecorators(new EventDecorator(myColor, calendarDays));
One other thing bears mentioning, and this was a major source of my confusion. I didn't understand how to instantiate this Collection<CalendarDay> object. Way up in the instance variable section (before the constructor), I added this code, almost all of which Android Studio filled in for 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;
}
};
I hope that this helps someone. Again, if there is a better solution, please post and I'll delete mine.
If you want to change the background color of the selected programatically, use this method:-
MaterialCalendarView materialCalendar = (MaterialCalendarView)findViewById(R.id.materialCalenderView);
materialCalendar.setSelectionColor(Color.parseColor("#00BCD4"));
Using this code makes all selectors of same color, so if you want to have different color selectors depending on your condition, use decorator()
Why did you use the ArrayList instead of the HashSet ?
The reason you cannot instantiate Collection is because it is an interface, hence you had to create anonymous class and override the methods.
Here is how I did something similar:
This method takes in two Calendar objects and adds all the days in between the two Calendar dates into a HashSet of 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;
}
on the onCreateView(...) method,I have dynamically set the two calendar dates, the difference between which will be stored in the HashSet. However, you can pass your own random set of dates in the 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));
In my case BookingDecorator is the class that implements the DayViewDecorator interface.
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));
}
}
Your post was very helpful. Hope mine helps somebody as well.
In the top of my page I want a dropdown to change the preferred language. If it alters the page is to be reloaded and rendered with the selected langauge.
In my solution the language is not loaded immediately though.
#SuppressWarnings("serial")
public class CurrentLanguageDropdown extends LanguageDropDown {
private String sessionlanguage;
private IModel<String> model;
public CurrentLanguageDropdown(String id, Locale locale) {
super(id, locale);
this.sessionlanguage = locale.getCountry();
GlobalAccountSession session = GlobalAccountSession.get();
model = new SelectedLocaleModel("sessionlanguage", this, new Model<Serializable>(session.getLocale()),
locale.getCountry());
setModel(model);
}
#Override
public void onSelectionChanged(String newSelection) {
GlobalAccountSession session = GlobalAccountSession.get();
model = new SelectedLocaleModel("sessionlanguage", this, new Model<Serializable>(session.getLocale()),
newSelection);
}
#Override
protected boolean wantOnSelectionChangedNotifications() {
return true;
}
String getSessionlanguage() {
return sessionlanguage;
}
private class SelectedLocaleModel extends StringResourceModel {
private String selectedValue = "";
private Component parent;
public SelectedLocaleModel(String resourceKey, Component parent, IModel<?> model, String selectedValue) {
super(resourceKey, parent, model);
this.selectedValue = selectedValue;
this.parent = parent;
}
#Override
public void setObject(java.lang.String object) {
GlobalAccountSession session = GlobalAccountSession.get();
Locale locale = new Locale(object.toString());
session.setLocale(locale);
selectedValue = locale.getLanguage();
}
#Override
public String getObject() {
GlobalAccountSession session = GlobalAccountSession.get();
selectedValue = session.getLocale().getLanguage();
return selectedValue;
}
}
}
Looking at my code I see that getObject is called first, and setObject after that. So rendering seems to be done before the change made by the user is handled.
Can anyone tell me what I'm doing wrong?
You're creating a new model object in onSelectionChanged. This defeats the purpose of a model which should be modified but not replaced. If you need to create a new model object, you'll have to replace the model used by your component too (call setModel(model) again).
I know this isnt a component but an implementation of one but shows the general idea
public class LocaleDropDownPanel extends Panel
{
private Locale sessionLocale;
public LocaleDropDownPanel(String id, Locale locale)
{
super(id);
ArrayList<Locale> choices = Lists.newArrayList(Locale.getAvailableLocales());
//didnt know if you need country or language
IChoiceRenderer<Locale> choiceRenderer = new ChoiceRenderer<Locale>("language");
DropDownChoice<Locale> ddc = new DropDownChoice<Locale>("ddc", new PropertyModel<Locale>(this, "sessionLocale"),
new Model<ArrayList<Locale>>(choices), choiceRenderer)
{
#Override
protected void onSelectionChanged(Locale newSelection)
{
//if you want to save the selected locale in your session.
GlobalAccountSession session = GlobalAccountSession.get();
session.setLocale(newSelection);
}
};
//This Language selected to begin with
ddc.setDefaultModelObject(locale);
}
public Locale getSessionLocale() {
return sessionLocale;
}
public void setSessionLocale(Locale sessionLocale) {
this.sessionLocale = sessionLocale;
}
}
CompositeCell let us customize the content of a table cell's in GWT using Java. We can put almost any other group of widget within the table's cell and layout them as we want. Problem is that if we used the html tags to define the layout of the CompositeCell as yet another table (see CompositeCell anonymous class implementation bellow) we loose the event handling for the components of the cell :(.
Running the following code, when we click in the buttons of the cell will realize the popup in response of the event handling IF WE COMMENT the CompositeCell anonymous implementation.
I've been debugging CompositeCell.onBrowserEvent(Context, Element, C, NativeEvent, ValueUpdater) because i think that the definition of the cell layout using HTML table tags breaks the event chain within GWT widgets hierarchy but haven't been successful so far.
Remark: both commented and uncommented versions of the code realize the same GUI layout. This example just intent to show that we loose event handling when customizing cell's content.
public class ActionCellTest implements EntryPoint {
private static final String SERVER_ERROR = "An error occurred while " + "attempting to contact the server. Please check your network "
+ "connection and try again.";
private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
public void onModuleLoad() {
CellTable<Person> table = new CellTable<ActionCellTest.Person>();
final List<HasCell<Person, ?>> cells = new LinkedList<HasCell<Person, ?>>();
cells.add(new HasCellImpl("first name", new ActionCell.Delegate<Person>() {
#Override
public void execute(Person object) {
Window.alert(object.getFirstName());
}
}));
cells.add(new HasCellImpl("last name", new ActionCell.Delegate<ActionCellTest.Person>() {
#Override
public void execute(Person object) {
Window.alert(object.getLastName());
}
}));
CompositeCell<Person> cell = new CompositeCell<Person>(cells) {
#Override
public void render(Context context, Person value, SafeHtmlBuilder sb) {
sb.appendHtmlConstant("<table><tbody><tr>");
for (HasCell<Person, ?> hasCell : cells) {
render(context, value, sb, hasCell);
}
sb.appendHtmlConstant("</tr></tbody></table>");
}
#Override
protected <X> void render(Context context, Person value, SafeHtmlBuilder sb, HasCell<Person, X> hasCell) {
Cell<X> cell = hasCell.getCell();
sb.appendHtmlConstant("<td>");
cell.render(context, hasCell.getValue(value), sb);
sb.appendHtmlConstant("</td>");
}
#Override
protected Element getContainerElement(Element parent) {
return parent.getFirstChildElement().getFirstChildElement().getFirstChildElement();
}
};
table.addColumn(new TextColumn<ActionCellTest.Person>() {
#Override
public String getValue(ActionCellTest.Person object) {
return object.getFirstName() + " " + object.getLastName();
}
}, "name");
table.addColumn(new Column<Person, Person>(cell) {
#Override
public Person getValue(ActionCellTest.Person object) {
return object;
}
}, "composite");
LinkedList<Person> data = new LinkedList<ActionCellTest.Person>();
data.add(new Person("Amy", "Reed"));
data.add(new Person("Tim", "Gardner"));
table.setRowData(data);
RootPanel.get().add(table);
}
private class HasCellImpl implements HasCell<Person, Person> {
private ActionCell<Person> fCell;
public HasCellImpl(String text, Delegate<Person> delegate) {
fCell = new ActionCell<Person>(text, delegate);
}
#Override
public Cell<Person> getCell() {
return fCell;
}
#Override
public FieldUpdater<Person, Person> getFieldUpdater() {
return null;
}
#Override
public Person getValue(Person object) {
return object;
}
}
private class Person {
private String fFirstName;
private String fLastName;
public Person(String first, String last) {
fFirstName = first;
fLastName = last;
}
public String getFirstName() {
return fFirstName;
}
public String getLastName() {
return fLastName;
}
}
}
This is a known issue which will be fixed in the upcoming GWT 2.5 (a matter of weeks): http://code.google.com/p/google-web-toolkit/issues/detail?id=5714
(in the mean time, you can run off trunk or try backporting the change)