public class FriendListMainActivity extends ListActivity{
 
 DBFriendListManager fndLstDBHelper; //DB open Helper
 
 private String searchKeyword; //검색어가 저장되는 변수
 private List<FriendListMain> contactsList; //onListItem 에서 사용하기 위해 선언
 
 //private boolean mLockListView = true; //list lock을 위한 변수
 
    private List<FriendListMain> getContactsList() throws Exception { //data 저장소
     
     
     SQLiteDatabase db = fndLstDBHelper.getReadableDatabase(); //db를 읽기 위한 db의 인스턴스를 생성 
  Cursor cursor = db.rawQuery("SELECT name, serialNo, statusMsg FROM friendList", null); //table 에 cursor 장착 
  
  List<FriendListMain> contactsList = new ArrayList<FriendListMain>();
  // addContact (param1, param2, param3, param4)
  // param1: adapter 에 장착될 List Object 
  // param2: 사용자 image
  // param3: 사용자 이름
  // param4: 상태 메세지
  
  while (cursor.moveToNext()) {//순차적으로 하나의 row 씩 읽어 나간다.
   String name = cursor.getString(0);
   String serial_no = cursor.getString(1);
   String  status = cursor.getString(2);
   
   addContact(contactsList, R.drawable.friend_default_image, name, serial_no, status);//contact 에 1row 씩 붙여준다.
  }
  cursor.close();
  fndLstDBHelper.close();
    
  return contactsList;
 }
 private void addContact(List<FriendListMain> contactsList, int icon ,String name, String serial_no, String stateMsg) throws Exception {
        //contactList에 1row 씩 추가하기 위한 메서드
  if (contactsList == null) {
   throw new NullPointerException("contactList가 null 입니다.");
  }
  boolean isAdd = false;
  if (searchKeyword != null && "".equals(searchKeyword.trim()) == false) { //만약 검색창에 검색어가 입력된다면
   
   String iniName = HangulUtils.getHangulInitialSound(name, searchKeyword); // ㄱㅣㅁㅈㅓㅇ  이런식으로 iniName 에 저장됨
   if (iniName.indexOf(searchKeyword) >= 0) { //iniName 안에(search 하려는 keyword) 일치 하는 문자가 있다면 
    isAdd = true; 
   }
  } else { //검색어가 입력 되지 않았다면 
   isAdd = true;
  }
  if (isAdd) { //contactList에 해당 메세지를 add 시킵니다.
   contactsList.add(new FriendListMain(icon, name, serial_no, stateMsg));
  }
  
 }
  
 private void displayList() throws Exception {
  //List<Contact> contactsList = null;
  contactsList = getContactsList(); //contactList 에 getContactsList 에 있는 row 들을 add
   
  ContactsListAdapter<FriendListMain> adapter =
    new ContactsListAdapter<FriendListMain>(this, R.layout.friend_list_row, contactsList); //Contact type 의 adapter 를 생성 
  setListAdapter(adapter); //set 해준다
  //adapter.notifyDataSetChanged();
 }
 private class ContactsListAdapter<T extends FriendListMain> extends ArrayAdapter<T> {
  private List<T> contactsList;
  
  public ContactsListAdapter(Context context, int textViewResourceId, List<T> items) { //constructor
   super(context, textViewResourceId, items);
   contactsList = items;
  }
  
  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
   View view = convertView;
   if (view == null) {//레이아웃 리소스로부터 뷰를 인플레이트 시킨다,
    LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    view = vi.inflate(R.layout.friend_list_row, null); 
   }
   T contacts = contactsList.get((int)getItemId(position));
   //추가시작
   LinearLayout header = (LinearLayout)view.findViewById(R.id.section);
   String label = HangulUtils.getHangulInitialSound(contacts.getName());
   char firstChar = label.toUpperCase().charAt(0);
   
