뭐 고작 ListView에 index 넣는 걸로 엄청 오래 끌었는데... 무튼 이제 거의 다왔음요.

전편 필요한 분.
2012/03/07 - [Android Study] - Android Study ListView Indexer 5편 

Layout 파일 내용.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/header"
        android:layout_width="match_parent"
        android:layout_height="25dip"
        android:clickable="false"
        android:background="@*android:drawable/dark_header"
        android:gravity="center_vertical"
        android:focusable="false"
        android:visibility="gone">

        <TextView
            android:id="@+id/head"
            android:layout_width="56dip"
            android:layout_height="wrap_content"
            android:textStyle="bold"
            android:textColor="@*android:color/dim_foreground_dark"
            android:textSize="14sp"
            android:gravity="center"/>
    </LinearLayout>

    <TextView
        android:id="@+id/text1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:minHeight="?android:attr/listPreferredItemHeight"
        android:gravity="left|center_vertical"
        android:layout_weight="1"
        android:textAppearance="?android:attr/textAppearanceMedium"/>
</LinearLayout>
붉은 색 부분이 index 표현을 위해서 추가된 code임. Layout 설명은 생략 하도록 하겠음.
IconAdapter에 추가된 함수

private void bindSectionHeader(View itemView, int position) {
    final int section = getSectionForPosition(position);
    LinearLayout header = (LinearLayout) itemView.findViewById(R.id.header);
    TextView head = (TextView) itemView.findViewById(R.id.head);
    if (getPositionForSection(section) == position) {
        String title = (String)mIndexer.getSections()[section];
        head.setText(title);
        header.setVisibility(View.VISIBLE);
    } else {
        header.setVisibility(View.GONE);
    }
}

Index 표시하는 부분 임 그럼 이 함수를 어디서 호출 해주는 것이냐 하면.

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    mCursor.moveToPosition(position);
    if (convertView == null) {
        convertView = newView(mContext, mCursor, parent);
    }
    bindView(convertView, mContext, mCursor);
    bindSectionHeader(convertView, position);
    return convertView;
}

이렇게 CursorAdapter 에 기본 함수 getView에서 호출 하도록 만들면 땡!
그러면 Adapter는 어떻게 초기화 하냐 하면.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.list_content);

    mAdapter = new IconAdapter(this, null);
    mList = (ListView) findViewById(android.R.id.list);
    mList.setAdapter(mAdapter);
    mList.setOnItemClickListener(this);

    Cursor cursor = getContentResolver().query(PracticeColumns.CONTENT_URI, 
    new String[] {PracticeColumns.ID, PracticeColumns.DATA}, null,
    null, PracticeColumns.DATA + " ASC");
    mAdapter.changeCursor(cursor);
}

Adapter 에서 changeCursor를 호출하면 땡!

이런 DB를 출력하면

이렇게 출력됨.


보통 Code를 통째로 공개하지는 않지만... 흠흠 이번엔 특별히 내가 귀찮으므로... 첨부~

AndroidList.zip


'Android' 카테고리의 다른 글

Android Custom Widget 만들기 2편  (0) 2012.04.12
Android Custom Widget 만들기 1편  (1) 2012.04.12
Android Study ListView Indexer 5편  (0) 2012.03.07
Android Study ListView Indexer 4편  (0) 2012.03.07
Android Study ListView Indexer 3편  (0) 2012.03.07
전편 필요한분
2012/03/07 - [Android Study] - Android Study ListView Indexer 4편

여기 까지 해놓으면 대충 기본은 완성 해둔 상태 임.
이제 mIndexer 초기화와 사용 법을 알려 주겠음요.

여기서 부터는 아래 글 안보고 온 분들은 멘탈 붕괴될테니 꼭 보시길...
2012/02/08 - [Android Study] - Android List에 index를 표시해보자 1편 

PracticeIndexer 초기화

        // CursorAdapter 에서 제공하는 기본 함수 Cursor 변경 하고 싶을때 호출하면됨
        @Override
        public void changeCursor(Cursor cursor) {
            super.changeCursor(cursor);
            updateIndexer(cursor);
            mCursor = cursor;
        }
 
        // Indexer 초기화 함수
        private void updateIndexer(Cursor cursor) {
            // cursor가 null 이면 초기화 종료 
            if (cursor == null) {
                mIndexer = null;
                return;
            }
            // Provider 에서 만들어 준 Indexer 얻어 오기. 
            Bundle bundle = cursor.getExtras();
            // 붉은색 긁씨는 꼴릿한 데로 작성해도 됨 단 Provider와 동일하게 설정해야 함. 
            // bundle에 내용이 있으면 PracticeIndexer 초기화 
            if (bundle.containsKey(PracticeColumns.EXTRA_DATA_INDEX_TITLES)) {
                String sections[] =
                    bundle.getStringArray(PracticeColumns.EXTRA_DATA_INDEX_TITLES);
                int counts[] = bundle.getIntArray(PracticeColumns.EXTRA_DATA_INDEX_COUNTS);
                // PracticeIndexer 초기화
                mIndexer = new PracticeIndexer(sections, counts);
            } else {
                mIndexer = null;
            }
        }


