Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android自定義控件---聯系人列表A-Z排序

Android自定義控件---聯系人列表A-Z排序

編輯:關於Android編程

這幾天在做IM模塊,設計圖要求做一個類似下圖所示的自定義控件。

 

\

 

我百度了一下,發現類似的Ddmo有很多,但是還不能完全滿足設計圖的需求。 參考了幾個比較有價值的demo琢磨了一天總算做出來了,現在發出來和大家分享。 分析一下這個需求的難點。 1、右邊側滑欄(SideBar)控件繪制。 2、將列表中的中文昵稱轉化為拼音列表。(這個問題用jpinyin解決。) 3、滑動側滑欄(SideBar)的過程中如何與ListView列表建立對應的聯系? 如果能夠解決這三個問題那麼這個需求也就迎刃而解了。 接下來看看整個Demo的結構圖
\
一、SideBar控件的繪制 1、首先創建一個名為SideBar的類並且繼承View。在這個類中分別重寫onMeasure,onDraw,onTouchEvent三個方法。 (1)onMeasure顧名思義這是一個用來測量SideBar視圖的大小的方法。 MeasureSpec.getMode是用來獲取測量模式類型。測量模式類型有三種UNSPECIFIED,EXACTLY,AT_MOST。 其中UNSPECIFIED很少會用到,我們忽略。我們主要理解EXACTLY和AT_MOST 當我們在XML文件裡面設置SideBar類的layout_width屬性的時候, 如果設置為match_parent或者一個精確值(例如30dp)那麼MeasureSpec.getMode得到的測量模式類型就是EXACTLY。 如果設置為warp_content那麼MeasureSpec.getMode得到的測量模式類型就是AT_MOST。(layout_height屬性同理) 根據這些獲取的類型值,就會進入下面的if條件中計算該視圖的大小。在該方法的最後會調用setMeasureDimension方法設置最終的寬度和高度。
@Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int heightMode = MeasureSpec. getMode(heightMeasureSpec) ;

    int finalWidth = 0, finalHeight = 0;
    // 測量單個字符的寬度和高度
    float charWidthAndHeight = paint.measureText( letter.get(0 )) + letterSpace;

    if (widthMode == MeasureSpec. EXACTLY) {
        finalWidth = MeasureSpec.getSize (widthMeasureSpec);
    } else if (widthMode == MeasureSpec.AT_MOST) {
        finalWidth = (int ) charWidthAndHeight + getPaddingLeft() + getPaddingRight();
    }


    if (heightMode == MeasureSpec.EXACTLY) {
        finalHeight = MeasureSpec.getSize (heightMeasureSpec);
    } else if (heightMode == MeasureSpec.AT_MOST) {

        // 注意measureText的值與 paint.setTextSize的值有關
        finalHeight = ( int) charWidthAndHeight * letter .size() + getPaddingBottom() + getPaddingTop();
    }


    setMeasuredDimension(finalWidth, finalHeight);
}

(2)在測量好這個視圖的大小之後,接下來就是在onDraw方法中繪制自己想要的視圖。
  @Override
    protected void onDraw(Canvas canvas) {
        //27 個字符(包含 #)均分整個視圖的高度,例如視圖高度為 270,270/27 均分之後,每個字符的y坐標為10。
        y = getHeight() / letter.size() ;

        for ( int i = 0 ; i < letter .size(); i++) {
            Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();

            // 計算繪制字符 X的坐標,整個視圖寬度的一半減去字符寬度的一半
            x = getWidth() / 2 - ( int) paint.measureText(letter .get(i)) / 2;
 //            int correctY=y*i+y;
//            int correctY = y * i + y / 2;
            int correctY = ((y * i + y) + (y * i) - fontMetricsInt.bottom - fontMetricsInt.top) / 2;
            String tempString = isLetterUpper ? letter.get(i).toUpperCase() : letter .get(i).toLowerCase();
            canvas.drawText(tempString , x, correctY, paint );
//            canvas.drawLine(0, y * i + y, 100, y * i + y, paint);
        }
    }
關於繪制字符X坐標的求法比較簡單,注釋已經解釋得很清楚就不再分析。 主要分析y坐標的求法。我百度了一些demo總結發現有兩種關於字符y坐標的求法。 (為了便於觀察,我暫時將SideBar的背景改為了淺藍色,並且每個字符的都用橫線分隔) 第一種是int correctY=y*i+y。運行一下程序發現字符的繪制明顯向下偏移(如下圖所示)
\