   if((int)getItemId(position) == 0){
    setSection(header, label);
   }else{
    String preLabel = HangulUtils.getHangulInitialSound(contactsList.get((int)getItemId(position)-1).getName());
    char preFirstChar = preLabel.toUpperCase().charAt(0);
    
    if(firstChar != preFirstChar){   
     setSection(header, label);  
     }else{ 
      header.setVisibility(View.GONE);  
      
    }
   }
   //추가 끝
   
   
   
   if (contacts != null) {
    //사용자 사진
    ImageView viewIcon = (ImageView) view.findViewById(R.id.picture);
    if (viewIcon != null) {
     viewIcon.setImageResource(contacts.getIcon());
    }
    //사용자 이름
    TextView viewName = (TextView) view.findViewById(R.id.toptext); //textView 와 XML 의 id 연결
    if (viewName != null) {
     viewName.setText(contacts.getName() + " "+position); //textView 에 특정 문자열 지정
    }
    //사용자 메세지       
    TextView viewStateMsg = (TextView) view.findViewById(R.id.righttext);
    if (viewStateMsg != null) {
     viewStateMsg.setText(contacts.getStateMsg());
    }
   }
   return view;
  }
 }
 
 private void setSection(LinearLayout header, String label)
 {
  TextView text = new TextView(getBaseContext());
  header.setBackgroundColor(0xffaabbcc);
  text.setTextColor(Color.WHITE); 
  text.setText(label.substring(0, 1).toUpperCase());  
  text.setTextSize(15);
  text.setPadding(5, 0, 0, 0);
  text.setGravity(Gravity.CENTER_VERTICAL);  
  header.removeAllViewsInLayout(); //모든 view 삭제
  header.addView(text); 
  
 }
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  fndLstDBHelper = new DBFriendListManager(this); //db 를 open 하는 helper class 객체 생성
  
  setContentView(R.layout.friend_list);
  EditText searchBox = (EditText) findViewById(R.id.EditText01);
    
  try {
   searchBox.addTextChangedListener(new TextWatcher() {//EditText 에 text 변화를 감지하는 Listener 를 장착합니다.
    public void afterTextChanged(Editable arg0) {
     // ignore
    }
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
     // ignore
    }
    public void onTextChanged(CharSequence s, int start, int before, int count) { //text 가 변할 때
     try {
      searchKeyword = s.toString().toLowerCase(); //대소문자 구별을 위한 변경
      displayList(); // 검색된 리스트를 보여 준다
     } catch (Exception e) {
      Log.e("", e.getMessage(), e); //에러 발생시 로그 남김
     }
    }
    
   });//Listener end
   displayList(); //맨 처음 시작시 전체 리스트 보여주기 위한 용도
  } catch (Exception e) {
   Log.e("", e.getMessage(), e);
  }
 }

 

안드로이드 공부를 하고 있는 학생입니다.

지금 제가 구현하고자 하는 부분이

카카오톡 처럼 List 에 있는 사용자 이름의 초성별로

header로 구분지어 놓은 부분입니다.

 

여기서 문제가,

처음 로딩 시에는 별 다른 문제 없이 헤더가 잘 정렬되어 출력이 되는데,

스크롤을 상 하로 움직이거나, 검색창에 포커스가 갔다가 취소 버튼을 누르게 되면

헤더가 엉망이 되어 버립니다.

 

여기 저기 알아보니, list 에서 position이 유동적으로 변하기 때문에 sync 맞추기가 힘들다고 그러더군요.

아마도 제가 모든 View에 header 를 달아두고,

position을 통하여 처음부터 순차적으로 읽어 나가면서

이전 view와 초성이 같으면 setVisibility.GONE 을 통하여 보이지 않게 하는 방식으로 구현 했는데...

여기에서의 로직이 잘못된 듯 싶네요.

 

며칠째 이 문제 때문에 너무 답답하네요.

 

고수님들의 답변 부탁 드립니다.

 

제목 없음-1.png

 

     [스크롤을 움직이고 난 후의 모습: 초성이 ㄱ인 view와 ㅁ인 view가 합쳐지게 되는 현상 발생]