2013년 10월 30일 수요일

Spinner widget customizing

이전 블로그에서 이전 함 (원본 글 2013/10/30 작성)

Spinner을 사용할 경우 android app theme에 맞춰 설정된 대로만 보여지는 관계로
별도의 App GUI에 맞춰 가야 할 경우 style 변경이 필요함.

style 변경은 action bar 의 style 수정과 유사하게 android widget의 SpinnerItem Style을 상속하여 수정하고 Spinner의 Adapter에 설정 하면 됨.


*참고로 ArrayAdapter 설정 시 spinner style이 오타임.


Create a custom adapter with a custom layout for your spinner.
Spinner spinner = (Spinner) findViewById(R.id.pioedittxt5);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
        R.array.travelreasons, R.layout.simple_spinner_item);
adapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
R.layout.simple_spinner_item
<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@android:id/text1"
    style="@style/spinnerItemStyle"
    android:singleLine="true"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ellipsize="marquee" />
R.layout.simple_spinner_dropdown_item
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@android:id/text1"
    style="@style/spinnerDropDownItemStyle"
    android:singleLine="true"
    android:layout_width="match_parent"
    android:layout_height="?android:attr/dropdownListPreferredItemHeight"
    android:ellipsize="marquee" />
In styles add your custom dimensions and height as per your requirement.
 <style name="spinnerItemStyle" parent="android:Widget.TextView.SpinnerItem">

  </style>

  <style name="spinnerDropDownItemStyle" parent="android:TextAppearance.Widget.TextView.SpinnerItem">

  </style>
share|improve this answer



Spinner를 수정한 예제

2013년 10월 26일 토요일

Dreaming in Code (드리밍 인 코드), "천국과 지옥을 넘나드는 소프트웨어 개발 이야기"

이전 블로그에서 이전 함 (원본 글 2013/10/26 작성)


드리밍 인 코드 :
천국과 지옥을 넘나드는 소프트웨어 개발 이야기
스콧 로젠버그 저/황대산 역 | 에이콘출판사



"Software is Hard."
책의 첫 챕터에서 나오는 글이고 
이 문구가 책의 결론이자 모든 S/W 개발 프로젝트의 결론인것 같다.

S/W 개발을 주업으로하는 입장에서 상당히 공감가는 글이고 국내, 해외, 개발자의 역량을 떠나서 S/W 프로젝트의 여러 시행 착오와 어려움을 엿볼 수 있는 책이다. 저자가 3자의 입장에서 프로젝트를 관찰하고 집필한 책이므로 객관적인 입장에서 볼 수 있어 좋은 것 같고 또한 S/W 프로젝트에서 manager, architecture, engineers, tester외에도 librarian이 별도로 있으면 좋겠다는 생각도 들기도 한다.

책의 내용은 OSAF (Open Source Application Foundation)에서의 Open Source PIMS application인 챈들러를 개발하는 과정을 기록한 내용이다. 하지만 저자가 챈들러 프로젝트의 끝까지 참여하지 못해 베타테스팅 까지만 기록 되어 있다.

책에서 보던 중 공감하는 일부를 개인적인 생각과 정리하여 나중에 보려고 함.


P.23
"소프트웨어는 골칫덩이다. ... 우리는 더 나은 소프트웨어를 꿈꾼다. 소프트웨어 프로젝트 관리 분야의 창시자라고 할 수 있는 프레데렉 P. 브룩스는 1987년 '은총알은 없다 No Silver Bullet'란 유명한 에세이에서 다음과 같은 말을 했다. "컴퓨터 프로그램을 개발하는 작업은 정말 어렵지만, 이를 한순간에 획기적으로 개선하는 방법은 영어 나타나지 않을 것입니다. 그저 수수한 정도의 점진적이고 꾸준한 진전만이 가능할 것입니다."

=> No Silver Bullet. 뭐든지 한번에 모든 것을 해결하는 것은 없다고 생각한다 더구나 보이지 않는 실체를 만들어야 하는 S/W 개발에서는 더더욱..
(TODO) 다시 읽어보기 