第二種是int correctY=y*i+y/2。再運行程序,發現還是有點偏移。我是處女座有強迫症,果斷不能忍啊。

 

\

 

於是在網上搜索了不少資料,研究了一番。 我把計算公式改為int correctY = ((y * i + y) + (y * i) - fontMetricsInt.bottom - fontMetricsInt.top) / 2; 運行程序,完美解決問題。
\

剛看到這個式子可能不是很理解。我給大家解釋一下,假設我們要繪制D這個字符。如圖所示:

 

\

 

這時包含D字符的這個矩形上下邊的縱坐標分別是y*i,y*i+y。那麼這個矩形的中間縱坐標怎麼算呢?答案就是((y*i)+(y*i+y))/2 得到這個中間值之後,我們直接調用繪制方法canvas.drawText(tempString, x, ((y*i)+(y*i+y))/2 , paint);發現還是出問題了 字符還是畫在矩形偏上位置(如下圖)
\
為什麼會這樣?這是因為canvas.drawText方法在繪制文本的時候並不是從文本的中間(下圖的黃線)開始 ,而且是從文本的中間偏下位置,即圖中綠色的baseLine這條線開始繪制。
\
明白了這些知識點之後就好處理了。(FontMetricInt.top+FontMetricInt.bottom)/2就是這邊黃線的縱坐標(注意FontMetricInt.top 是負值)。 綜合起來:矩形縱坐標的值減去黃線縱坐標的值除以2整理得到 ((y * i + y) + (y * i) - fontMetricsInt.bottom - fontMetricsInt.top) / 2 再調用Canvas.drawText方法繪制字符。 (3)整個視圖都測量,繪制好之後。我們還需要添加控件的觸摸事件。所以還需要重寫onTouchEvent方法。 首先設置回調接口,向用戶提供兩個方法,分別是showCurrentLetter和hideCurrentLetter。
/**
* 回調接口。
 */
public interface OnCurrentLetterListener {
    void showCurrentLetter(String currentLetter);

    void hideCurrentLetter ();
}

重寫onTouchEvent方法,首先獲取用戶在點擊,移動SideBar視圖時的y坐標。 y/getHeight()*letter.size()表示y坐標占整個視圖高度的比例(例如50%) 乘以字符數組(長度為27)的長度等於下標(約等於13,) switch(event.getAction())是用來判斷用戶觸摸手機屏幕的手勢。 當用戶在手機屏幕按壓,移動時 MotionEvent.ACTION_DOWN(按壓手勢), MotionEvent.ACTION_MOVE(移動手勢)回調上面回調接口的showCurrentLetter方法。 當用戶在手機屏幕抬起時MotionEvent.ACTION_UP(抬起手勢)回調接口中的hideCurrentLetter方法。
@Override
 public boolean onTouchEvent(MotionEvent event) {
    float y = event.getY();

    // 獲取當前側滑欄字母的下標
    float currentLetterIndex = y / getHeight() * letter.size();

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_MOVE:

            if (onCurrentLetterListener != null) {
                //對上下邊界對限制
                if (currentLetterIndex >= letter.size()) {
                    currentLetterIndex = letter.size() - 1 ;
                } else if (currentLetterIndex < 0) {
                    currentLetterIndex = 0;
                }
                onCurrentLetterListener .showCurrentLetter(letter.get(( int) currentLetterIndex));

            }
            return true;

        case MotionEvent. ACTION_UP:
            if (onCurrentLetterListener != null) {
                onCurrentLetterListener.hideCurrentLetter() ;
            }
            return true;

        default:
            return true;
    }
}
最後整個方法return true;表示這個觸摸事件被SideBar視圖消費了,不再向其它地方傳遞事件。 2、最後貼個SideBar類的代碼
package per.edward.ui;

import android.content.Context ;
import android.content.res.TypedArray ;
import android.graphics.Canvas ;
import android.graphics.Color ;
import android.graphics.Paint ;
import android.util.AttributeSet ;
import android.view.MotionEvent ;
import android.view.View ;

import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.List ;


