안 드 로 이 드 위 챗 연락처 색인 목록 기능 모방

머리말
  자신 이 만 든 작은 소프트웨어 에 A-Z 에서 순 위 를 매 기 는 ListView 를 사용 해 야 하기 때문에 자 연 스 럽 게 위 챗 의 연락 처 를 떠 올 렸 다.내 가 원 하 는 것 은 바로 그런 효과 다.원래 스스로 쓰 려 고 하지 않 았 는데 제3자 가 쓴 것 을 원 했다.몇 개 를 찾 아 보 니 어떤 것 은 너무 복잡 하고 어떤 것 은 간단 하지만 나의 요구 에 부합 되 지 않 았 다.그래서 나 는 통합 시 켜 복잡성 과 단순 성 을 하나 로 합 쳤 다.
이루어지다
『8195』효과 도 를 먼저 살 펴 보 자.

요점 분석
『8195』이러한 효 과 를 실현 하려 면 다음 과 같은 몇 가지 문 제 를 고려 해 야 한다.
  • 오른쪽 알파벳 표시 줄 그리 기
  • 클릭 효과 의 실현
  • 한 자 를 A-Z 로 정렬 하 는 문제
  • 정상 적 인 Item 과 알파벳 구분자 의 Item 실현
  • 『8195』아래 에서 우 리 는 이 몇 가지 문 제 를 해결 한 후에 위의 효과 가 나타 날 수 있다.
    [첫걸음]
      우 리 는 먼저 하나의 종 류 를 사용자 정의 해 야 합 니 다.SlideBar 라 고 합 니 다.Button 을 계승 한 다음 에 onDraw 방법 을 덮어 서 알파벳 a-z 를 그리 면 오른쪽 알파벳 표시 줄 의 효 과 를 나 타 낼 수 있 습 니 다.
    원본 코드 보기:
    
    public class SlideBar extends Button{ 
    
     public interface OnTouchAssortListener{ 
     public void onTouchAssortListener(String s); 
     } 
    
     //    
     private static final String[] ASSORT_TEXT = {"A", "B", "C", "D", "E", "F", "G", 
     "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", 
     "U", "V", "W", "X", "Y", "Z" ,"#"};
    
     private Paint mPaint = new Paint(); 
     private int mSelectIndex = -1; 
     private OnTouchAssortListener mListener = null;
     private Activity mAttachActivity;
     PopupWindow mPopupWindow = null;
     View layoutView;
     TextView text;
    
     public SlideBar(Context context){ 
     this(context,null); 
     } 
    
     public SlideBar(Context context, AttributeSet attrs) { 
     this(context, attrs,0); 
     } 
    
     public SlideBar(Context context, AttributeSet attrs, int defStyle){ 
     super(context, attrs, defStyle);
     mAttachActivity = (Activity)context;
     init(context);
     } 
     private void init(Context context) {
     layoutView = LayoutInflater.from(context).inflate(R.layout.alert_dialog_menu_layout, null);
     text = (TextView) layoutView.findViewById(R.id.content);
     }
    
     public void setOnTouchAssortListener(OnTouchAssortListener listener) {
     this.mListener = listener;
     }
    
     @Override 
     protected void onDraw(Canvas canvas){ 
     super.onDraw(canvas);
     int nHeight = getHeight(); 
     int hWidth = getWidth(); 
     int nAssortCount = ASSORT_TEXT.length;
     int nInterval = nHeight / nAssortCount;
    
     for (int i = 0; i < nAssortCount; i++){ 
     mPaint.setAntiAlias(true); //     
     mPaint.setTypeface(Typeface.DEFAULT_BOLD); //      
     mPaint.setColor(Color.parseColor("#5f5f5f")); //    
     if (i == mSelectIndex){ 
     //               
     mPaint.setColor(Color.parseColor("#3399ff")); 
     mPaint.setFakeBoldText(true); 
     mPaint.setTextSize(30); 
     } 
     float xPos = hWidth / 2 - mPaint.measureText(ASSORT_TEXT[i]) / 2; //      X   
     float yPos = nInterval * i + nInterval; //      Y   
     canvas.drawText(ASSORT_TEXT[i], xPos, yPos, mPaint); 
     mPaint.reset(); 
     } 
     } 
    
     @Override
     public boolean dispatchTouchEvent(MotionEvent event) {
     //            
     int nIndex = (int) (event.getY() / getHeight() * ASSORT_TEXT.length);
     if (nIndex >= 0 && nIndex < ASSORT_TEXT.length){
     switch (event.getAction()){ 
     case MotionEvent.ACTION_MOVE: 
     //        
     if (mSelectIndex != nIndex){ 
      mSelectIndex = nIndex;
      showCharacter(ASSORT_TEXT[mSelectIndex]);
      if (mListener != null){
      mListener.onTouchAssortListener(ASSORT_TEXT[mSelectIndex]);
      }
     } 
     break; 
     case MotionEvent.ACTION_DOWN: 
     mSelectIndex = nIndex; 
     showCharacter(ASSORT_TEXT[mSelectIndex]);
     if (mListener != null){ 
      mListener.onTouchAssortListener(ASSORT_TEXT[mSelectIndex]); 
     } 
    
     break; 
     case MotionEvent.ACTION_UP: 
     disShowCharacter();
     mSelectIndex = -1; 
     break; 
     } 
     } else { 
     mSelectIndex = -1; 
     disShowCharacter();
     } 
     invalidate();
     return true;
     }
    
     private void disShowCharacter() {
     if (mPopupWindow != null) {
     mPopupWindow.dismiss();
     mPopupWindow=null;
     }
     }
    
     /**
     *        
     * @param string
     */
     private void showCharacter(String string){
    
     if (mPopupWindow != null){
     text.setText(string);
     } else{ 
     mPopupWindow = new PopupWindow(layoutView, 100, 100, false);
     mPopupWindow.showAtLocation(mAttachActivity.getWindow().getDecorView(), Gravity.CENTER, 0, 0);
     }
     text.setText(string);
     }
    } 
    
    
      는 onDraw 방법 을 먼저 보고 다른 내용 은 먼저 보지 않 으 며 먼저 컨트롤 의 너비 와 높이 를 얻 은 다음 에 모든 자모 가 차지 해 야 할 높이 가 얼마 인지 계산 한 다음 에 모든 자모 가 차지 하 는 공간의 중간 에 이 자 모 를 그리 면 된다.코드 가 비교적 간단 하 므 로 이 부분 은 상세 하 게 설명 할 필요 가 없다.
    [두 번 째 단계]
      우 리 는 클릭 이 벤트 를 추가 해 야 합 니 다.SlideBar 를 클릭 할 때 먼저 오른쪽 칸 에 클릭 된 알파벳 이 커지 는 것 을 볼 수 있 습 니 다.클릭 되 지 않 은 알파벳 과 구별 되 고 Dialog 와 유사 한 것 을 팝 업 하여 피 점 중의 알파벳 을 표시 합 니 다.이 효과 도 잘 이 루어 집 니 다.
      SlideBar 에서 우리 가 덮어 야 할 방법 중 하 나 는 dispatchTouchEvent()입 니 다.우리 가 SlideBar 를 누 르 면 다음 동작 은 미 끄 러 지고 들 어 올 릴 수 있 습 니 다.클릭 한 동작 에 응답 해 야 합 니 다.들 어 올 리 면 dialog 와 유사 한 것 이 사라 지고 커 진 자모 도 그대로 돌아 가 야 합 니 다.계속 미 끄 러 지면...어떤 자모 로 미 끄 러 질 때 대응 하 는 자모 가 커지 고 표 시 됩 니 다.
      위 에 있 는 소스 코드 를 보면 알파벳 이 커지 는 효과 가 잘 이 루어 집 니 다.선 택 된 알파벳 을 그린 Paint 대상 의 textsize 값 을 크게 만 들 면 됩 니 다.그리고 dialog 와 유사 한 것 은 PopupWindow 로 이 루어 집 니 다.클릭 하고 미 끄 러 질 때 PopupWindow 를 표시 하고 SlideBar 범 위 를 올 리 거나 미 끄 러 질 때 PopupWindow 를 사라 지게 합 니 다.마지막 으로 주의해 야 할 것 은 invalidate()라 는 방법 입 니 다.이 방법 은 화면 을 다시 그 리 는 데 사용 되 는 것 입 니 다.
    [세 번 째 단계]
    저 는 가장 중요 하고 가장 어 려 운 것 은 한자 가 A-Z 의 순 서 를 따 르 는 것 이 라 고 생각 합 니 다.다행히 이것 은 이미 누군가가 실현 되 었 으 니,우 리 는 이른바'가 져 오기 주의'를 하 자.프로젝트 안에 CharacterParser 류 가 있 습 니 다.이 종 류 는 한자 병 음 을 바 꾸 는 작업 을 봉 인 했 습 니 다.그 중에서 getSelling(String s)방법 은 한자 문자열 을 들 여 한자 의 병 음 을 얻 는 역할 을 합 니 다.역시 좋 은 방법 입 니 다.마음 에 듭 니 다!!이렇게 해서 우 리 는 표시 할 한자 문자열 의 병 음 자 모 를 얻 은 다음 에 모든 문자열 을 자모 에 따라 정렬 하면 A-Z 에서 질서 있 는 목록 을 얻 을 수 있다.ListView 는 일반적으로 하나의 List 대상 을 연결 한 다음 에 List 대상 에 일련의 대상 을 저장 하기 때문에 여 기 는 제 가 하나의 대상 으로 말 하 겠 습 니 다.
    
    public class DataBean {
    
     public static final int TYPE_CHARACTER = 0;
     public static final int TYPE_DATA = 1;
     private int item_type;
     private String item_en;
     private String name;
     private String phone;
     /*    */
    
     public DataBean(String name,String phone,int type){
     CharacterParser parser = CharacterParser.getInstance();
     this.name = name;
     this.phone = phone;
     this.item_type = type;
     this.item_en = parser.getSelling(name).toUpperCase().trim();
     if(!item_en.matches("[A-Z]+")){
     item_en = "#"+item_en;
     }
     }
    
     /*
     *  geter seter   
     */
    }
    
      이 대상 에서 주의해 야 할 것 은 두 구성원 변수 입 니 다.itemtype 과 itemn,이 대상 이 표시 할 정상 적 인 대상 인지 알파벳 구분자 대상 인지,item 에 따라type 에 따라 Adapter 의 getView 방법 을 쓸 때 서로 다른 View 대상 을 되 돌려 주 고 효과 그림 의 정상 적 인 Item 과 알파벳 분할 자 Item 을 실현 할 수 있 습 니 다.item_n 은 name 변수,즉 한자 문자열 의 병 음 문자열 을 나타 내 는데 주로 이니셜 을 가 져 오고 문자열 간 의 비 교 를 하 는 데 사 용 됩 니 다.
      현재 List 대상 이 있다 고 가정 하면 그 안에 DataBean 이 저장 되 어 있 습 니 다.그러면 문제 가 생 겼 습 니 다.이 DataBean 대상 을 병 음 문자열 에 따라 정렬 하고 List 대상 에 알파벳 구분 자 를 나타 내 는 DataBean 대상 을 어떻게 추가 합 니까?
    우선 정렬 문 제 를 해결 합 니 다.이것 은 비교적 간단 합 니 다.
      여 기 는 Collections 의 sort 방법 을 사 용 했 습 니 다.이 방법 은 두 가지 매개 변수 가 있 습 니 다.하 나 는 정렬 이 있 는 List 대상 이 고 다른 하 나 는 Comparator 인터페이스의 유형 을 실현 하 는 대상 입 니 다.정렬 을 어떻게 하 는 지,어떤 구성원 변수 로 정렬 하 는 지 설명 합 니 다.
      PinyinComparator 라 는 종 류 는 Comparator 를 실현 했다.
    
    public class PinyinComparator implements Comparator<DataBean>{
     public int compare(DataBean o1, DataBean o2){
     if (o1.getItem_en().equals("@")
     || o2.getItem_en().equals("#")){
     return -1;
     } else if (o1.getItem_en().equals("#")
     || o2.getItem_en().equals("@")) {
     return 1;
     } else {
     return o1.getItem_en().compareTo(o2.getItem_en());
     }
     }
    }
    
      볼 수 있 습 니 다.두 DataBean 대상 은 변수 itemn.즉,병 음 문자열 로 정렬 을 하 는 것 입 니 다.이렇게 하면 실현 하기에 비교적 편리 합 니 다.스스로 정렬 하 는 알고리즘 을 쓸 필요 가 없습니다.물론 여러분 이 스스로 정렬 하 는 것 도 반대 하지 않 습 니 다.
      Collections 의 sort 함 수 를 거 쳐 정렬 한 후에 현재 List 대상 에 저 장 된 DataBean 대상 은 A-Z 에 따라 정렬 되 었 습 니 다.지금 우리 가 해 야 할 일 은 바로 이 대상 에 알파벳 구분자 DataBean 을 나타 내 는 대상 을 삽입 하 는 것 입 니 다.이 실현 은 비교적 간단 해 야 합 니 다.제 가 사용 하 는 방법 은 비교적 멍청 합 니 다/(ㄒ o ㄒ)/~
    
    public class ListUtil {
     public static void sortList(List<DataBean> list){
     List<DataBean> _List = new ArrayList<DataBean>();
     Collections.sort(list, new PinyinComparator());
     DataBean dataBean = new DataBean(getFirstCharacter(list.get(0).getItem_en()), "",DataBean.TYPE_CHARACTER);
     String currentCharacter = getFirstCharacter(list.get(0).getItem_en());
     _List.add(dataBean);
     _List.add(list.get(0));
     for(int i=1;i<list.size();i++){
     if(getFirstCharacter(list.get(i).getItem_en()).compareTo(currentCharacter)!=0){
     currentCharacter = getFirstCharacter(list.get(i).getItem_en());
     dataBean = new DataBean(currentCharacter, "",DataBean.TYPE_CHARACTER);
     _List.add(dataBean);
     }
     _List.add(list.get(i));
     }
     list.clear();
     for(DataBean bean:_List){
     list.add(bean);
     }
     }
     public static String getFirstCharacter(String str){
     return str.substring(0, 1);
     }
    }
      이런 종 류 는 List 대상 에 알파벳 구분 자 를 나타 내 는 대상 을 추가 하고 item 설정 을 통 해type 변수의 값 이 다 르 기 때문에 Adapter 에서 이 값 에 따라 서로 다른 View 를 되 돌려 주면 서로 다른 Item 디 스 플레이 를 실현 할 수 있 습 니 다.
    자,이제 질문 하나만 남 았 습 니 다.바로 알파벳 을 클릭 한 후에 ListView 는 이 알파벳 에 대응 하 는 Item 을 첫 번 째 로 표시 합 니 다.이 실현 도 어렵 지 않 습 니 다.점 에 있 는 알파벳 을 얻 은 후에 모든 DataBean 대상 을 옮 겨 다 니 고 현재 자모 와 일치 하 는 첫 번 째 알파벳 구분자 대상 을 찾 은 다음 에 이 Item 의 position 값 을 얻 습 니 다.ListView 에서 선 택 된 Item 의 position 을 찾 은 Item 의 position 으로 설정 하면 됩 니 다.
    드디어 모든 문제 가 해결 되 었 습 니 다.지금 자신 이 이런 효 과 를 실현 할 수 있 는 지 보 세 요.만약 안 된다 면 나의 소스 코드 를 참고 할 수 있다.
    작은 매듭
      원래 저도 이것 에 대해 잘 모 르 지만 자신 에 게 소스 코드 를 보 여 달라 고 강 요 했 습 니 다.인터넷 에 있 는 큰 신 이 쓴 것 이 100%자신의 요 구 를 만족 시 키 는 것 이 아니 기 때문에 소스 코드 를 알 아 볼 수 있 으 면 스스로 수정 할 수 있 습 니 다.
    원본 코드 다운로드여기,이곳.
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기