欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

android仿微信聯(lián)系人索引列表功能

 更新時(shí)間:2020年10月23日 08:49:58   作者:潘建成  
這篇文章主要為大家詳細(xì)介紹了android仿微信聯(lián)系人索引列表功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

前言

  因?yàn)樽约涸谧龅囊粋€(gè)小軟件里面需要用到從A-Z排序的ListView,所以自然而然的想到了微信的聯(lián)系人,我想要的就是那樣的效果。本來(lái)沒(méi)打算自己去寫(xiě),想要第三方寫(xiě)好的東西,搜了幾個(gè)之后發(fā)現(xiàn)有的太復(fù)雜了,有的簡(jiǎn)單是簡(jiǎn)單,但是不符合我的要求,所以我就來(lái)個(gè)整合,把復(fù)雜性和簡(jiǎn)單性合二為一。

實(shí)現(xiàn)

  先來(lái)看效果圖吧:

要點(diǎn)分析

  要實(shí)現(xiàn)這樣的效果需要考慮下面的幾個(gè)問(wèn)題:

  • 右邊字母欄的繪制
  • 點(diǎn)擊效果的實(shí)現(xiàn)
  • 漢字按A-Z的排序問(wèn)題
  • 正常的Item和字母分隔符的Item的實(shí)現(xiàn)

  下面我們就解決這幾個(gè)問(wèn)題,然后就可以出現(xiàn)上面的效果了。

【第一步】

  我們需要先自定義一個(gè)類(lèi),就叫SlideBar吧,讓它繼承Button,然后我們覆蓋onDraw方法,繪制字母a-z就可以出現(xiàn)右邊字母欄的效果了。

看一下源碼:

public class SlideBar extends Button{ 

 public interface OnTouchAssortListener{ 
 public void onTouchAssortListener(String s); 
 } 

 // 分類(lèi) 
 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); // 默認(rèn)粗體 
 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; // 計(jì)算字母的X坐標(biāo) 
 float yPos = nInterval * i + nInterval; // 計(jì)算字母的Y坐標(biāo) 
 canvas.drawText(ASSORT_TEXT[i], xPos, yPos, mPaint); 
 mPaint.reset(); 
 } 
 } 

 @Override
 public boolean dispatchTouchEvent(MotionEvent event) {
 //判斷是哪一個(gè)字母被點(diǎn)擊了
 int nIndex = (int) (event.getY() / getHeight() * ASSORT_TEXT.length);
 if (nIndex >= 0 && nIndex < ASSORT_TEXT.length){
 switch (event.getAction()){ 
 case MotionEvent.ACTION_MOVE: 
 // 如果滑動(dòng)改變 
 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方法,其他的內(nèi)容先不看,首先得到控件的寬和高,然后計(jì)算每一個(gè)字母應(yīng)該占據(jù)的高度為多少,然后在每一個(gè)字母所占空間的中間繪制該字母就可以了,代碼比較簡(jiǎn)單,這一部分就不需要詳解了。

【第二步】

  我們需要添加一個(gè)點(diǎn)擊事件,當(dāng)點(diǎn)擊SlideBar的時(shí)候,首先可以看到的是右邊欄被點(diǎn)擊的字母變大來(lái)區(qū)別于沒(méi)被點(diǎn)擊的字母,然后彈出一個(gè)類(lèi)似Dialog的東西,顯示被點(diǎn)中的字母,這個(gè)效果也很好實(shí)現(xiàn)。
  在SlideBar里面我們還需要覆蓋的一個(gè)方法是dispatchTouchEvent(),我們點(diǎn)中SlideBar之后,接下來(lái)的動(dòng)作可能是滑動(dòng)和抬起,我們需要對(duì)點(diǎn)擊之后的動(dòng)作進(jìn)行響應(yīng),如果是抬起的話,那么顯示出來(lái)的類(lèi)似dialog的東西就要消失,變大的字母也要回復(fù)原樣,如果是接著滑動(dòng),滑到某一個(gè)字母的時(shí)候,對(duì)應(yīng)的字母就要變大和顯示出來(lái)。
  從上面的源碼可以看到,字母變大的效果很好實(shí)現(xiàn),把繪制被選中的字母的Paint對(duì)象的textsize的值變大就可以了,然后那個(gè)類(lèi)似dialog的東西是用PopupWindow來(lái)實(shí)現(xiàn)的,當(dāng)點(diǎn)擊和滑動(dòng)的時(shí)候就顯示PopupWindow,抬起或者滑出SlideBar范圍的時(shí)候就讓PopupWindow消失。最后需要注意的是invalidate()這個(gè)方法千萬(wàn)不要忘記調(diào)用了,這個(gè)是用來(lái)進(jìn)行畫(huà)面的重繪。

【第三步】

  我認(rèn)為最重要也是最難的就是漢字按A-Z的排序了。不過(guò)還好,這個(gè)已經(jīng)有人實(shí)現(xiàn)了,我們就來(lái)所謂的“拿來(lái)主義”吧。在工程里面有一個(gè)CharacterParser類(lèi),這個(gè)類(lèi)封裝了對(duì)漢字轉(zhuǎn)拼音的操作,其中g(shù)etSelling(String s)方法的作用是傳入漢字字符串得到漢字的拼音,果然是好方法,我喜歡?。∵@樣我們就得到了要顯示的漢字字符串的拼音首字母,然后將所有的字符串按照字母進(jìn)行排序就可以得到一個(gè)從A-Z的有序的列表了。因?yàn)長(zhǎng)istView一般都是綁定一個(gè)List對(duì)象,然后List對(duì)象里面保存一系列的對(duì)象,這里我就用一個(gè)對(duì)象來(lái)說(shuō):

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方法 
 */
}

  這個(gè)對(duì)象里面需要注意的是兩個(gè)成員變量,item_type和item_en,分別表示該對(duì)象是要顯示的正常對(duì)象還是字母分隔符對(duì)象,根據(jù)item_type的不同,我們?cè)趯?xiě)Adapter的getView方法的時(shí)候就可以返回不同的View對(duì)象,然后就可以實(shí)現(xiàn)效果圖中的正常的Item和字母分割符Item了。item_en表示的是name變量也就是漢字字符串的拼音字符串,主要是用來(lái)獲取首字母和進(jìn)行字符串之間的比較。

  現(xiàn)在假設(shè)已經(jīng)有了一個(gè)List對(duì)象,里面保存了一些DataBean,那么問(wèn)題來(lái)了,如何把這些DataBean對(duì)象按拼音字符串進(jìn)行排序以及如何在List對(duì)象里面添加表示字母分隔符的DataBean對(duì)象呢?

首先解決排序的問(wèn)題,這個(gè)比較簡(jiǎn)單:

  這里用到了Collections的sort方法,這個(gè)方法有兩個(gè)參數(shù),一個(gè)就是帶排序的List對(duì)象,另一個(gè)是實(shí)現(xiàn)了Comparator接口的類(lèi)的對(duì)象,用來(lái)說(shuō)明如何進(jìn)行排序,用哪一個(gè)成員變量來(lái)進(jìn)行排序。

  PinyinComparator這個(gè)類(lèi)實(shí)現(xiàn)了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());
 }
 }
}

  可以看到,兩個(gè)DataBean對(duì)象按照變量item_en也就是拼音字符串來(lái)進(jìn)行排序,這樣實(shí)現(xiàn)起來(lái)比較方便,不需要自己去寫(xiě)排序的算法了,當(dāng)然也不反對(duì)大家自己去實(shí)現(xiàn)排序。

  經(jīng)過(guò)Collections的sort函數(shù)排序之后,現(xiàn)在List對(duì)象里面保存的DataBean對(duì)象已經(jīng)是按照A-Z進(jìn)行排序的了,現(xiàn)在我們要做的就是在這些對(duì)象里面插入一些用來(lái)表示字母分隔符DataBean的對(duì)象,這個(gè)實(shí)現(xiàn)應(yīng)該比較簡(jiǎn)單,我用的方法比較笨/(ㄒ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);
 }
}

  這個(gè)類(lèi)就實(shí)現(xiàn)了往List對(duì)象里面添加一些表示字母分隔符的對(duì)象,通過(guò)設(shè)置item_type變量的值不同,在Adapter里面根據(jù)這個(gè)值返回不同的View就可以實(shí)現(xiàn)不同的Item顯示。

  好了,到現(xiàn)在只剩一個(gè)問(wèn)題了,那就是點(diǎn)擊了字母之后,ListView設(shè)置該字母對(duì)應(yīng)的Item在第一個(gè)顯示,這個(gè)實(shí)現(xiàn)也不難,得到了被點(diǎn)中的字母之后,遍歷所有的DataBean對(duì)象,然后找到和當(dāng)前字母匹配的第一個(gè)字母分隔符對(duì)象,然后得到該Item的position的值,設(shè)置ListView被選中的Item的position為找到的Item的position即可。

  終于,所有的問(wèn)題解決了,看看現(xiàn)在自己能不能實(shí)現(xiàn)這樣的效果了呢?如果不行的話可以參考一個(gè)我的源碼。