/**
* 側滑欄視圖
 * Created by Edward on 2016/4/27.
*/
public class SideBar extends View {
    private String[] letterStrings = { "#", "A" , "B", "C", "D" , "E", "F" , "G", "H", "I" , "J", "K", "L" , "M", "N", "O" , "P", "Q", "R", "S" , "T", "U", "V" , "W", "S", "Y" , "Z"} ;
    private Paint paint;
    // 字母列表
    private List letter;
    // 繪制字母的 x,y坐標
    private int x, y ;
    // 字母的間距
    private int letterSpace = 0 ;
    // 字母是否大寫
    private boolean isLetterUpper = true;

    private OnCurrentLetterListener onCurrentLetterListener;

    public void setLetter (List letter) {
        this .letter = letter ;
    }

    // 設置回調接口
    public void setOnCurrentLetterListener(OnCurrentLetterListener onCurrentLetterListener) {
        this .onCurrentLetterListener = onCurrentLetterListener ;
    }

    public SideBar(Context context) {
        this (context, null) ;
    }

    public SideBar(Context context, AttributeSet attrs) {
        super (context, attrs) ;

        if ( letter == null ) {
            letter = new ArrayList<>() ;
            letter = Arrays.asList(letterStrings );
        }

        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SideBar) ;
        letterSpace = typedArray.getInt(R.styleable.SideBar_SB_Letter_Space, 0);
        isLetterUpper = typedArray.getBoolean(R.styleable.SideBar_SB_Is_Letter_Upper, true);
        typedArray.recycle() ;

        paint = new Paint() ;
        paint .setColor(Color.BLACK) ;
        paint .setAntiAlias(true) ;
        paint .setTextSize(30) ;//3CAC48
        paint .setColor(Color.parseColor("#ffffff" ));
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec. getMode(heightMeasureSpec) ;

        int finalWidth = 0, finalHeight = 0;
        // 測量單個字符的寬度和高度
        float charWidthAndHeight = paint.measureText( letter.get(0 )) + letterSpace;

        if (widthMode == MeasureSpec. EXACTLY) {
            finalWidth = MeasureSpec.getSize(widthMeasureSpec);
        } else if (widthMode == MeasureSpec.AT_MOST) {
            finalWidth = (int) charWidthAndHeight + getPaddingLeft() + getPaddingRight();
        }


        if (heightMode == MeasureSpec.EXACTLY) {
            finalHeight = MeasureSpec.getSize(heightMeasureSpec) ;
        } else if (heightMode == MeasureSpec.AT_MOST) {

            // 注意measureText的值與 paint.setTextSize的值有關
            finalHeight = ( int) charWidthAndHeight * letter .size() + getPaddingBottom() + getPaddingTop();
        }

 //        Log.e("--------------->", MeasureSpec.getSize(widthMeasureSpec) + "    " + MeasureSpec.getSize(heightMeasureSpec));
        setMeasuredDimension(finalWidth , finalHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        setBackgroundColor(Color.parseColor ("#31b2f7" ));
        //27 個字符(包含 #)均分整個視圖的高度,例如視圖高度為 270,270/27 均分之後,每個字符的 y坐標為10
        y = getHeight() / letter.size() ;

        Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();

        for ( int i = 0 ; i < letter .size(); i++) {
            // 計算繪制字符 X的坐標,整個視圖寬度的一半減去字符寬度的一半
            x = getWidth() / 2 - ( int) paint.measureText(letter .get(i)) / 2;
 //            int correctY=y*i+y;
//            int correctY = y * i + y / 2;
            int correctY = ((y * i + y) + (y * i) - fontMetricsInt.bottom - fontMetricsInt.top) / 2;
            String tempString = isLetterUpper ? letter.get(i).toUpperCase() : letter .get(i).toLowerCase();
            canvas.drawText(tempString , x, ((y * i) + ( y * i + y)) / 2 , paint) ;
            canvas.drawLine( 0, y * i + y, 100, y * i + y, paint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float y = event.getY();

        // 獲取當前側滑欄字母的下標
        float currentLetterIndex = y / getHeight() * letter.size();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:

                if ( onCurrentLetterListener != null ) {
                    //對上下邊界對限制
                    if (currentLetterIndex >= letter.size()) {
                        currentLetterIndex = letter.size() - 1 ;
                    } else if (currentLetterIndex < 0) {
                        currentLetterIndex = 0;
                    }
                    onCurrentLetterListener .showCurrentLetter(letter.get(( int) currentLetterIndex));

                }
                return true;

            case MotionEvent. ACTION_UP:
                if ( onCurrentLetterListener != null ) {
                    onCurrentLetterListener.hideCurrentLetter() ;
                }
                return true;

            default:
                return true;
        }
    }

    /**
     * 回調接口。
     */
    public interface OnCurrentLetterListener {
        void showCurrentLetter(String currentLetter);

        void hideCurrentLetter ();
    }


}


3、SideBar類寫完之後,我們就可以創建一個XML文件命名為activity_main, 在裡面用上我們剛才寫的自定義控件。整個XML代碼布局很簡單。 最外層是一個RelativeLayout容器。 中間放了一個TextView控件,默認為隱藏狀態。 將SideBar右置垂直居中。
4、最後再創建一個主體類,命名為MainActivity並且繼承Activity。首先實例化TextView和SideBar兩個控件。 之後用SideBar的實例。設置setOnCurrentLetterListener的回調接口,在這個接口需要實現兩個方法分別是showCurrentLetter,hideCurrentLetter。前者用來顯示TextView,並且設置當前字母值。後者用來隱藏TextView。具體操作看下面代碼。簡單吧?
package per.edward.ui;

import android.app.Activity ;
import android.os.Bundle ;
import android.view.View ;
import android.widget.TextView ;

/**
* author:Edward
*/
public class MainActivity extends Activity {
    private TextView txtShowCurrentLetter;
    private SideBar sideBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super .onCreate(savedInstanceState) ;
        setContentView(R.layout. activity_main);
        txtShowCurrentLetter = (TextView) findViewById(R.id.txt_show_current_letter );
        sideBar = (SideBar) findViewById(R.id. side_bar);