예전에 index 관련 내용을 잘 따라 오셨다면 요기 까지는 무난 하게 완성 할 꺼임 담은 사용 법.

ListView에 사용할 layout 파일을 수정 해야 함.
Index를 listView에 일일이 add 해도 되긴 하지만 그랬다간 position이 미친듯이 꼬일 꺼임.
추천 하는 방법으로는 layout에 해더부분을 만들고 Visibility를 gone 상태로 항시 유지 하는 것임.

To be continue...

'Android' 카테고리의 다른 글

Android Custom Widget 만들기 1편  (1) 2012.04.12
Android Study ListView Indexer 6편  (3) 2012.03.07
Android Study ListView Indexer 4편  (0) 2012.03.07
Android Study ListView Indexer 3편  (0) 2012.03.07
Android Study ListView Indexer 2편  (1) 2012.03.07
전편 필요한 분.
2012/03/07 - [Android Study] - Android Study ListView Indexer 3편

PracticeIndexer class 내용 입니당.
public class PracticeIndexer implements SectionIndexer {
    // Index 내용
    private final String[] mSections;
    // Index 위치 
    private final int[] mPositions;
    // 최종 index 위치 
    private final int mCount;

    public HistortSectionIndexer(String[] sections, int[] counts) {
        // 생성자에서 Index 내용, 위치 배열 설정 null 이면 그냥 종료
        if (sections == null || counts == null) {
            throw new NullPointerException();
        }
        // Index 내용, 위치 배열 크기가 다르면 그냥 종료
        if (sections.length != counts.length) {
            throw new IllegalArgumentException(
                    "The sections and counts arrays must have the same length");
        }

        // Index 내용 초기화
        this.mSections = sections;
        // 위치는 같은 index를 사용 하는 것이 몇개 인지 counting 해서 전달 함.
        // 그래서 count를 일일이 더해야 실제 위치가 나옴. 위치 배열 새로 생성
        mPositions = new int[counts.length];
        int position = 0;
        for (int i = 0; i < counts.length; i++) {
            // Index 내용이 null 이면 공백으로 초기화 
            if (mSections[i] == null) {
                mSections[i] = " ";
            } else {
                // Index 내용에 공백 있으면 제거
                mSections[i] = mSections[i].trim();
            }
            // Index 위치 초기화
            mPositions[i] = position;
            // counting 된 값 더하기. 
            position += counts[i];
        }
        // Index의 최종 위치 지정 
        mCount = position;
    }

    // Index 내용 반환
    @Override
    public Object[] getSections() {
        return mSections;
    }

    // Index 위치 반환
    @Override
    public int getPositionForSection(int section) {
        if (section < 0 || section >= mSections.length) {
            return -1;
        }

        return mPositions[section];
    }

    // Index 위치 내용을 binarySearch 해서 배열 index 반환
    @Override
    public int getSectionForPosition(int position) {
        if (position < 0 || position >= mCount) {
            return -1;
        }

        int index = Arrays.binarySearch(mPositions, position);
        /*
         * Consider this example: section positions are 0, 3, 5; the supplied
         * position is 4. The section corresponding to position 4 starts at
         * position 3, so the expected return value is 1. Binary search will not
         * find 4 in the array and thus will return -insertPosition-1, i.e. -3.
         * To get from that number to the expected value of 1 we need to negate
         * and subtract 2.
         */
         // 위 코멘트는 Google 꺼... 내용인 즉슨 예를 들어 인덱스 위치가 0,3,5 이면
         // 현재 위치가 4면 가까운 시작 위치가 3이니깐 1이 반환 되야함
         // 근데 Binary search에 의해서 4가 나옴
         // 그러니깐 -3이 반환되게 해서 4 + (-3) 하면 1이 나오게 됨.
        return index >= 0 ? index : -index - 2;
    } 


이 코드역시 google base code를 따온것 이구요.
힘드니께 담 이야기는 담편으로~
 

'Android' 카테고리의 다른 글

Android Study ListView Indexer 6편  (3) 2012.03.07
Android Study ListView Indexer 5편  (0) 2012.03.07
Android Study ListView Indexer 3편  (0) 2012.03.07
Android Study ListView Indexer 2편  (1) 2012.03.07
Android Study ListView Indexer 1편  (0) 2012.03.07

후~ 전편은 여기로!
2012/03/07 - [Android Study] - Android Study ListView Indexer 2편 

아흥 슬슬 어케 마무리 지어야 할지 매우 난감하네...
private class IconAdapter extends CursorAdapter implements SectionIndexer {
    private SectionIndexer mIndexer;
    
@Override
    public int getPositionForSection(int sectionIndex) {
        if (mIndexer == null) {
            return -1;
        }
        return mIndexer.getPositionForSection(sectionIndex);
    }
 