P.31
소프트웨어 시간에 관한 최초의, 그리고 가장 명쾌한 설명은 1975년에 프레데릭 브룩스가 쓴 "맨먼스 미신 The Mythical Man-Month"에서 찾아볼 수 있다. ... 개발 과정은 수많은 일정 지연과 비용 초과로 얼룩져 있었다. ... 브룩스의 팀은 일정 지연에 당황해서 마치 전투 인원을 증파하듯이 추가 개발자를 계속 투입했다. 하지만 놀랍게도 이렇게 투입된 인력은 프로젝트가 당면한 문제를 해결하기는 커녕 더 많은 문제들을 만들어낼 분이었다. 

=> 추가로 투입되는 인력은 프로젝트에 대한 이해와 개발환경 설정등의 비용이 발생하여 오히려 개발에 방해가 된다. 하지만 일정 지연으로 답답한 관리자 입장에서는 달콤한 방법이 아닐 수 없을 듯... 책은 다소 오래된 내용이고 따분하다.


P.39
성당과 시장

=> 사실 읽어보지는 않았으나 상당히 언급되는 책
(TODO) 읽어보기


P.70
이 장르의 최대 역작은 로버트 브리처의 "The Limits of Software"이다. ... 소프트웨어 프로젝트 역사상 최악의 실패로 손꼽히는 미 연방 항공국의 '진보된 자동화 시스템 AAS, Advanced Automation System" 프로젝트의 개발자 중 한 명이었다.

=> AAS는 S/W 개발 위기를 언급할 때 언제나 나오는 단골 프로젝트이다..
(TODO) 관련 논문 찾아보기


P.82
프레데릭 브룩스는 새로운 기술이나 설계를 도입할는 어떤 프로젝트에서도 "첫 번째 버전은 과감히 내다버릴 계획을 세워야 한다"고 충고했다. 첫번째에 마음에 쏙 드는 물건을 만드는 건 불가능에 가깝기 때문이다.

=> 보통 prototyping의 산출물로 나오는 prototype은 Throw-away prototype으로 생각하는게 맞다. 하지만 처음 결과물을 기반으로 개선해서 가는 형태의 Evolutionary prototyping가 더 reasonable하다고 생각할지 모르지만 나중에 뜯어고치는 비용도 만만치 않다.


P.113
파이썬과 조프 개발자들이 이미 만들어 놓은 것을 무시하고 새로 개발하는 일은 없었으면 좋겠습니다. 파이선과 조프는 이미 수년의 개발 과정을 거쳐왔으며, 이들 툴박스 안에는 훌륭한 기술이 보물처럼 잔뜩 숨어 있습니다.

P.119
원래 사용되는 질문은 "자체적으로 개발할 것인가, 상용 제품을 사다가 쓸 것인가, 기존 것을 빌려다 쓸 것인가?"이다. 하지만 기술적인 관점에서 '사서 쓰는 것'과 '빌려 쓰는 것'은 크게 다르지 않다. 이는 단지 상용 솔루션을 사용할 것인가, 오픈소스 솔루션을 쓸 것인가의 차이일 뿐이다.)

=> 새로운 solution을 사용할 때는 신중해야 한다. 개발 기간이 짧은 경우 당연히 숨겨진 버그나 부족한 feature로 고생을 하게 되고 개발 기간이 길더라도 유지보수가 제대로 되지 않는 경우 전자와 마찬가지라고 생각한다. 


P.125
종종 소프트웨어 개발자들은 '자사에서 직접 개발하지 않은 소프트웨어 사용을 거부하는' NIH Not Invented Here 신드롬에 시달리기도 한다.

=> 사실 좀 어려운 이슈다. 개발자라면 자기가 직접 만들기를 원할 것이고 가져다 쓸때는 비용과 시간을 절약하기 위해서 일 것이다. 상황에 따라서 다르겠지만 만약 직접 개발해서 적용하는 제품이 오랜시간동안 사용되어 유지보수 기간이 길어진다면 직접 개발하는 것도 괜찮다고 개인적으로 생각하고 가져다 쓸 경우 해당 소프트웨어가 2-3번의 상품화를 통해 검증 되었다면 가져다 써도 상관없을 것이라 생각되고...


