Reputation: 5954
I have implemented CalendarView in my project and I would like to get the DD/MM/YY format on clicking the date
I tried the following:
calendar =(CalendarView) findViewById(R.id.calendarforstart);
calendar.setShowWeekNumber(false);
calendar.setFirstDayOfWeek(2);
calendar.setOnDateChangeListener(new OnDateChangeListener()
{
@Override
public void onSelectedDayChange(CalendarView view, int year, int month, int day)
{
Toast.makeText(getApplicationContext(), day + "/" + month + "/" + year, Toast.LENGTH_LONG).show();
}
});
The above works fine but if I scroll the calendar to next month or previous month. I am getting the Toast, which I don't want instead, I would like to get the toast only when I click on the on a date?
How do I implement this?
Let me know!
Thanks!
Upvotes: 0
Views: 3655
Reputation: 179
To solve cannot select the current date
is a hard way. The idea is save each list item's screen position, and check every dispatchTouchEvent
if (x,y) is inside a date view item.
private long lastDate = 0;
private int downX;
private int downY;
private int upX;
private int upY;
private int lastX=0;
private int lastY=0;
private ItemArea currentArea;
private int year = -1;
private int month;
private int day;
private ListView listView;
private int[] startPoint = new int[2];
private int listItemCount = 0;
private int listItemWidth = 0;
private int listItemHeight = 0;
ArrayList<ItemArea> areaList = new ArrayList<>();
private CalendarView calendar;
private boolean isInitialized = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
calendar =(CalendarView) findViewById(R.id.calendarforstart);
calendar.setShowWeekNumber(false);
calendar.setFirstDayOfWeek(2);
calendar.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
@Override
public void onSelectedDayChange(CalendarView view, int year, int month, int day) {
if(view.getDate() != lastDate) {
lastDate = view.getDate();
MainActivity.this.year = year;
MainActivity.this.month = month;
MainActivity.this.day = day;
makeToast();
currentArea = getItemArea(upX, upY);
isInitialized = true;
}
}
});
listView = (ListView)calendar.findViewById(android.R.id.list);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = (int)event.getX();
downY = (int)event.getY();
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
upX = (int)event.getX();
upY = (int)event.getY();
if (areaList.size()==0) {
generateList();
}
// make sure it's not move
if (Math.abs(downX-upX)<3 && Math.abs(downY-upY)<3) {
ItemArea area = getItemArea(upX, upY);
// on application start up and click the current date, there are stored status.
if (currentArea==null || !isInitialized) {
long time = calendar.getDate();
Calendar currentCalendar = new GregorianCalendar();
currentCalendar.setTimeInMillis(time);
year = currentCalendar.get(Calendar.YEAR);
month = currentCalendar.get(Calendar.MONTH);
day = currentCalendar.get(Calendar.DAY_OF_MONTH);
makeToast();
}
if (area!=null && area.equals(currentArea)) {
makeToast();
}
} else {
// FIXME: still have bug when drag/scroll back
// it's move event, list view will scroll up/down, and update the y
if (currentArea!=null) {
if (downY<upY) {
// move down
int times = (upY-downY)/listItemHeight;
currentArea.top+=listItemHeight*(times+1);
currentArea.bottom+=listItemHeight*(times+1);
} else {
// move up
int times = (downY-upY)/listItemHeight;
currentArea.top-=listItemHeight*(times+1);
currentArea.bottom-=listItemHeight*(times+1);
}
}
}
break;
}
return super.dispatchTouchEvent(event);
}
private void generateList() {
listItemCount = listView.getChildCount();
listItemHeight = listView.getChildAt(0).getHeight();
listItemWidth = listView.getChildAt(0).getWidth();
listView.getChildAt(0).getLocationOnScreen(startPoint);
int deltaX = (int)(listItemWidth/7.0);
for (int i=0; i< listItemCount; i++) {
for (int j=0; j<7; j++) {
areaList.add(new ItemArea(startPoint[0]+deltaX*j, startPoint[1]+listItemHeight*i,
startPoint[0]+deltaX*(j+1), startPoint[1]+listItemHeight*(i+1)));
}
}
}
private void makeToast() {
Log.d("TAG", "do your job here");
lastX = upX;
lastY = upY;
Toast.makeText(this, "" + day + "/" + month + "/" + year, Toast.LENGTH_LONG).show();
}
private ItemArea getItemArea(int x, int y) {
for (int i=0; i < areaList.size(); i++) {
if (areaList.get(i).contains(x, y)) {
return areaList.get(i);
}
}
return null;
}
private class ItemArea {
int left;
int top;
int right;
int bottom;
ItemArea(int left, int top, int right, int bottom) {
this.left = left;
this.top = top;
this.right = right;
this.bottom = bottom;
}
boolean contains(int x, int y) {
return x>=left && x<=right && y>=top && y<=bottom;
}
boolean equals(ItemArea area) {
return area!=null &&
this.right==area.right &&
this.left==area.left &&
this.bottom==area.bottom &&
this.top==area.top;
}
}
UPDATE
In API 22 (android 5.1), android has changed CalendarView
to MATERIAL
. There is no ListView
at all, check the code from CalendarView MODE_MATERIAL and calendarViewMode
So the above code fails if you use default style, the only way is force using CalendarViewLegacyDelegate
which means set calendarViewMode
to MODE_HOLO
. You can do this by adding style="@android:style/Widget.CalendarView"
which is simply like this:
<CalendarView
android:id="@+id/calendarforstart"
style="@android:style/Widget.CalendarView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
But you will lost your material UI. You can extends Widget.CalendarView
for your needs, but I think it's still far away from material.
Upvotes: 1