        setCallbackInterface() ;
    }

    /**
     * 設置回調接口
     */
    public void setCallbackInterface() {
        // 回調接口
        sideBar .setOnCurrentLetterListener(new SideBar.OnCurrentLetterListener() {
            @Override
            public void showCurrentLetter(String currentLetter) {
                txtShowCurrentLetter .setVisibility(View.VISIBLE) ;
                txtShowCurrentLetter.setText(currentLetter) ;
            }

            @Override
            public void hideCurrentLetter() {
                txtShowCurrentLetter.setVisibility(View. GONE);
            }
        });
    }
}

5、最後實現的效果圖如下。

 

\

 

分享到這裡整個demo的流程已經走到一半了。 下面會講講ListView與SideBar控件的聯動處理。 二、建立側滑欄SideBar與ListView的對應關系 1、首先創建一個聯系人的實體類,在這個實體類中,定義了兩個變量firstLetter(用來存儲聯系人拼音的第一個字母)和name(聯系人的名字)。
package per.edward.ui;

/**
* 聯系人列表實體類
 * Created by Edward on 2016/4/26.
*/
public class ContactsModel {
    private String firstLetter;
    private String name;

    public String getFirstLetter() {
        return firstLetter;
    }

    public void setFirstLetter(String firstLetter) {
        this .firstLetter = firstLetter ;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this .name = name ;
    }


}

2、創建一個名為adapter_side_bar的XML布局。 這個布局將在MainActivity類中通過實例化myAdapter = new SideBarAdapter(this, list, R.layout.adapter_side_bar); 的方法傳遞給SideBarAdapter類。
這個布局的預覽圖是這樣滴。

 

\

 

SideBarAdapter接收到此布局之後,會通過convertView = LayoutInflater.from(context).inflate(mItemLayoutId, null);加載布局。 並且在getView方法中動態在控制字母標題的顯示或隱藏。 3、接著創建一個名為SideBarAdapter類的適配器並且繼承BaseAdapter。 (1)構造方法中調用traverseList方法。這個方法的算法是這樣的。此時mDatas列表所有的getFirstLetter字段已經排序成 ###ABCDEFLLLLMMMQTTZZ。#有三個,for循環。 第一次currentd的值是#把current的值作為鍵並且記錄它的下標,即map.put(current, i)。 第二次current的值是#不記錄,第三次current的值還是# 不記錄。 到第四次此時current更新為A,把current作為鍵並且記錄下標。 第五次此時current更新為B,把current作為鍵並且記錄下標....一直到for循環結束為止。 這時map的集合已經記錄了整個mDatas列表的字母標題和下標。我們只需要在getView方法(這個方法會傳進來一個position)中判斷當前的position是否等於map的下標值。如果相等就將字母標題顯示出來。否則隱藏
package per.edward.ui;