P.159
소프트웨어 프로젝트를 관리하는 일에 있어 커다란 아이러니는 프로그래머들이 작업하는 대상이 한치 오차도 없는 완벽한 정확성으로 작동함에도 불구하고, 소프트웨어 개발 과정을 측정하는 일은 놀라울 정도로 어렵다는 점이다. ... 개발자의 업무량을 가장 계량적으로 측정하려면 코드의 줄수를 세면 된다. 하지만 이는 불충분할 뿐만아니라 지독할 정도로 오해의 여지가 많은 지표다.

허츠펠드는 매킨토시 개발 역사에 관해 쓴 "Revolution in the Valley, 실리콘 밸리의 혁명"에서 이렇게 말한다. "앳킨슨은 가능한 한 적은 양의 코드 줄 수를 평가의 척도로 사용하는 것은 불필요하게 긴 엉터리 코드를 작성하도록 장려하는 일이라고 생각했죠".

=> 앳킨슨의 의견에 절대 공감이다. 하지만 S/W 개발 경험이 있는 관리자도 자주 이런 방법을 사용한다는게 현실이다.


 P.162
어쩌면 문제의 근원은 관리 테크닉에 있는 것이 아니라, 소프트웨어 개발을 하는 사람들의 기질에 있는 것이 아닐까 하는 두려움이다. ... 프로그래머들과 커뮤니케이션하는 것은 놀라울 정도로 어렵다 ... 그들은 천재 괴짜이며 문제아다.

=> 일반적인 S/W Engineer가 아닌 geek, guru 같은 애들을 말하는 것이라고 생각한다. 기존 논문을 봤을 때는 생각보다 MBTI 결과에서 외향적인 성격을 가진 S/W engineer가 꽤 있었고 실제 S/W 개발에서는 외향적인 사람들이 더 좋은 역할을 보여줬던 것으로 기억한다. 
(TODO)  관련 논문확인 필요


 P.189
"모질라의 결과물은 우리보다 훨씬 앞서 있습니다. 이들 중 일부를 활용하면 우리의 개발 속도를 획기적으로 높이게 될 겁니다."

=> 앞에서 말한 것 처럼 상황에 따라서 다르겠지만 상품화 단계의 프로젝트에서는 단지 앞서 개발된 결과물이라고 완성되지 않은 것을 그냥 가져다 쓰면 검증에 문제가 될 가능성이 크다고 생각한다.
 (TODO) 모질라 재단 open source 프로젝트 확인하기

 P.245
2003년 11월 마이클 토이가 더난 후로 케이퍼는 비전을 제시하는 역할 뿐만 아니라 디자인과 개발에 있어 실질적인 관리자 역할을 맡고 있었다. ... 업무의 범주가 넓어져만 갔다. ... 케이퍼가 참석해야 할 미팅의 수는 늘어났고 이들 미팅에서 그가 눈에 띄게 힘들어하는 모습도 쉽게 눈에 띄었다. 

=> 개인적인 생각으로 프로젝트에서 관리자가 관리할 수 있는 팀원의 수는 7-8명이 적절한 것 같다. 사람이 많아지면 많아 질 수록 관리의 역할, 업무가 늘어나고 의사소통의 비용이 늘어나서 오히려 역효과를 내는 것 같다. 


 P.253
"개밥 먹기는 ... 서버 릴리스 시 마지막 몇개의 버그를 잡기 위해 내부적으로 상당히 적극적으로 수행하는 활동입니다. 제품 개발 초기 단계에서 부터 품질을 높이는 데 있어 큰 동기를 부여해 준다는 사실을 깨달았습니다."

=> 비록 모든 기능을 구현하여 문제를 발견하지 않도록 테스트 한다는 게 단점이긴 하지만 제품 개발에 열정을 가진 사람들이 이런 역할에 적절할 것 같다. 즉 자발적 동기를 가진 사람들.. 윗선으로 부터 타 부서에서 개발한 제품을 대상으로 베타테스팅을 하는 경우가 있는데 대부분 배타적이다.


