안드로이드

 

 

 

 

 

 

 

                

 

 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);
			}
			
			
		}
		
	}
	
}

 

 

 

 

 

about author

PHRASE

Level 60  머나먼나라

헤엄 잘 치는 놈 물에 빠져 죽고, 나무에 잘 오르는 놈 나무에서 떨어져 죽는다 , 아무리 기술이나 재주가 좋아도 한 번 실수는 있다는 뜻.

댓글 ( 4)

댓글 남기기

작성