import android.content.Context ;
import android.view.LayoutInflater ;
import android.view.View ;
import android.view.ViewGroup ;
import android.widget.BaseAdapter ;
import android.widget.TextView ;

import java.util.HashMap ;
import java.util.List ;
import java.util.Map ;

/**
* 側欄適配器
 * Created by Edward on 2016/4/27.
*/
public class SideBarAdapter extends BaseAdapter {
    // 是否第一個 Item的
    private boolean isFirstItemLetter = true;
    // 記錄是否顯示字母標題,鍵為字母,值為下標
    private Map map;
    private List mDatas;
    private int mItemLayoutId ;
    private Context context;

    public SideBarAdapter(Context mContext , List mDatas, int mItemLayoutId) {
        this .mDatas = mDatas ;
        map = new HashMap<>() ;
        this. mItemLayoutId = mItemLayoutId;
        this. context = mContext;

        traverseList() ;
    }

    /**
     * 遍歷列表
     * 由於傳進來的 mDatas是一個已排好序的列表,遍歷整個列表,每遇到分類的第一個字母就把下標記錄下來
     */
    public void traverseList() {
        // 獲取初始值
        String current = mDatas.get(0 ).getFirstLetter();

        for ( int i = 0 ; i < mDatas .size(); i++) {
            char tempChar = mDatas.get(i).getFirstLetter().charAt(0) ;
            String tempFirstLetter = mDatas.get(i).getFirstLetter();

            if (tempFirstLetter.equals(current) || (tempChar < 'A' || tempChar > 'Z' )) {
                if ( isFirstItemLetter) {
                    map.put(current , i);
                }
            } else {
                //更新初始值
                current = mDatas .get(i).getFirstLetter();
                map.put(current , i);
            }
            isFirstItemLetter = false;
        }
    }


    /**
     * 獲取當前字母的下標
     *
     * @return
     */
    public int getCurrentLetterPosition(String currentLetter) {
        if (map.get(currentLetter) != null) {
            return map.get(currentLetter);
        } else
            return - 1;
    }

    @Override
    public int getCount() {
        return mDatas.size();
    }

    @Override
    public Object getItem( int position) {
        return mDatas.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView( int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;
        if (convertView == null) {
            viewHolder = new ViewHolder() ;
            convertView = LayoutInflater.from( context).inflate(mItemLayoutId , null);
            viewHolder. txtFirstLetter = (TextView) convertView.findViewById(R.id.txt_letter_category) ;
            viewHolder. txtName = (TextView) convertView.findViewById(R.id.txt_name) ;

            convertView.setTag(viewHolder) ;
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }


        // 判斷是否顯示字母標題
        if (map.get( mDatas.get(position).getFirstLetter()) != null && map.get(mDatas .get(position).getFirstLetter()).equals(position)) {
            viewHolder.txtFirstLetter .setVisibility(View.VISIBLE) ;
            viewHolder.txtFirstLetter.setText( mDatas.get(position).getFirstLetter());
        } else {
            viewHolder.txtFirstLetter .setVisibility(View.GONE) ;
        }

        viewHolder.txtName .setText(mDatas.get(position).getName()) ;

        return convertView ;
    }

    public class ViewHolder {
        TextView txtFirstLetter , txtName;
    }


}

4、記得在倒回剛才的activity_main的XML文件添加ListView控件

5、寫完了SideBarAdapter,我們再回到剛才寫的MainActivity類進行相應的設置,包括初始化值聯系人列表, 聯系人列表排序,聯系人昵稱轉化為拼音等。具體代碼如下所示,比較簡單。就不一一分析了。
package per.edward.ui;

import android.os.Bundle ;
import android.support.v7.app.AppCompatActivity ;
import android.view.View ;
import android.widget.ListView ;
import android.widget.TextView ;

import java.util.ArrayList ;
import java.util.Collections ;
import java.util.Comparator ;
import java.util.HashSet ;
import java.util.List ;
import java.util.Set ;

import opensource.jpinyin.PinyinHelper ;

/**
* author:Edward
* 此 demo的博客地址:http://blog.csdn.net/u012814441
*/
public class MainActivity extends AppCompatActivity {
    private ListView listView;
    private TextView txtShowCurrentLetter;
    private SideBar sideBar;
    private SideBarAdapter myAdapter;
//    private List list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super .onCreate(savedInstanceState) ;
        setContentView(R.layout. activity_main);
        txtShowCurrentLetter = (TextView) findViewById(R.id.txt_show_current_letter );
        sideBar = (SideBar) findViewById(R.id. side_bar);
        listView = (ListView) findViewById(R.id. list_view);

