androidgridviewcalendar

How to get previous month's days on the gridview (Calendar)


I want to make prev month's days visible (grayed out) on this calendar.

I am getting a present months view here, but as you can see the previous months days are not visible. I know why, but how to go about it? Also a few bugs are there in this present one as well. Posting the code for the custom adapter class:

CalendarAdapter.java

    import java.util.ArrayList;
    import java.util.Calendar;
    import android.content.Context;
    import android.graphics.Color;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;

public class CalendarAdapter extends BaseAdapter {
static final int FIRST_DAY_OF_WEEK =0; // Sunday = 0, Monday = 1


private Context mContext;

private java.util.Calendar month;
private Calendar selectedDate;
private ArrayList<String> items;

public CalendarAdapter(Context c, Calendar monthCalendar) {
    month = monthCalendar;
    selectedDate = (Calendar)monthCalendar.clone();
    mContext = c;
    month.set(Calendar.DAY_OF_MONTH, 1);
    this.items = new ArrayList<String>();
    refreshDays();
}

public void setItems(ArrayList<String> items) {
    for(int i = 0;i != items.size();i++){
        if(items.get(i).length()==1) {
        items.set(i, "0" + items.get(i));
        }
    }
    this.items = items;
}


public int getCount() {
    return days.length;
}

public Object getItem(int position) {
    return null;
}

public long getItemId(int position) {
    return 0;
}

// create a new view for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    TextView dayView;
    if (convertView == null) {  // if it's not recycled, initialize some attributes
        LayoutInflater vi = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = vi.inflate(R.layout.calendar_item, null);
        
    }
    dayView = (TextView)v.findViewById(R.id.date);
    
    // disable empty days from the beginning
    if(days[position].equals("")) {
        dayView.setClickable(false);
        dayView.setFocusable(false);
        //need to show previous months date
        
        
    }
    else {
        // mark current day as focused
        if(month.get(Calendar.YEAR)== selectedDate.get(Calendar.YEAR) && month.get(Calendar.MONTH)== selectedDate.get(Calendar.MONTH) && days[position].equals(""+selectedDate.get(Calendar.DAY_OF_MONTH))) {
            v.setBackgroundResource(R.drawable.date_area);
            dayView.setTextColor(Color.parseColor("#FFFFFF"));
        }
        else {
            v.setBackgroundResource(R.drawable.current_date_area);
        }
    }
    dayView.setText(days[position]);
    
    // create date string for comparison
    String date = days[position];
    
    if(date.length()==1) {
        date = "0"+date;
    }
    String monthStr = ""+(month.get(Calendar.MONTH)+1);
    if(monthStr.length()==1) {
        monthStr = "0"+monthStr;
    }
   
    // show icon if date is not empty and it exists in the items array
   /* ImageView iw = (ImageView)v.findViewById(R.id.date_icon);
    if(date.length()>0 && items!=null && items.contains(date)) {            
        iw.setVisibility(View.VISIBLE);
    }
    else {
        iw.setVisibility(View.INVISIBLE);
    }*/
    return v;
}

public void refreshDays()
{
    // clear items
    items.clear();
    
    int lastDay = month.getActualMaximum(Calendar.DAY_OF_MONTH);
    int firstDay = (int)month.get(Calendar.DAY_OF_WEEK);
    
    // figure size of the array
    if(firstDay==1){
        days = new String[lastDay+(FIRST_DAY_OF_WEEK*6)];
    }
    else {
        days = new String[lastDay+firstDay-(FIRST_DAY_OF_WEEK+1)];
    }
    
    int j=FIRST_DAY_OF_WEEK;
    
    // populate empty days before first real day
    if(firstDay>1) {
        for(j=0;j<firstDay-FIRST_DAY_OF_WEEK;j++) {
            days[j] = "";
        }
    }
    else {
        for(j=0;j<FIRST_DAY_OF_WEEK*6;j++) {
            days[j] = "";
        }
        j=FIRST_DAY_OF_WEEK*6+1; // sunday => 1, monday => 7
    }
    
    // populate days
    int dayNumber = 1;
    for(int i=j-1;i<days.length;i++) {
        days[i] = ""+dayNumber;
        dayNumber++;
    }
}

// references to our items
public String[] days;
}

and this is the Activity code on how I am using this adapter:

CalendarView.java

/*some code above*/
/*this is in the OnCreate block*/
adapter = new CalendarAdapter(this, month);

    GridView gridview = (GridView) findViewById(R.id.gridview);
    gridview.setAdapter(adapter);
/*some code below*/

and here's my calendar view screen (grid):

CalendarView Screenshot:

Grid

To be straight and to the point, all I want is that blank boxes before first of the month be filled in with the previous month's last week's days.


Solution

  • Declare another calendar

    private java.util.Calendar month, prevMonth;
    

    Add a clone to calendar in the constructor

    prevMonth = (Calendar) month.clone();
    prevMonth.roll(Calendar.MONTH, false);
    

    Then replace the refreshDays with this one.This fills up the blank spaces with the days from the last month and the next month for the first and last week of the current month respectively.

    public void refreshDays() {
        // clear items
        items.clear();
    
        int lastDay = month.getActualMaximum(Calendar.DAY_OF_MONTH);
        int firstDay = (int) month.get(Calendar.DAY_OF_WEEK);
        int maxweek = month.getActualMaximum(Calendar.WEEK_OF_MONTH);
        Log.d("CalendarAdapter", String.valueOf(maxweek));
        // figure size of the array
        /*
         * if (firstDay == 1) { days = new String[lastDay + (FIRST_DAY_OF_WEEK *
         * 6)]; }
         * 
         * else { days = new String[lastDay + firstDay - (FIRST_DAY_OF_WEEK +
         * 1)]; }
         */
        days = new String[maxweek * 7];
    
        int j = FIRST_DAY_OF_WEEK;
    
        // populate empty days before first real day
        if (firstDay > 1) {
    
            // can be made a bit faster if implemented without this following
            // for loop for roll
            for (j = 0; j < firstDay - FIRST_DAY_OF_WEEK; j++) {
                prevMonth.roll(Calendar.DAY_OF_MONTH, false);
                Log.d("CalendarAdapter",
                        "roll block: " + prevMonth.get(Calendar.DAY_OF_MONTH));
            }
    
            for (j = 0; j < firstDay - FIRST_DAY_OF_WEEK; j++) {
    
                // days[j] = "";
                prevMonth.roll(Calendar.DAY_OF_MONTH, true);
                int dayPrev = prevMonth.get(Calendar.DAY_OF_MONTH);
                days[j] = " " + String.valueOf(dayPrev) + " ";
                Log.d("CalendarAdapter", "calculation:J if firstDay>1 -- " + j
                        + " roll gives:" + dayPrev);
            }
        } else {
            for (j = 0; j < FIRST_DAY_OF_WEEK * 6; j++) {
                days[j] = "";
                Log.d("CalendarAdapter", "calculation:J if firstDay<1 -- " + j);
            }
            j = FIRST_DAY_OF_WEEK * 6 + 1; // sunday => 1, monday => 7
        }
    
        // populate days
        int dayNumber = 1;
        boolean flag = false;
        for (int i = j - 1; i < days.length; i++) {
    
            days[i] = String.valueOf(dayNumber).trim() + ".";
            if (flag)
                days[i] = String.valueOf(dayNumber).trim();
            if (dayNumber == lastDay) {
                dayNumber = 0;
                flag=true;
            }
            dayNumber++;
        }
    }
    
    // references to our items
    public String[] days;
    }