P.270
"우리 관리자들이 종종 빠지곤 하는 함정은," ... "엔지니어들은 일을 마쳤다고 하는데 아파나와 디자인팀은 어리둥절해하는 상황입니다." 다르게 말하면, 기능은 동작할지도 모른다. 하지만 수많은 버그가 있고 인터페이스에는 디자인이 입혀져 있지도 않고, 아직도 산더미 같이 할일이 남아 있는 것이다.

=> 반성한다..ㅜㅜ 시작이 반이고 기능구현이 반이니.. 보통 기능 구현하면 끝이라고 생각한다. ㅜㅜ


P.302
2001년 워드 커닝햄과 켄트 벡 등 이 분야의 리더 17명이 유타주의 스키 리조트에 모여 일련의 연관성을 띠지만 저마다 다른 접근 방식에서 공통점을 찾으려 했다. ... 이 회합에서 사람들은 좀더 그럴듯한 이름을 만들어냈다. '애자일 소프트웨어 개발 방법론.' 그리고 다음과 같은 선언문도 발표했다.

=> 애자일 개발 방법론은 찾아봤지만 관련 역사는 몰랐었는데.. 애자일 관련 책을 읽어봐야 겠음. 
(TODO) 애자일 관련 기본 개론, 역사 책 찾아보기 

P.332
만약 당신이 프로그래머에게 버그를 보고한다면, 당신이 들을 첫마디는 이 말일 것이다. "그 문제가 반복해서 나타나나요?" .... 만약 그렇지 않다면 아마도 프로그래머는 어깨를 으쓱하면서 그 문제를 하드웨어 문제나 아니면 우주 광선 때문에 일어난 일 정도로 치부해 버릴지도 모른다.

=> 역시나 반성한다.. 난 이것 보다 더해서 확인하기 전에 먼저 화를 낸다 ㅜㅜ


P.368
2004년에는 마이크로소프트 윈도우 2000의 소스코드 일부가 인터넷을 통해 유출된 적이 있다. ... 매우 놀라웠던 것은 마이크로소프트의 프로그래머들이 소스코드에서 그들 자신과 그들의 도구, 그들의 동료, 그들이 개발한 제품을 심하게 꾸짖었다는 것이다

=> 재밋겟다. 나중에 나도 해봐야지 ㅎㅎㅎ
 (TODO) 해보기

 P.394
소프트웨어 개발에 있어 수많은 문제와 마찬가지로 챈들러의 반복되는 일정을 어떻게 처리할 것이냐는 문제는 '나누고, 정복하고, 미룬다 divide, conquer and punt'라는 방법으로 해결될 수 있음이 드러났다.

=> 스크럼 방법론을 쓰면서 정말 잘 와닫고 공감하는 것 중 하나이다. 다만 회사에서는 일정과 산출물을 정해두고 한다는게 함정.. ㅜㅜ

2013년 10월 21일 월요일

FragmentPagerAdapter, FragmentStatePagerAdapter 차이

이전 블로그에서 이전 함 (원본 글 2013/10/21 작성)

한 Activity에서 Navigation Drawer의 메뉴에 따라서 Fragment들을 업데이트 해줘야할 필요가 있어
FragmentPagerAdapter 를 사용해서 구현하던 중 Fragment가 제대로 업데이트 되지 않는 현상 발생..

아무래도 FragmentPagerAdapter를 잘못 상속 구현한 것으로 보여 여기저기 찾아봄.
(참고했던 Android tab swipe sample code가 FragmentPagerAdapter + ViewPager를 사용하고 있어 이것을 그대로 사용했었음.)

결론적으로 fragment를 바로 destroy하지 않고 재사용하는 FragmentPagerAdapter 대신 FragmentStatePagerAdapter를 사용하고 getItemPosition()을 override하여 제거된 Fragment에 대해서 POSITION_NONE를 리턴하게 하여 구현 함.

관련 설명 및 링크는 다음과 같다.

[API documentation for FragmentPagerAdapter and FragmentStatePagerAdapter]