        setCallbackInterface() ;

        List list = initData() ;

        chineseToPinyin(list) ;

        // 將聯系人列表的標題字母排序
        Collections. sort(list , new Comparator() {
            @Override
            public int compare(ContactsModel lhs, ContactsModel rhs) {
                return lhs.getFirstLetter().compareTo(rhs.getFirstLetter()) ;
            }
        });


        // 將聯系人列表的標題字母放到 List列表中,准備數據去重
        List getLetter = new ArrayList<>();
        for ( int i = 0 ; i < list.size(); i++) {
            getLetter.add(list.get(i).getFirstLetter());
        }

        // 數據去重
        getLetter = removeDuplicate(getLetter) ;

        // 將聯系人列表的字母標題排序
        Collections. sort(getLetter , new Comparator() {
            @Override
            public int compare(String lhs, String rhs) {
                return lhs.compareTo(rhs) ;
            }
        });

        // 設置已排序好的標題
        sideBar .setLetter(getLetter);


        myAdapter = new SideBarAdapter( this, list, R.layout.adapter_side_bar) ;
        listView .setAdapter(myAdapter) ;

    }

    /**
     * 將中文轉化為拼音
     */
    public void chineseToPinyin(List list) {
        for (int i = 0; i < list.size() ; i++) {
            ContactsModel contactsModel1 = list.get(i);
            // 將漢字轉換為拼音
            String pinyinString = PinyinHelper.getShortPinyin(list.get(i).getName()) ;
            // 將拼音字符串轉換為大寫拼音
            String upperCasePinyinString = String.valueOf(pinyinString.charAt( 0)).toUpperCase();
            // 獲取大寫拼音字符串的第一個字符
            char tempChar = upperCasePinyinString.charAt( 0);

            if (tempChar < 'A' || tempChar > 'Z' ) {
                contactsModel1.setFirstLetter( "#");
            } else {
                contactsModel1.setFirstLetter(String.valueOf(tempChar)) ;
            }
        }
    }

    /**
     * 設置回調接口
     */
    public void setCallbackInterface() {
        // 回調接口
        sideBar .setOnCurrentLetterListener(new SideBar.OnCurrentLetterListener() {
            @Override
            public void showCurrentLetter(String currentLetter) {
                txtShowCurrentLetter .setVisibility(View.VISIBLE) ;
                txtShowCurrentLetter.setText(currentLetter) ;

                int position = myAdapter.getCurrentItemPosition(currentLetter);
                if (position != -1 )
                    listView.setSelection(position) ;
            }

            @Override
            public void hideCurrentLetter() {
                txtShowCurrentLetter.setVisibility(View. GONE);
            }
        });
    }

    /**
     * 初始化數據
     */
    public List initData() {
        List list = new ArrayList<>();

        ContactsModel contactsModel ;
        String[] nameStrings = { "覃" , "岑 ", "$ 來啊,來互相傷害啊 ", "疍姬" , "梵蒂岡 ", " 亳州", "佟" , "郄 ", " 張三", "Edward", " 李四", "萌萌哒" , "霾耷 ", " 離散", "趙信" , "啦啦 ", " 辣妹子", "嗷嗷" , "妹妹 ", "']asd" , "%Hello"} ;
        for ( int i = 0 ; i < nameStrings.length ; i++) {
            contactsModel = new ContactsModel() ;
            contactsModel.setName(nameStrings[i]) ;
            list.add(contactsModel) ;
        }
        return list;
    }

    /**
     * 去重數據
     *
     * @param list
     * @param 
     * @return
     */
    public  List< T> removeDuplicate (List list) {

        Set h = new HashSet<>(list) ;
        list.clear() ;
        list.addAll(h) ;
        return list ;

    }
}


6、最後特別注意的是。在項目工程的libs文件夾裡面需要添加jpinyin.jar包(這個jar包可以在下面的demo源碼中copy出來)。

 

\

 

7、最終效果圖

 

\

 

  1. 上一頁:
  2. No
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved