android仿微信好友列表功能
android studio實(shí)現(xiàn)微信好友列表功能,注意有一個(gè)jar包我沒(méi)有放上來(lái),請(qǐng)大家到MainActivity中的那個(gè)網(wǎng)址里面下載即可,然后把pinyin4j-2.5.0.jar
復(fù)制粘貼到項(xiàng)目的app/libs文件夾里面,然后clean項(xiàng)目就可以使用了
實(shí)現(xiàn)效果圖:
(1)在build.gradle中引用第三方的類庫(kù)
compile 'com.android.support:recyclerview-v7:26.0.0-alpha1' compile files('libs/pinyin4j-2.5.0.jar')
(2)在MainActivity:
public class MainActivity extends AppCompatActivity { //參考網(wǎng)址:https://github.com/JanecineJohn/WeChatList private RecyclerView contactList; private String[] contactNames; private LinearLayoutManager layoutManager; private LetterView letterView; private ContactAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); contactNames = new String[] {"安然","奧茲","德瑪","張三豐", "郭靖", "黃蓉", "黃老邪", "趙敏", "123", "天山童姥", "任我行", "于萬(wàn)亭", "陳家洛", "韋小寶", "$6", "穆人清", "陳圓圓", "郭芙", "郭襄", "穆念慈", "東方不敗", "梅超風(fēng)", "林平之", "林遠(yuǎn)圖", "滅絕師太", "段譽(yù)", "鳩摩智"}; contactList = (RecyclerView) findViewById(R.id.contact_list); letterView = (LetterView) findViewById(R.id.letter_view); layoutManager = new LinearLayoutManager(this); adapter = new ContactAdapter(this, contactNames); contactList.setLayoutManager(layoutManager); contactList.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST)); contactList.setAdapter(adapter); letterView.setCharacterListener(new LetterView.CharacterClickListener() { @Override public void clickCharacter(String character) { layoutManager.scrollToPositionWithOffset(adapter.getScrollPosition(character),0); } @Override public void clickArrow() { layoutManager.scrollToPositionWithOffset(0,0); } }); } } (3)Contact類 public class Contact implements Serializable { private String mName; private int mType; public Contact(String name, int type) { mName = name; mType = type; } public String getmName() { return mName; } public int getmType() { return mType; } }
(3)listview好友列表適配器,在這里設(shè)置顯示的用戶名和頭像,并且添加點(diǎn)擊事件 ContactAdapter
public class ContactAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{ private LayoutInflater mLayoutInflater; private Context mContext; private String[] mContactNames; // 聯(lián)系人名稱字符串?dāng)?shù)組 private List<String> mContactList; // 聯(lián)系人名稱List(轉(zhuǎn)換成拼音) private List<Contact> resultList; // 最終結(jié)果(包含分組的字母) private List<String> characterList; // 字母List public enum ITEM_TYPE { ITEM_TYPE_CHARACTER, ITEM_TYPE_CONTACT } public ContactAdapter(Context context, String[] contactNames) { mContext = context; mLayoutInflater = LayoutInflater.from(context); mContactNames = contactNames; handleContact(); } private void handleContact() { mContactList = new ArrayList<>(); Map<String, String> map = new HashMap<>(); for (int i = 0; i < mContactNames.length; i++) { String pinyin = Utils.getPingYin(mContactNames[i]); map.put(pinyin, mContactNames[i]); mContactList.add(pinyin); } Collections.sort(mContactList, new ContactComparator()); resultList = new ArrayList<>(); characterList = new ArrayList<>(); for (int i = 0; i < mContactList.size(); i++) { String name = mContactList.get(i); String character = (name.charAt(0) + "").toUpperCase(Locale.ENGLISH); if (!characterList.contains(character)) { if (character.hashCode() >= "A".hashCode() && character.hashCode() <= "Z".hashCode()) { // 是字母 characterList.add(character); resultList.add(new Contact(character, ITEM_TYPE.ITEM_TYPE_CHARACTER.ordinal())); } else { if (!characterList.contains("#")) { characterList.add("#"); resultList.add(new Contact("#", ITEM_TYPE.ITEM_TYPE_CHARACTER.ordinal())); } } } resultList.add(new Contact(map.get(name), ITEM_TYPE.ITEM_TYPE_CONTACT.ordinal())); } } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == ITEM_TYPE.ITEM_TYPE_CHARACTER.ordinal()) { return new CharacterHolder(mLayoutInflater.inflate(R.layout.item_character, parent, false)); } else { return new ContactHolder(mLayoutInflater.inflate(R.layout.item_contact, parent, false)); } } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder instanceof CharacterHolder) { ((CharacterHolder) holder).mTextView.setText(resultList.get(position).getmName()); } else if (holder instanceof ContactHolder) { ((ContactHolder) holder).mTextView.setText(resultList.get(position).getmName()); } } @Override public int getItemViewType(int position) { return resultList.get(position).getmType(); } @Override public int getItemCount() { return resultList == null ? 0 : resultList.size(); } public class CharacterHolder extends RecyclerView.ViewHolder { TextView mTextView; CharacterHolder(View view) { super(view); mTextView = (TextView) view.findViewById(R.id.character); } } public class ContactHolder extends RecyclerView.ViewHolder { TextView mTextView; ContactHolder(View view) { super(view); mTextView = (TextView) view.findViewById(R.id.contact_name); } } public int getScrollPosition(String character) { if (characterList.contains(character)) { for (int i = 0; i < resultList.size(); i++) { if (resultList.get(i).getmName().equals(character)) { return i; } } } return -1; // -1不會(huì)滑動(dòng) } }
(4)ContactComparator 做英文字母的判斷
public class ContactComparator implements Comparator<String> { @Override public int compare(String o1, String o2) { int c1 = (o1.charAt(0) + "").toUpperCase().hashCode(); int c2 = (o2.charAt(0) + "").toUpperCase().hashCode(); boolean c1Flag = (c1 < "A".hashCode() || c1 > "Z".hashCode()); // 不是字母 boolean c2Flag = (c2 < "A".hashCode() || c2 > "Z".hashCode()); // 不是字母 if (c1Flag && !c2Flag) { return 1; } else if (!c1Flag && c2Flag) { return -1; } return c1 - c2; } }
(5)DividerItemDecoration
public class DividerItemDecoration extends RecyclerView.ItemDecoration { private static final int[] ATTRS = new int[]{ android.R.attr.listDivider }; public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; private Drawable mDivider; private int mOrientation; public DividerItemDecoration(Context context, int orientation) { final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = a.getDrawable(0); a.recycle(); setOrientation(orientation); } private void setOrientation(int orientation) { if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { throw new IllegalArgumentException("invalid orientation"); } mOrientation = orientation; } @Override public void onDraw(Canvas c, RecyclerView parent) { if (mOrientation == VERTICAL_LIST) { drawVertical(c, parent); } else { drawHorizontal(c, parent); } } // @Override // public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { // //super.onDraw(c, parent, state); // if (mOrientation == VERTICAL_LIST) { // drawVertical(c, parent); // } else { // drawHorizontal(c, parent); // } // } public void drawVertical(Canvas c, RecyclerView parent) { final int left = parent.getPaddingLeft(); final int right = parent.getWidth() - parent.getPaddingRight(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); final int top = child.getBottom() + params.bottomMargin + Math.round(ViewCompat.getTranslationY(child)); final int bottom = top + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } public void drawHorizontal(Canvas c, RecyclerView parent) { final int top = parent.getPaddingTop(); final int bottom = parent.getHeight() - parent.getPaddingBottom(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child .getLayoutParams(); final int left = child.getRight() + params.rightMargin + Math.round(ViewCompat.getTranslationX(child)); final int right = left + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } @Override public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) { if (mOrientation == VERTICAL_LIST) { outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); } else { outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); } } // @Override // public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { // if (mOrientation == VERTICAL_LIST){ // outRect.set(0,0,0,mDivider.getIntrinsicHeight()); // }else { // outRect.set(0,0,mDivider.getIntrinsicWidth(),0); // } // } }
(6)LetterView
public class LetterView extends LinearLayout{ private Context mContext; private CharacterClickListener mListener; public LetterView(Context context,AttributeSet attrs) { super(context, attrs); mContext = context;//接收傳進(jìn)來(lái)的上下文 setOrientation(VERTICAL); initView(); } private void initView(){ addView(buildImageLayout()); for (char i = 'A';i<='Z';i++){ final String character = i + ""; TextView tv = buildTextLayout(character); addView(tv); } addView(buildTextLayout("#")); } private TextView buildTextLayout(final String character){ LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,1); TextView tv = new TextView(mContext); tv.setLayoutParams(layoutParams); tv.setGravity(Gravity.CENTER); tv.setClickable(true); tv.setText(character); tv.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { if (mListener != null){ mListener.clickCharacter(character); } } }); return tv; } private ImageView buildImageLayout() { LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 1); ImageView iv = new ImageView(mContext); iv.setLayoutParams(layoutParams); iv.setBackgroundResource(R.mipmap.ic_launcher); iv.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (mListener != null) { mListener.clickArrow(); } } }); return iv; } public void setCharacterListener(CharacterClickListener listener) { mListener = listener; } public interface CharacterClickListener { void clickCharacter(String character); void clickArrow(); } }
(7)Utils
public class Utils { public static String getPingYin(String inputString) { HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat(); format.setCaseType(HanyuPinyinCaseType.LOWERCASE); format.setToneType(HanyuPinyinToneType.WITHOUT_TONE); format.setVCharType(HanyuPinyinVCharType.WITH_V); char[] input = inputString.trim().toCharArray(); String output = ""; try { for (char curchar : input) { if (java.lang.Character.toString(curchar).matches("[\\u4E00-\\u9FA5]+")) { String[] temp = PinyinHelper.toHanyuPinyinStringArray(curchar, format); output += temp[0]; } else { output += java.lang.Character.toString(curchar); } } } catch (BadHanyuPinyinOutputFormatCombination e) { e.printStackTrace(); } return output; } }
總結(jié)
以上所述是小編給大家介紹的android仿微信好友列表,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
詳解Android業(yè)務(wù)組件化之URL Schema使用
這篇文章主要為大家詳細(xì)介紹了Android業(yè)務(wù)組件化之URL Schema使用,感興趣的小伙伴們可以參考一下2016-09-09在AndroidManifest.xml中uses-sdk內(nèi)屬性意思
本文為大家講解下minSdkVersion、targetSdkVersion、maxSdkVersion、target API level四個(gè)數(shù)值的意思與區(qū)別,感興趣的朋友可以參考下哈2013-06-06Android實(shí)現(xiàn)仿excel數(shù)據(jù)表格效果
這篇文章主要介紹了Android實(shí)現(xiàn)仿excel數(shù)據(jù)表格效果的實(shí)現(xiàn)代碼,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下2016-10-10Android中Activity常用功能設(shè)置小結(jié)(包括全屏、橫豎屏等)
這篇文章主要介紹了Android中Activity常用功能設(shè)置小結(jié)(包括全屏、橫豎屏等),以簡(jiǎn)單實(shí)例形式分析了Android實(shí)現(xiàn)全屏、豎屏及一直顯示等的技巧與注意事項(xiàng),需要的朋友可以參考下2015-10-10android ContentResolver獲取手機(jī)電話號(hào)碼和短信內(nèi)容
這篇文章主要為大家詳細(xì)介紹了android ContentResolver獲取手機(jī)電話號(hào)碼、短信內(nèi)容,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07Android實(shí)現(xiàn)一對(duì)一藍(lán)牙聊天APP
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)一對(duì)一藍(lán)牙聊天APP,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06Android中AndroidStudio&Kotlin安裝到運(yùn)行過(guò)程及常見(jiàn)問(wèn)題匯總
這篇文章主要介紹了Android(AndroidStudio&Kotlin)安裝到運(yùn)行過(guò)程及常見(jiàn)問(wèn)題匯總,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒借鑒價(jià)值,需要的朋友可以參考下2020-03-03