: Fragment manager에서 등록된 Fragment들을 최대한 영구적으로 가지고 있도록 구현되어 있고
소규모의 static한 fragment들을 사용할 경우에 추천되는 adapter.
* view가 invisible한 상황에서 destroyed되더라도 fragment들은 영구적으로 남아 있어 메모리를 차지함.
public abstract class

FragmentPagerAdapter

extends PagerAdapter 
   ↳

   ↳
android.support.v4.app.FragmentPagerAdapter

Class Overview


Implementation of PagerAdapter that represents each page as a Fragment that is persistently kept in the fragment manager as long as the user can return to the page.
This version of the pager is best for use when there are a handful of typically more static fragments to be paged through, such as a set of tabs. The fragment of each page the user visits will be kept in memory, though its view hierarchy may be destroyed when not visible. This can result in using a significant amount of memory since fragment instances can hold on to an arbitrary amount of state. For larger sets of pages, consider FragmentStatePagerAdapter.
When using FragmentPagerAdapter the host ViewPager must have a valid ID set.
Subclasses only need to implement getItem(int) and getCount() to have a working adapter.



: FragmentPagerAdapter 에 비해 다소 많은 Fragment들을 관리해야 할 경우 추천되는 Adapter. listview와 유사한 behavior를 가지고 등록된 Fragment들이 이상 보이지 않을 경우 saved state 만을 보관하고 destroyed 함.
* Fragment들을 동적으로 create/destory 하므로 page switch시 overhead 발생.
public abstract class

FragmentStatePagerAdapter

extends PagerAdapter 
   ↳

   ↳
android.support.v4.app.FragmentStatePagerAdapter

Class Overview


Implementation of PagerAdapter that uses a Fragment to manage each page. This class also handles saving and restoring of fragment's state.
This version of the pager is more useful when there are a large number of pages, working more like a list view. When pages are not visible to the user, their entire fragment may be destroyed, only keeping the saved state of that fragment. This allows the pager to hold on to much less memory associated with each visited page as compared to FragmentPagerAdapter at the cost of potentially more overhead when switching between pages.
When using FragmentPagerAdapter the host ViewPager must have a valid ID set.
Subclasses only need to implement getItem(int) and getCount() to have a working adapter.


[기타 관련 링크]

like miller님의 "ViewPager를 사용해 보자2"

