class MainActivity
package org.androidtown.calendar.month;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.TextView;
/**
* 그리드뷰를 이용해 월별 캘린더를 만드는 방법에 대해 알 수 있습니다.
*
* @author Mike
*/
public class MainActivity extends ActionBarActivity {
/**
* 월별 캘린더 뷰 객체
*/
CalendarMonthView monthView;
/**
* 월별 캘린더 어댑터
*/
CalendarMonthAdapter monthViewAdapter;
/**
* 월을 표시하는 텍스트뷰
*/
TextView monthText;
/**
* 현재 연도
*/
int curYear;
/**
* 현재 월
*/
int curMonth;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 월별 캘린더 뷰 객체 참조
monthView = (CalendarMonthView) findViewById(R.id.monthView);
monthViewAdapter = new CalendarMonthAdapter(this);
monthView.setAdapter(monthViewAdapter);
// 리스너 설정
monthView.setOnDataSelectionListener(new OnDataSelectionListener() {
public void onDataSelected(AdapterView parent, View v, int position, long id) {
// 현재 선택한 일자 정보 표시
MonthItem curItem = (MonthItem) monthViewAdapter.getItem(position);
int day = curItem.getDay();
Log.d("CalendarMonthViewActivity", "Selected : " + day);
}
});
monthText = (TextView) findViewById(R.id.monthText);
setMonthText();
// 이전 월로 넘어가는 이벤트 처리
Button monthPrevious = (Button) findViewById(R.id.monthPrevious);
monthPrevious.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
monthViewAdapter.setPreviousMonth();
monthViewAdapter.notifyDataSetChanged();
setMonthText();
}
});
// 다음 월로 넘어가는 이벤트 처리
Button monthNext = (Button) findViewById(R.id.monthNext);
monthNext.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
monthViewAdapter.setNextMonth();
monthViewAdapter.notifyDataSetChanged();
setMonthText();
}
});
}
/**
* 월 표시 텍스트 설정
*/
private void setMonthText() {
curYear = monthViewAdapter.getCurYear();
curMonth = monthViewAdapter.getCurMonth();
monthText.setText(curYear + "년 " + (curMonth+1) + "월");
}
}
R.layout.activity_main
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffffff"
>
<Button
android:id="@+id/monthPrevious"
android:layout_width="46dp"
android:layout_height="wrap_content"
android:background="@drawable/backward"
android:gravity="center_horizontal"
android:layout_alignParentLeft="true"
/>
<TextView
android:id="@+id/monthText"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="MonthView"
android:textSize="24dp"
android:textStyle="bold"
android:gravity="center_horizontal"
android:layout_centerInParent="true"
/>
<Button
android:id="@+id/monthNext"
android:layout_width="46dp"
android:layout_height="wrap_content"
android:background="@drawable/forward"
android:gravity="center_horizontal"
android:layout_alignParentRight="true"
/>
</RelativeLayout>
<org.androidtown.calendar.month.CalendarMonthView
android:id="@+id/monthView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
class MonthItem
package org.androidtown.calendar.month;
/**
* 일자 정보를 담기 위한 클래스 정의
*
* @author Mike
*
*/
public class MonthItem {
private int dayValue;
public MonthItem() {
}
public MonthItem(int day) {
dayValue = day;
}
public int getDay() {
return dayValue;
}
public void setDay(int day) {
this.dayValue = day;
}
}
class MonthItemView
package org.androidtown.calendar.month;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.widget.TextView;
/**
* 일자에 표시하는 텍스트뷰 정의
*
* @author Mike
*/
public class MonthItemView extends TextView {
private MonthItem item;
public MonthItemView(Context context) {
super(context);
init();
}
public MonthItemView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
setBackgroundColor(Color.WHITE);
}
public MonthItem getItem() {
return item;
}
public void setItem(MonthItem item) {
this.item = item;
int day = item.getDay();
if (day != 0) {
setText(String.valueOf(day));
} else {
setText("");
}
}
}
interface OnDataSelectionListener
package org.androidtown.calendar.month;
import android.view.View;
import android.widget.AdapterView;
/**
* 아이템이 선택되었을 때 처리하는 리스너 새로 정의
*
* @author Mike
*/
public interface OnDataSelectionListener {
/**
* 아이템이 선택되었을 때 호출되는 메소드
*
* @param parent Parent View
* @param v Target View
* @param row Row Index
* @param column Column Index
* @param id ID for the View
*/
public void onDataSelected(AdapterView parent, View v, int position, long id);
}
class CalendarMonthAdapter
package org.androidtown.calendar.month;
import java.util.Calendar;
import android.content.Context;
import android.graphics.Color;
import android.text.format.Time;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
/**
* 어댑터 객체 정의
*
* @author Mike
*
*/
public class CalendarMonthAdapter extends BaseAdapter {
public static final String TAG = "CalendarMonthAdapter";
Context mContext;
public static int oddColor = Color.rgb(225, 225, 225);
public static int headColor = Color.rgb(12, 32, 158);
private int selectedPosition = -1;
private MonthItem[] items;
private int countColumn = 7;
int mStartDay;
int startDay;
int curYear;
int curMonth;
int firstDay;
int lastDay;
Calendar mCalendar;
boolean recreateItems = false;
public CalendarMonthAdapter(Context context) {
super();
mContext = context;
init();
}
public CalendarMonthAdapter(Context context, AttributeSet attrs) {
super();
mContext = context;
init();
}
private void init() {
items = new MonthItem[7 * 6];
mCalendar = Calendar.getInstance();
recalculate();
resetDayNumbers();
}
public void recalculate() {
// set to the first day of the month
mCalendar.set(Calendar.DAY_OF_MONTH, 1);
// get week day
int dayOfWeek = mCalendar.get(Calendar.DAY_OF_WEEK);
firstDay = getFirstDay(dayOfWeek);
Log.d(TAG, "firstDay : " + firstDay);
mStartDay = mCalendar.getFirstDayOfWeek();
curYear = mCalendar.get(Calendar.YEAR);
curMonth = mCalendar.get(Calendar.MONTH);
lastDay = getMonthLastDay(curYear, curMonth);
Log.d(TAG, "curYear : " + curYear + ", curMonth : " + curMonth + ", lastDay : " + lastDay);
int diff = mStartDay - Calendar.SUNDAY - 1;
startDay = getFirstDayOfWeek();
Log.d(TAG, "mStartDay : " + mStartDay + ", startDay : " + startDay);
}
public void setPreviousMonth() {
mCalendar.add(Calendar.MONTH, -1);
recalculate();
resetDayNumbers();
selectedPosition = -1;
}
public void setNextMonth() {
mCalendar.add(Calendar.MONTH, 1);
recalculate();
resetDayNumbers();
selectedPosition = -1;
}
public void resetDayNumbers() {
for (int i = 0; i < 42; i++) {
// calculate day number
int dayNumber = (i+1) - firstDay;
if (dayNumber < 1 || dayNumber > lastDay) {
dayNumber = 0;
}
// save as a data item
items[i] = new MonthItem(dayNumber);
}
}
private int getFirstDay(int dayOfWeek) {
int result = 0;
if (dayOfWeek == Calendar.SUNDAY) {
result = 0;
} else if (dayOfWeek == Calendar.MONDAY) {
result = 1;
} else if (dayOfWeek == Calendar.TUESDAY) {
result = 2;
} else if (dayOfWeek == Calendar.WEDNESDAY) {
result = 3;
} else if (dayOfWeek == Calendar.THURSDAY) {
result = 4;
} else if (dayOfWeek == Calendar.FRIDAY) {
result = 5;
} else if (dayOfWeek == Calendar.SATURDAY) {
result = 6;
}
return result;
}
public int getCurYear() {
return curYear;
}
public int getCurMonth() {
return curMonth;
}
public int getNumColumns() {
return 7;
}
public int getCount() {
return 7 * 6;
}
public Object getItem(int position) {
return items[position];
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
Log.d(TAG, "getView(" + position + ") called.");
MonthItemView itemView;
if (convertView == null) {
itemView = new MonthItemView(mContext);
} else {
itemView = (MonthItemView) convertView;
}
// create a params
GridView.LayoutParams params = new GridView.LayoutParams(
GridView.LayoutParams.MATCH_PARENT,
120);
// calculate row and column
int rowIndex = position / countColumn;
int columnIndex = position % countColumn;
Log.d(TAG, "Index : " + rowIndex + ", " + columnIndex);
// set item data and properties
itemView.setItem(items[position]);
itemView.setLayoutParams(params);
itemView.setPadding(2, 2, 2, 2);
// set properties
itemView.setGravity(Gravity.LEFT);
if (columnIndex == 0) {
itemView.setTextColor(Color.RED);
} else {
itemView.setTextColor(Color.BLACK);
}
// set background color
if (position == getSelectedPosition()) {
itemView.setBackgroundColor(Color.YELLOW);
} else {
itemView.setBackgroundColor(Color.WHITE);
}
return itemView;
}
/**
* Get first day of week as android.text.format.Time constant.
* @return the first day of week in android.text.format.Time
*/
public static int getFirstDayOfWeek() {
int startDay = Calendar.getInstance().getFirstDayOfWeek();
if (startDay == Calendar.SATURDAY) {
return Time.SATURDAY;
} else if (startDay == Calendar.MONDAY) {
return Time.MONDAY;
} else {
return Time.SUNDAY;
}
}
/**
* get day count for each month
*
* @param year
* @param month
* @return
*/
private int getMonthLastDay(int year, int month){
switch (month) {
case 0:
case 2:
case 4:
case 6:
case 7:
case 9:
case 11:
return (31);
case 3:
case 5:
case 8:
case 10:
return (30);
default:
if(((year%4==0)&&(year%100!=0)) || (year%400==0) ) {
return (29); // 2월 윤년계산
} else {
return (28);
}
}
}
/**
* set selected row
*
* @param selectedRow
*/
public void setSelectedPosition(int selectedPosition) {
this.selectedPosition = selectedPosition;
}
/**
* get selected row
*
* @return
*/
public int getSelectedPosition() {
return selectedPosition;
}
}
class CalendarMonthView
package org.androidtown.calendar.month;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.GridView;
/**
* 그리드뷰를 상속하여 새로운 뷰를 정의한 클래스
* 선택한 일자를 표시하는 기능등을 효율적으로 처리하기 위해 정의한 클래스임
*
* @author Mike
*/
public class CalendarMonthView extends GridView {
/**
* 일자 선택을 위해 직접 정의한 리스너 객체
*/
private OnDataSelectionListener selectionListener;
/**
* 어댑터 객체
*/
CalendarMonthAdapter adapter;
/**
* 생성자
*
* @param context
*/
public CalendarMonthView(Context context) {
super(context);
init();
}
/**
* 생성자
*
* @param context
* @param attrs
*/
public CalendarMonthView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
/**
* 속성 초기화
*/
private void init() {
setBackgroundColor(Color.GRAY);
setVerticalSpacing(1);
setHorizontalSpacing(1);
setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
// 칼럼의 갯수 설정
setNumColumns(7);
// 그리드뷰의 원래 이벤트 처리 리스너 설정
setOnItemClickListener(new OnItemClickAdapter());
}
/**
* 어댑터 설정
*
* @param adapter
*/
public void setAdapter(BaseAdapter adapter) {
super.setAdapter(adapter);
this.adapter = (CalendarMonthAdapter) adapter;
}
/**
* 어댑터 객체 리턴
*
* @return
*/
public BaseAdapter getAdapter() {
return (BaseAdapter)super.getAdapter();
}
/**
* 리스너 설정
*
* @param listener
*/
public void setOnDataSelectionListener(OnDataSelectionListener listener) {
this.selectionListener = listener;
}
/**
* 리스너 객체 리턴
*
* @return
*/
public OnDataSelectionListener getOnDataSelectionListener() {
return selectionListener;
}
class OnItemClickAdapter implements OnItemClickListener {
public OnItemClickAdapter() {
}
public void onItemClick(AdapterView parent, View v, int position, long id) {
if (adapter != null) {
adapter.setSelectedPosition(position);
adapter.notifyDataSetInvalidated();
}
if (selectionListener != null) {
selectionListener.onDataSelected(parent, v, position, id);
}
}
}
}
댓글 ( 4)
댓글 남기기