안녕하세요.
열심히 안드로이드를 공부하다가 이번에 GridView를 이용해 달력을 만들어 봤습니다.
각 월(month)의 일(day)자 개수를 GridView로 표현을 했는데요.
GridView의 가로 사이즈는 화면 사이즈를 계산해서 7컬럼씩 맞게하고,
GridView의 세로 사이즈의 경우엔 고정시켜놓고 화면 사이즈보다 높으면 스크롤되게 해놨습니다.
만들어본 달력 어플을 실행해서 GridView를 상/하로 스크롤 하지 않을때는 문제없는 어플인데.
스크롤할때 그려주는 순서가 1일 부터 시작하는게 아니라 랜덤하게 바꿔서 시작하더라구요.
캡춰한 사진으로 보여드릴께요~
Loading images...
①번 이미지가 처음 실행시켰을때의 화면입니다. 스크롤하지 않았을때나 원하는 날짜를 터치 하지 않았을
때는 문제 없이 돌아가더군요.
②번 이미지는 처음 실행시킨후에 GridView에서 첫번째 컬럼(SUN)을 제외하고 다른 부분을 터치해서 선택하면 이상하게 계속
첫번째 컬럼이 선택되어졌다고 표시가 되네요. 선택되어진 영역만 표시가 저렇게 될뿐이고 터치된 값은 Toast로 출력해보니
첫번째 컬럼의 값이 아닌 터치한곳의 컬럼 값이 표시되구요.
③번 이미지는 GridView를 상/하로 스크롤했을때 발생되는 문제입니다. 각 컬럼별로 ImageView를 Custom 해서 객체를 생성하고요.
BaseAdapter를 상속받은 Class에서 오버라이드된 GetView에서 postion을 받아 ImageView를 생성할때 넘겨 줘서 그려주는 position 순서를 확인해보니. 처음에는 문제없이 0 ~ 해당달의 끝 일(day) 까지 순서대로 그려주는것 같은데 상/하로 스크롤하다보면 어느 순간엔가 이 순서가 뒤죽박죽이 되더군요. 그려주는 순서가 틀어진다는건 알았는데 원인을 도저히 못찾겠습니다. ㅜㅠ
아래는 제가 GridView를 사용한 간략한 메소드 입니다.
Activity를 상속받은 Diary.class
public void setGridView(){ GridView gridview = (GridView)findViewById(R.id.gv_dayView); gridview.setAdapter(new ImageAdapter(this, sltDate, iColumnWidth)); gridview.setOnItemClickListener(new OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> parent, View v, int pos, long id) { Toast.makeText(PetDiary.this, ""+pos, Toast.LENGTH_SHORT).show(); } }); }
ImageAdapter를 생성할때 넘겨주는 값은 현재 선택된 년/월을 저장한 배열(sltDate)과 GridView의 컬럼별 Width 크기를 저장한
iColumnWidth 입니다.
BaseAdapter를 상속받은 ImageAdapter.class
public View getView(int position, View convertView, ViewGroup parent) { CustomImage imageView = null; if(convertView == null){ imageView = new CustomImage(mContext, position, iDate, iColumnWidth); }else{ imageView = (CustomImage) convertView; } return imageView; }
CustomImage를 생성할때 넘겨주는 값은 getView에서 받은 position 과 선택되어진 년/월에서 계산하여 시작요일등을 저장한
iDate와 iColumnWidth를 그대로 넘겨줍니다.
main.xml 에서 GridView
<GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gv_dayView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:numColumns="7" android:verticalSpacing="5dp" android:stretchMode="columnWidth" android:gravity="center" />
아직 공부를 시작한지 별로 되지 않아 이 문제에 대해서 어떤걸 어떻게 질문해야할지 참으로 애매하더군요.
혼자서 이것저것 해보다가 도저히 해답을 찾질 못해서 이렇게 질문드립니다. ㅜㅠ
지저분하지만 소스도 압축해서 올릴께요~
p.s
안드로이드 펍을 이용하면서 하는 첫번째 질문이라 공지를 읽고 제목을 정해보려 했는데...
도저히 딱 맞는 제목을 정하지 못하겠어서 이렇게 올리는걸 양해해 주세요^^
우선 경험에 의한 글로 말씀드리자면 gridview 자체가 결론적으론 Adapter의 getView 함수를 호출해서
생기시는 문제인듯한데요 getView를 부르는건 안드로이드 시스템에서 부르는거라 컨트롤 할 수 없는걸로 알고있고요,
불리우는 횟수를 그나마 적게 불리게 하는건 이따금식 xml에서 fill_parent 로 통해서 1회만 불리우게 한다라는
글을 얼핏 본거 같지만 어째든 화면 상에서 re draw를 하게된다면
불리울때마다 가지고 있던 데이터를 표기하진 않고 말그대로 View를 부를 뿐이기 때문에 데이터 유지는 직접적으로
저장하고 있는 배열의 position을 가져와서 다시 데이터 setting을 통해서 유지시켜줘야 하는걸로 알고있습니다.
알고 있는게 이정도 이네요 ..ㅎ
그안에 드러갈 xml도 커스텀 list 일때는 당연히 child 로 xml을 만들고 값을 줬는데요. 궁금하점은 해당 child 에 xml 값을
dip 식으로 주게된다면 포지션 값이 엉망으로 안불린다고 말씀하신건가요? 또 , inflater 가 null일때는 새로 생성시켜주는게
getView 에서 해주는 일로 알고있는데요. 포지션 값이 잘 불리운다는게 잘 이해가 안되는데요. 좀더 확실한 답을 알고 싶네요.
제가 이해를 못해서 getView 에서 불리우는 원리를 알고싶다는 거죠... 사이즈가 명확하다고 해버리니셔서 너무 막연하네요.