- 비교 및 FragmentPagerAdapter 예제, FragmentStatePagerAdpater 예제


  • Android FragmentStatePagerAdapter
  • Android FragmentPagerAdapter
  • Android FragmentPagerAdapter vs FragmentStatePagerAdapter




  • - 이건 좀 다른 얘기 일 수도 있지만 그래도 알아두면 유용할듯

    : 질문자는 Fragment 들이 업데이트 안되는 현상을 getItemPosition(Object object) 를 override하여 POSITION_NONE 를 항상 하여 무조건 fragment들을 재생성하여 업데이트 되도록 하였으나
    밑에 답변에서 해당 상황에서는 FragmentPagerAdpater, FragmentStatePagerAdapter를 상속할 경우 getItem()만을 override하고 그 외 API는 건들지 말라는 지적과 Fragment들의 업데이트?를 위해서는 FragmentStatePagerAdapter를 사용하라는 답변..

    Google API documentation에서 보듯이 위 Adapter들을 사용할 경우 두 API들( getItem(), getCount() )을 override 하는 것이 맞겠고 사용하는 Fragment들의 사용주기와 갯수에 따라서 Adapter들을 고르는게 맞을 것 같음.
    그리고 참고로 override한 getItemPosition()에서 argument(object)에 대해서 POSITION_NONE을 리턴할 경우 해당 object는 삭제가 되어야 하지만 이것은 FragmentStatePagerAdapter에서만 가능할 것 같음.

    2013년 10월 11일 금요일

    (link) 안드로이드(Android) 에서 layout_gravity 와 gravity 속성차이 알아보기

    이전 블로그에서 이전 함 (원본 글 2013/10/11 작성)

    맨날 헷갈려..


    안드로이드(Android) 에서 layout_gravity 와 gravity 속성차이 알아보기

    By 녹두장군

     Layout_gravity : 부모 컨테이너의 여유공간을 활용하여 뷰를 배치한다.
    Gravity : 뷰내에 여유공간을 활용하여 글자나 이미지등을 배치한다.

    설명에서 두 속성의 차이점은 layout 의 정렬 속성이냐 뷰에서의 정렬
    속성이냐 이다. Layout 에 포함되어있는 layout 이나 뷰등의 컨트롤을
    정리할 때 쓰고 그런 컨트롤중 뷰를 상속받아 만든 것들의 정렬은
    Gravity 속성을 쓰는 것이다.

    Gravity 속성을 사용하기 위해서는 컨테이너와 컨트롤들의 layout_height
    Layout_width 속성이 wrap_content 가 되야 한다. 그래야 여유 공간이 생기기
    때문이다. 가로로 정렬하고 싶다면 layout_width = 'wrap_content' 가 되어
    있어야 하고 세로로 정렬하고 싶다면 layout_height = 'wrap_content' 로 셋팅
    되어야 한다. match_parent 는 여유공간없이 꽉 채우기 때문에 정렬을
    할수 없는 것이다.

    안드로이드 개발 시 이분 사이트는 정말 유용하다
    검색 시에도 항상 상위권에 링크되어 있을 정도로 여러 주제를 자세히 다루고 있음.

    2013년 10월 10일 목요일

    ScrollView 내의 삽입된 ListView의 height가 조절되지 않는 현상

    이전 블로그에서 이전 함 (원본 글 2013/10/10 작성)

    예전에 경험하고 그냥 넘어갔었는데..
    오늘 다시 같은 것을 가지고 삽질 했음. 정리의 필요성!!!을 새삼 느낌. ㅜㅜ

    <ScrollView>
    ...
       <ListView>
    </ScrollView>

    와 같은 경우 ListView의 크기가 하나의 item 크기로 고정되어 버리거나 의도한 대로 보이지 않는 현상이 발생

    Android에서는 ScrollView를 설명할 때 다음과 같은 언급을 하고 있다.

     You should never use a ScrollView with a ListView, because ListView takes care of its own vertical scrolling. Most importantly, doing this defeats all of the important optimizations in ListView for dealing with large lists, since it effectively forces the ListView to display its entire list of items to fill up the infinite container supplied by ScrollView.

    ListView와 ScrollView는 각자 vertical scrolling을 관리하므로 서로 간섭을 일으켜서 원치 않는 결과가 발생된다. 사실 내가 본건 scrollview가 listview안에 들어가 있는게 아니라 반대의 경우라서 아마도 하나의 item 크기로 listview가 고정된게 아닌가 생각됨..

    만약 위의 상황에서 ScrollView에 android:fillViewport="true" 속성을 주게 되면 ScrollView의 height가 parent view에 맞춰지게 되어 ListView도 view에 맞춰 나오긴 하지만 정작 scroll이 안된다. 
    해당 option은 ScrollView 내의 view들의 height가 parent의 height에 도달하지 않을 때 강제로 늘리는 방법이지만 view hierachy상에 ListView가 들어 있는 상황에서는 ListView의 scrolling 계산에 영향을 주어 ScrollView의 height는 바로 변경되더라도 의도한 대로 ListView가 동작하지 않는 것으로 추측..


    이를 회피하는 방법으로는 다음과 같은 방법들이 있다.
     1. scrollview의 내용들을 listview의 header로 설정하는 방법
     2. scrollview와 listview를 분리해서 사용하는 방법
     3. scrollview의 height를 재 계산해서 업데이트 해주는 방법.

    개인적으로는 2번 추천...

    1, 2번 방법


    I would recommend you to put the ScrollView Content as HeaderView in the ListView or do you explicitly want to have two separated scrollable areas on screen?
    Example for putting the content of the scroll view in the list view as header (one single scrollable area):
    public void onCreate(Bundle s){
        setContentView(R.id.yourLayout);
    
        ListView listView = (ListView) findViewById(R.id.listView);
    
        // Set the adapter before the header, because older 
        // Android version may have problems if not
    
        listView.setAdapter(new YourAdapter());
    
        // Add the header
        View header = inflater.inflate(
                R.layout.you_layout_that_was_in_scrollview_before, null, false); 
    
        listView.addHeaderView(header);
    
    }
    The layout of the activity would look like that:
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/frameLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    
        <ListView  android:id="@+id/listView" 
        android:layout_height="match_parent" 
        android:layout_width="match_parent"
        android:background="#FFF"/>
    </LinearLayout>
    If you want two scrollable areas, you should work with layout weight:
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/frameLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <ScrollView 
      android:id="@+id/marketDetailScrollView"
      android:layout_width="match_parent"
      android:layout_height="0dp"
      android:layout_weight="1" >
      <!-- ScrollViewContent -->
    </ScrollView>
    <ListView  android:id="@android:id/list" 
    android:layout_height="0dp" 
    android:layout_width="match_parent"
    android:background="#FFF"
    android:layout_weight="1"/>
    </LinearLayout>
    share|improve this answer

    [안드로이드/Android ListView Header, Footer 설정 하기 ~! by 아라비안왕자]
     : 2번의 예제로는 잘 되어 있는듯.


    * 만약 header, footer 설정 후 실행 시 ClassCaseException 발생 시
    ListView에서 getAdapter() 함수가 존재하는지 확인하고 이를 제거 해줘야 한다.

    01-01 14:41:27.467: E/AndroidRuntime(19481): FATAL EXCEPTION: main
    01-01 14:41:27.467: E/AndroidRuntime(19481): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.xxx.yyy/com.xxx.yyy.createsession.ZzzActivity}: java.lang.ClassCastException: android.widget.HeaderViewListAdapter cannot be cast to android.widget.BaseAdapter
    01-01 14:41:27.467: E/AndroidRuntime(19481):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2247)
    01-01 14:41:27.467: E/AndroidRuntime(19481):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2297)
    01-01 14:41:27.467: E/AndroidRuntime(19481):  at android.app.ActivityThread.access$700(ActivityThread.java:152)
    01-01 14:41:27.467: E/AndroidRuntime(19481):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1282)
    01-01 14:41:27.467: E/AndroidRuntime(19481):  at android.os.Handler.dispatchMessage(Handler.java:99)
    01-01 14:41:27.467: E/AndroidRuntime(19481):  at android.os.Looper.loop(Looper.java:137)
    01-01 14:41:27.467: E/AndroidRuntime(19481):  at android.app.ActivityThread.main(ActivityThread.java:5329)
    01-01 14:41:27.467: E/AndroidRuntime(19481):  at java.lang.reflect.Method.invokeNative(Native Method)
    01-01 14:41:27.467: E/AndroidRuntime(19481):  at java.lang.reflect.Method.invoke(Method.java:511)
    01-01 14:41:27.467: E/AndroidRuntime(19481):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
    01-01 14:41:27.467: E/AndroidRuntime(19481):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
    01-01 14:41:27.467: E/AndroidRuntime(19481):  at dalvik.system.NativeStart.main(Native Method)
    01-01 14:41:27.467: E/AndroidRuntime(19481): Caused by: java.lang.ClassCastException: android.widget.HeaderViewListAdapter cannot be cast to android.widget.BaseAdapter




    3번 방법, 사실 해보지는 않았다.

    Android ListView in ScrollView Problem

    This is the method to re-calculate listview height to fix the problem.
    public static void setListViewHeightBasedOnChildren(ListView listView) {
      ListAdapter listAdapter = listView.getAdapter();
      if (listAdapter == null) {
       // pre-condition
       return;
      }
     
      int totalHeight = 0;
      int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.AT_MOST);
      for (int i = 0; i < listAdapter.getCount(); i++) {
       View listItem = listAdapter.getView(i, null, listView);
       listItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
       totalHeight += listItem.getMeasuredHeight();
      }
     
      ViewGroup.LayoutParams params = listView.getLayoutParams();
      params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
      listView.setLayoutParams(params);
      listView.requestLayout();