小結(jié)

  本來(lái)我也是對(duì)這個(gè)不是太懂,但是強(qiáng)迫自己去看源碼,因?yàn)榫W(wǎng)上的大神寫(xiě)的東西可能并不是100%滿足自己的要求,所以自己能看懂源碼的話就可以自己去修改了。

源碼下載在這里。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android封裝的http請(qǐng)求實(shí)用工具類(lèi)

    Android封裝的http請(qǐng)求實(shí)用工具類(lèi)

    提供一個(gè)Android封裝的http請(qǐng)求實(shí)用工具類(lèi),在做ANDROID網(wǎng)絡(luò)開(kāi)發(fā)中這個(gè)經(jīng)常要用到,大家可以參考下面的工具類(lèi)修改成自己的工具
    2013-11-11
  • Android NDK開(kāi)發(fā)入門(mén)

    Android NDK開(kāi)發(fā)入門(mén)

    本文主要對(duì)NDK產(chǎn)生的背景、使用NDK原因、NDK簡(jiǎn)介、NDK開(kāi)發(fā)環(huán)境的搭建、如何運(yùn)行NDK提供的事例demo等進(jìn)行了詳細(xì)的介紹。具有很好的參考價(jià)值,需要的朋友一起來(lái)看下吧
    2016-12-12
  • RecyclerView實(shí)現(xiàn)查看更多及收起

    RecyclerView實(shí)現(xiàn)查看更多及收起

    這篇文章主要為大家詳細(xì)介紹了RecyclerView實(shí)現(xiàn)查看更多及收起,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • Android RecyclerView item選中放大被遮擋問(wèn)題詳解

    Android RecyclerView item選中放大被遮擋問(wèn)題詳解

    這篇文章主要介紹了Android RecyclerView item選中放大被遮擋問(wèn)題詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04
  • Android網(wǎng)絡(luò)技術(shù)HttpURLConnection詳解

    Android網(wǎng)絡(luò)技術(shù)HttpURLConnection詳解

    這篇文章主要為大家詳細(xì)介紹了Android網(wǎng)絡(luò)技術(shù)HttpURLConnection的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Android中ListView Item布局優(yōu)化技巧

    Android中ListView Item布局優(yōu)化技巧

    這篇文章主要介紹了Android中ListView Item布局優(yōu)化技巧,以實(shí)例形式分析了ListView Item布局的相關(guān)實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-10-10
  • Android返回鍵功能的實(shí)現(xiàn)方法

    Android返回鍵功能的實(shí)現(xiàn)方法

    這篇文章主要介紹了Android返回鍵功能的實(shí)現(xiàn)方法,實(shí)例分析了Android返回鍵的原理與具體的功能實(shí)現(xiàn)代碼,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-02-02
  • Android檢測(cè)Activity或者Service是否運(yùn)行的方法

    Android檢測(cè)Activity或者Service是否運(yùn)行的方法

    下面小編就為大家分享一篇Android檢測(cè)Activity或者Service是否運(yùn)行的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • 淺談android nexus私服的使用

    淺談android nexus私服的使用

    這篇文章主要介紹了淺談android nexus私服的使用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • Android CameraX結(jié)合LibYUV和GPUImage自定義相機(jī)濾鏡

    Android CameraX結(jié)合LibYUV和GPUImage自定義相機(jī)濾鏡

    之前使用Camera實(shí)現(xiàn)了一個(gè)自定義相機(jī)濾鏡(Android自定義相機(jī)濾鏡 ),但是運(yùn)行起來(lái)有點(diǎn)卡頓,這次用Camerax來(lái)實(shí)現(xiàn)一樣的效果發(fā)現(xiàn)很流暢,在此記錄一下,也希望能幫到有需要的同學(xué)
    2021-12-12

最新評(píng)論