2012. 8. 14. 17:09
안드로이드 - 그리드뷰 캘린더 안드로이드 이야기2012. 8. 14. 17:09
728x90
반응형
안드로이드 - 그리드뷰 캘린더
오늘은 그리드 뷰에 대해서 알아보았습니다.
원래 간단한 예제를 찾아서 가져다 쓰려고 했는데, 적합한 예제도 없고,
해서, 그리드뷰를 이용해서 기본적인 달력을 만들어 보았습니다.
결과적으로 만들어질 달력의 모습은 아래와 같습니다.
|
순서는 아래의 다섯단계입니다.
1. GridView selector XML 작성
2. Activity Layout XML 작성
3. 날짜 하나(Cell)에 해당하는 XML 작성
4. Adapter 작성
5. Activity Code 구현
1. GridView selector XML 작성 |
저장위치 : res/drawable
파일이름 : grideview_selector.xml
1
2
3
4 |
<? xml version = "1.0" encoding = "UTF-8" ?>
android:variablePadding = "false" > </ selector > |
이 selector xml 파일은 그리드뷰 자체에 기본적으로 있는 padding을 없애기 위해서 작성하는 것입니다.
2. Activity Layout XML 작성 |
저장위치 : res/layout
파일이름 : gv_calendar_activity.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 |
<? xml version = "1.0" encoding = "utf-8" ?>
android:orientation = "vertical"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
android:background = "#456789" >
<!-- Activity Layout XML -->
<!-- @author croute -->
<!-- @since 2011.03.08 -->
< TextView
android:text = "2011년 몇월"
android:textSize = "20sp"
android:id = "@+id/gv_calendar_activity_tv_title"
android:layout_height = "wrap_content"
android:layout_width = "fill_parent"
android:layout_marginTop = "20dp"
android:gravity = "center"
android:textColor = "#000"
android:textStyle = "bold" />
< GridView
android:id = "@+id/gv_calendar_activity_gv_calendar"
android:layout_width = "320dp"
android:layout_height = "320dp"
android:layout_marginTop = "30dp"
android:numColumns = "7"
android:stretchMode = "columnWidth"
android:listSelector = "@drawable/gridview_selector" />
< LinearLayout
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
android:orientation = "horizontal"
android:gravity = "center" >
< Button
android:id = "@+id/gv_calendar_activity_b_last"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:layout_weight = "1"
android:text = "지난달" />
< Button
android:id = "@+id/gv_calendar_activity_b_next"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:layout_weight = "1"
android:text = "다음달" />
</ LinearLayout > </ LinearLayout > |
달력을 만들것이기 때문에, 그리드뷰의 컬럼의 갯수를 7로 설정합니다.
3. 날짜 하나(Cell)에 해당하는 XML 작성 및 이미지 생성 |
XML 작성
저장위치 : res/layout
파일이름 : day.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 |
<? xml version = "1.0" encoding = "utf-8" ?> < LinearLayout
android:id = "@+id/day_cell_ll_background"
android:layout_width = "45dp"
android:layout_height = "53dp"
android:background = "@drawable/bg_day" >
<!-- 날짜 -->
< TextView
android:id = "@+id/day_cell_tv_day"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
android:paddingLeft = "3dp"
android:paddingTop = "2dp"
android:gravity = "center"
android:textSize = "18sp" />
<!-- /날짜 -->
</ LinearLayout > |
그리드뷰도 기본적으로는 리스트뷰이기 때문에(리스트뷰를 상속받았기때문에),
리스트뷰를 커스텀하던 것 처럼, cell(리스트 뷰의 경우 row)에 해당하는 XML 파일을 작성해줍니다.
이미지 생성
저장위치 : res/drawable
파일이름 : bg_day.9.png
(나인패치를 사용한 이미지 파일)
|
이 이미지는 나인패치를 사용한 것으로, 날짜 셀 하나의 배경으로 사용합니다.
4. Adapter 작성 |
저장위치 : me.croute.calendarexample/adapter
파일이름 : CalendarAdapter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162 |
package me.croute.calendarexample.adapter; import java.util.ArrayList; import me.croute.calendarexample.R; import me.croute.calendarexample.domain.DayInfo; 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.GridView; import android.widget.LinearLayout; import android.widget.TextView; /**
* BaseAdapter를 상속받아 구현한 CalendarAdapter
*
* @author croute
* @since 2011.03.08
*/ public class CalendarAdapter extends BaseAdapter {
private ArrayList<DayInfo> mDayList;
private Context mContext;
private int mResource;
private LayoutInflater mLiInflater;
/**
* Adpater 생성자
*
* @param context
* 컨텍스트
* @param textResource
* 레이아웃 리소스
* @param dayList
* 날짜정보가 들어있는 리스트
*/
public CalendarAdapter(Context context, int textResource, ArrayList<DayInfo> dayList)
{
this .mContext = context;
this .mDayList = dayList;
this .mResource = textResource;
this .mLiInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount()
{
// TODO Auto-generated method stub
return mDayList.size();
}
@Override
public Object getItem( int position)
{
// TODO Auto-generated method stub
return mDayList.get(position);
}
@Override
public long getItemId( int position)
{
return 0 ;
}
@Override
public View getView( int position, View convertView, ViewGroup parent)
{
DayInfo day = mDayList.get(position);
DayViewHolde dayViewHolder;
if (convertView == null )
{
convertView = mLiInflater.inflate(mResource, null );
if (position % 7 == 6 )
{
convertView.setLayoutParams( new GridView.LayoutParams(getCellWidthDP()+getRestCellWidthDP(), getCellHeightDP()));
}
else
{
convertView.setLayoutParams( new GridView.LayoutParams(getCellWidthDP(), getCellHeightDP()));
}
dayViewHolder = new DayViewHolde();
dayViewHolder.llBackground = (LinearLayout)convertView.findViewById(R.id.day_cell_ll_background);
dayViewHolder.tvDay = (TextView) convertView.findViewById(R.id.day_cell_tv_day);
convertView.setTag(dayViewHolder);
}
else
{
dayViewHolder = (DayViewHolde) convertView.getTag();
}
if (day != null )
{
dayViewHolder.tvDay.setText(day.getDay());
if (day.isInMonth())
{
if (position % 7 == 0 )
{
dayViewHolder.tvDay.setTextColor(Color.RED);
}
else if (position % 7 == 6 )
{
dayViewHolder.tvDay.setTextColor(Color.BLUE);
}
else
{
dayViewHolder.tvDay.setTextColor(Color.BLACK);
}
}
else
{
dayViewHolder.tvDay.setTextColor(Color.GRAY);
}
}
return convertView;
}
public class DayViewHolde
{
public LinearLayout llBackground;
public TextView tvDay;
}
private int getCellWidthDP()
{ // int width = mContext.getResources().getDisplayMetrics().widthPixels;
int cellWidth = 480 / 7 ;
return cellWidth;
}
private int getRestCellWidthDP()
{ // int width = mContext.getResources().getDisplayMetrics().widthPixels;
int cellWidth = 480 % 7 ;
return cellWidth;
}
private int getCellHeightDP()
{ // int height = mContext.getResources().getDisplayMetrics().widthPixels;
int cellHeight = 480 / 6 ;
return cellHeight;
}
} |
BaseAdapter를 상속받아 구현한 Calendar Adapter입니다.
5. Activity Code 구현 |
저장위치 : me.croute.calendarexample/activity
파일이름 : GVCalendarActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208 |
package me.croute.calendarexample.activity; import java.util.ArrayList; import java.util.Calendar; import me.croute.calendarexample.R; import me.croute.calendarexample.adapter.CalendarAdapter; import me.croute.calendarexample.domain.DayInfo; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.Button; import android.widget.GridView; import android.widget.TextView; /**
* 그리드뷰를 이용한 달력 예제
*
* @blog http://croute.me
* @link http://croute.me/335
*
* @author croute
* @since 2011.03.08
*/ public class GVCalendarActivity extends Activity implements OnItemClickListener, OnClickListener {
public static int SUNDAY = 1 ;
public static int MONDAY = 2 ;
public static int TUESDAY = 3 ;
public static int WEDNSESDAY = 4 ;
public static int THURSDAY = 5 ;
public static int FRIDAY = 6 ;
public static int SATURDAY = 7 ;
private TextView mTvCalendarTitle;
private GridView mGvCalendar;
private ArrayList<DayInfo> mDayList;
private CalendarAdapter mCalendarAdapter;
Calendar mLastMonthCalendar;
Calendar mThisMonthCalendar;
Calendar mNextMonthCalendar;
@Override
public void onCreate(Bundle savedInstanceState)
{
super .onCreate(savedInstanceState);
setContentView(R.layout.gv_calendar_activity);
Button bLastMonth = (Button)findViewById(R.id.gv_calendar_activity_b_last);
Button bNextMonth = (Button)findViewById(R.id.gv_calendar_activity_b_next);
mTvCalendarTitle = (TextView)findViewById(R.id.gv_calendar_activity_tv_title);
mGvCalendar = (GridView)findViewById(R.id.gv_calendar_activity_gv_calendar);
bLastMonth.setOnClickListener( this );
bNextMonth.setOnClickListener( this );
mGvCalendar.setOnItemClickListener( this );
mDayList = new ArrayList<DayInfo>();
}
@Override
protected void onResume()
{
super .onResume();
// 이번달 의 캘린더 인스턴스를 생성한다.
mThisMonthCalendar = Calendar.getInstance();
mThisMonthCalendar.set(Calendar.DAY_OF_MONTH, 1 );
getCalendar(mThisMonthCalendar);
}
/**
* 달력을 셋팅한다.
*
* @param calendar 달력에 보여지는 이번달의 Calendar 객체
*/
private void getCalendar(Calendar calendar)
{
int lastMonthStartDay;
int dayOfMonth;
int thisMonthLastDay;
mDayList.clear();
// 이번달 시작일의 요일을 구한다. 시작일이 일요일인 경우 인덱스를 1(일요일)에서 8(다음주 일요일)로 바꾼다.)
dayOfMonth = calendar.get(Calendar.DAY_OF_WEEK);
thisMonthLastDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
calendar.add(Calendar.MONTH, - 1 );
Log.e( "지난달 마지막일" , calendar.get(Calendar.DAY_OF_MONTH)+ "" );
// 지난달의 마지막 일자를 구한다.
lastMonthStartDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
calendar.add(Calendar.MONTH, 1 );
Log.e( "이번달 시작일" , calendar.get(Calendar.DAY_OF_MONTH)+ "" );
if (dayOfMonth == SUNDAY)
{
dayOfMonth += 7 ;
}
lastMonthStartDay -= (dayOfMonth- 1 )- 1 ;
// 캘린더 타이틀(년월 표시)을 세팅한다.
mTvCalendarTitle.setText(mThisMonthCalendar.get(Calendar.YEAR) + "년 "
+ (mThisMonthCalendar.get(Calendar.MONTH) + 1 ) + "월" );
DayInfo day;
Log.e( "DayOfMOnth" , dayOfMonth+ "" );
for ( int i= 0 ; i<dayOfMonth- 1 ; i++)
{
int date = lastMonthStartDay+i;
day = new DayInfo();
day.setDay(Integer.toString(date));
day.setInMonth( false );
mDayList.add(day);
}
for ( int i= 1 ; i <= thisMonthLastDay; i++)
{
day = new DayInfo();
day.setDay(Integer.toString(i));
day.setInMonth( true );
mDayList.add(day);
}
for ( int i= 1 ; i< 42 -(thisMonthLastDay+dayOfMonth- 1 )+ 1 ; i++)
{
day = new DayInfo();
day.setDay(Integer.toString(i));
day.setInMonth( false );
mDayList.add(day);
}
initCalendarAdapter();
}
/**
* 지난달의 Calendar 객체를 반환합니다.
*
* @param calendar
* @return LastMonthCalendar
*/
private Calendar getLastMonth(Calendar calendar)
{
calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), 1 );
calendar.add(Calendar.MONTH, - 1 );
mTvCalendarTitle.setText(mThisMonthCalendar.get(Calendar.YEAR) + "년 "
+ (mThisMonthCalendar.get(Calendar.MONTH) + 1 ) + "월" );
return calendar;
}
/**
* 다음달의 Calendar 객체를 반환합니다.
*
* @param calendar
* @return NextMonthCalendar
*/
private Calendar getNextMonth(Calendar calendar)
{
calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), 1 );
calendar.add(Calendar.MONTH, + 1 );
mTvCalendarTitle.setText(mThisMonthCalendar.get(Calendar.YEAR) + "년 "
+ (mThisMonthCalendar.get(Calendar.MONTH) + 1 ) + "월" );
return calendar;
}
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long arg3)
{
}
@Override
public void onClick(View v)
{
switch (v.getId())
{
case R.id.gv_calendar_activity_b_last:
mThisMonthCalendar = getLastMonth(mThisMonthCalendar);
getCalendar(mThisMonthCalendar);
break ;
case R.id.gv_calendar_activity_b_next:
mThisMonthCalendar = getNextMonth(mThisMonthCalendar);
getCalendar(mThisMonthCalendar);
break ;
}
}
private void initCalendarAdapter()
{
mCalendarAdapter = new CalendarAdapter( this , R.layout.day, mDayList);
mGvCalendar.setAdapter(mCalendarAdapter);
} } |
이제는 액티비티를 구현해 줍니다.
기본적으로 버튼들과 그리드뷰, 텍스트뷰에 대해 reference를 해주고,
데이터를 구성한 후, setAdapter를 통해서 화면에 보여줍니다.
6. 추가적으로 필요한 데이터 |
저장위치 : me.croute.calendarexample/domain
파일이름 : DayInfo.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 |
package me.croute.calendarexample.domain; /**
* 하루의 날짜정보를 저장하는 클래스
*
* @author croute
* @since 2011.03.08
*/ public class DayInfo {
private String day;
private boolean inMonth;
/**
* 날짜를 반환한다.
*
* @return day 날짜
*/
public String getDay()
{
return day;
}
/**
* 날짜를 저장한다.
*
* @param day 날짜
*/
public void setDay(String day)
{
this .day = day;
}
/**
* 이번달의 날짜인지 정보를 반환한다.
*
* @return inMonth(true/false)
*/
public boolean isInMonth()
{
return inMonth;
}
/**
* 이번달의 날짜인지 정보를 저장한다.
*
* @param inMonth(true/false)
*/
public void setInMonth( boolean inMonth)
{
this .inMonth = inMonth;
} } |
이제 달력을 화면에 보여줄 수 있습니다.
월 이동도 가능하고, 조금만 코드를 수정한다면, 모든 기계에 보여질 수 있는 달력을 만들 수 있다라는 것입니다!!
각 요일에 대한 클릭이벤트는 Activity Java 코드에 있는 onItemClick 메소드를 구현하면 됩니다.
예제 소스코드
728x90
반응형
'안드로이드 이야기' 카테고리의 다른 글
안드로이드 - 달력소스3 (0) | 2012.08.14 |
---|---|
안드로이드 - 달력 레이아웃 만들기 2 (0) | 2012.08.14 |
안드로이드 - S펜 SDK 소개 및 분석 (0) | 2012.08.13 |
안드로이드 - db를 csv파일로 변환 (0) | 2012.08.11 |
안드로이드 - Tutorial Code For Download (0) | 2012.08.11 |