    @Override
    public int getSectionForPosition(int position) {
        if (mIndexer == null) {
            return -1;
        }
        return mIndexer.getSectionForPosition(position);
    }

    @Override
    public Object [] getSections() {
        if (mIndexer == null) {
            // 이거 null 리턴하면 200% 에러 발생함. 그냥 요롷게 주는게 속편함.
            return new String[] { " " };
        } else {
            return mIndexer.getSections();
        }
    } 
}
정말 별거 없는 내용임... 그냥 mIndexer 객체가 null 일 경우만 정해 주면 알아서 처리가 됨. 참 쉽죠잉~ 
다음 편은 PracticeIndexer class 내용 입니당~

'Android' 카테고리의 다른 글

Android Study ListView Indexer 5편  (0) 2012.03.07
Android Study ListView Indexer 4편  (0) 2012.03.07
Android Study ListView Indexer 2편  (1) 2012.03.07
Android Study ListView Indexer 1편  (0) 2012.03.07
LayoutInflater에 대하여...  (0) 2012.02.15
전편 필요 한분 ㄱㄱㅆ
2012/03/07 - [Android Study] - Android Study ListView Indexer 1편 

나는 늘 이게 문제인듯 ㅍㅍ 발행 해놓고 한동안 잠적질?? (마치 왕창 똥싸놓고 튀는 느낌ㅋ)
우리 이제 후후 실전 code를 짜보아요~ let's go!

Base 뼈대 Code.
private class IconAdapter extends CursorAdapter implements SectionIndexer {
    private PracticeIndexer mIndexer;
    @Override
    public int getPositionForSection(int section) {
        return 0;
    }

    @Override
    public int getSectionForPosition(int position) {
        return 0;
    }

    @Override
    public Object[] getSections() {
        return null;
    }

위 뼈대 code만 체우면 제대로 된거 나올꺼 같은 느낌이 마구마구 샘솓음 으캬~
Indexer 사용 하려면 기본 뼈대니까 그냥 외워버리...기는 너무 큰가?
별거 없음 그냥 위에 @Override 함수하고 PracticeIndexer 만 체워 넣으면 되는 거니깐 너무 겁먹지 마시고..

PracticeIndexer class는 SecticeIndexer를 상속 받은 class

getSectionForPosition 함수는 현재 ListView position을 넣으면 해당 배열 위치가 반환 됨
getPositionForSection 함수는 현재 section 배열 위치를 넣으면 해당 position이 반환 됨

요지는  getSectionForPosition 이걸로 현재 section 위치 얻어옴. 이 위치에 다음 section의 위치를 얻고 싶응 께 getPositionForSection 요걸로 얻어 오는 거임.
왜 이렇게 하냐면 현재 List의 위치에 sectionIndexer가 끝인지 시작인지, 다음 껀지 모르니까 담 section 위치와 List의 현재 위치를 비교해서 처리 하려고 하는 거임.
무튼 실전 코드는 담편에... (난 편수 늘리기 대마왕~)

- 네가 알고 있는 지식을 순순히 내놓는다면 유혈 사태는 벌어지지 않을 것이다..?


후~ 간만에 돌아와서 Android 강좌를 하게 되었네... (웃음...)
자 전편에 이어서 마무리~ ㄱㄱㅆ

2012/02/08 - [Android Study] - Android List에 index를 표시해보자 1편 


Android 에서 IPhone 처럼 list에 index 표시 하려면 indexer라는 걸 이용 하는 것이 속편한거 같다.
Indexer는 2개가 있는데 SectionIndexer와 AlphabetIndexer 요고...
자세히 다 아는건 아닌데 그냥 사용해 본 경험만 있는 (읭? 무슨 말인지?)

내가 사용 할 녀석은 SectionIndexer 이거 쓸꺼임. 사용 할 곳은 Adapter(ListView 내용물 처리 해주는 녀석). 에다가 사용 할 예정임.

이렇게 말로만 하면 이해도 안되고 감흥도 없고 지루하기 짝이 없겠지??
그래서 준비한 code...
private class IconAdapter extends CursorAdapter implements SectionIndexer {
    ...
}

뭐 대충 이렇다는거 사실 SectionIndexer에는 3개의 abstract 함수가 존재함
그거 다 구현 해야하는데 그건 담편으로 넘길꺼임,
마찬가지로 BaseAdapter 여기에도 abstarct 함수가 존재함.
이건 예전에 강좌로 남겼기 때문에 버릴예정. 모르겠으면 전편 찾아보시길...

담편에서 보아용~
 

'Android' 카테고리의 다른 글

Android Study ListView Indexer 3편  (0) 2012.03.07
Android Study ListView Indexer 2편  (1) 2012.03.07
LayoutInflater에 대하여...  (0) 2012.02.15
Cursor close 해야 하는 이유와 하는 방법.  (2) 2012.02.14
Android database 만들기 7편  (0) 2012.02.10

+ Recent posts