主要就三个部分,一个是listview,一个是一侧的sidebar,还有就是加入一个checkbox的处理
1、ListView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/bg_grey"
android:fitsSystemWindows="true"
android:orientation="vertical"
tools:context="com.cn.app_bxb.ui.ActImportAddressBook">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="@dimen/title_height"
android:background="@color/white">
<ImageView
android:id="@+id/back"
style="@style/back_icon" />
<TextView
style="@style/UpTitle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="选择手机联系人" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/item_height"
android:layout_margin="15dp"
android:background="@drawable/bg_login_edit"
android:orientation="horizontal"
android:padding="5dp"
android:shadowRadius="160">
<ImageView
android:layout_width="20dp"
android:layout_height="match_parent"
android:src="@mipmap/add_search" />
<EditText
android:id="@+id/et_search_edit"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@null"
android:hint="搜索客户"
android:inputType="number"
android:padding="10dp"
android:textColorHint="@color/edit_text_hint_grey"
android:textSize="15dp" />
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/above_frame"
android:layout_width="match_parent"
android:layout_marginBottom="2dp"
android:layout_height="320dp">
<ListView
android:id="@+id/ls_contacts_listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:divider="@color/bg_grey"
android:dividerHeight="3dp"></ListView>
<TextView
android:id="@+id/tv_letter_notice"
style="@style/addressCircleButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:textSize="20sp"
android:visibility="gone" />
<TextView
android:id="@+id/pb_nocontacts_notice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="暂无匹配联系人"
android:visibility="gone" />
<com.cn.app_bxb.view.AlphabetScrollBar
android:id="@+id/alphabetscrollbar"
android:layout_width="30dp"
android:layout_height="match_parent"
android:layout_gravity="right" />
</FrameLayout>
<LinearLayout
android:layout_below="@id/above_frame"
android:id="@+id/bottom_buttons"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_selected_number"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:layout_weight="1"
android:background="@drawable/bg_import_button"
android:gravity="center"
android:text="已选择:0人"
android:textSize="25sp" />
<TextView
android:id="@+id/btn_yes"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/bg_import_button"
android:clickable="true"
android:gravity="center"
android:onClick="onClick"
android:textColor="@color/theme_red"
android:text="确定"
android:textSize="25sp" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
效果如下 当然,要定制一下listview里面的item
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/cut_item_LetterTag"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/bg_grey"
android:paddingLeft="5dp"
android:visibility="gone" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/contacts_first_letter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/addressCircleButton"
android:layout_alignParentLeft="true"
android:layout_marginLeft="10dp"/>
<TextView
android:id="@+id/contacts_name"
android:layout_width="wrap_content"
android:textSize="20dp"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:layout_height="wrap_content" />
<CheckBox
android:id="@+id/ck_is_checked"
android:layout_gravity="center"
android:layout_alignParentRight="true"
android:gravity="right"
android:paddingRight="30dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
</LinearLayout>
预览图如下
2、sidebar,也就是导航用的侧边栏,a~z的
package com.cn.app_bxb.view;
import android.content.Context;
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 android.widget.TextView;
/**
* Created by liushuqing on 16/3/11.
* 右侧的滑动点击条,用来选择联系人
*/
public class AlphabetScrollBar extends View {
private Paint mPaint = new Paint();
private String[] mAlphabet = new String[] {
"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 boolean mPressed;
private int mCurPosIdx = -1;
private int mOldPosIdx = -1;
private OnTouchBarListener mTouchListener;
private TextView LetterNotice;
public AlphabetScrollBar(Context arg0, AttributeSet arg1, int arg2) {
super(arg0, arg1, arg2);
}
public AlphabetScrollBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AlphabetScrollBar(Context context) {
super(context);
}
public void setTextView(TextView LetterNotice) {
this.LetterNotice = LetterNotice;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = this.getWidth();
int height = this.getHeight();
int singleLetterH = height/mAlphabet.length;
if(mPressed) {
//如果处于按下状态,改变背景及相应字体的颜色
canvas.drawColor(Color.parseColor("#40000000"));
}
for(int i=0; i<mAlphabet.length; i++) {
mPaint.setColor(Color.parseColor("#000000"));
mPaint.setAntiAlias(true);
mPaint.setTextSize(23);
float x = width/2 - mPaint.measureText(mAlphabet[i])/2;
float y = singleLetterH*i+singleLetterH;
if(i == mCurPosIdx)
{
mPaint.setColor(Color.parseColor("#0000FF"));
mPaint.setFakeBoldText(true);
}
canvas.drawText(mAlphabet[i], x, y, mPaint);
mPaint.reset();
}
}
@Override
public boolean onTouchEvent(MotionEvent arg0) {
int action = arg0.getAction();
switch(action) {
case MotionEvent.ACTION_DOWN:
mPressed = true;
mCurPosIdx =(int)( arg0.getY()/this.getHeight() * mAlphabet.length);
if(mTouchListener != null && mOldPosIdx!=mCurPosIdx){
if((mCurPosIdx>=0) && (mCurPosIdx<mAlphabet.length)) {
mTouchListener.onTouch(mAlphabet[mCurPosIdx]);
this.invalidate();
}
mOldPosIdx = mCurPosIdx;
}
LetterNotice.setText(mAlphabet[mCurPosIdx]);
LetterNotice.setVisibility(View.VISIBLE);
return true;
case MotionEvent.ACTION_UP:
if (LetterNotice != null) {
LetterNotice.setVisibility(View.INVISIBLE);
}
mPressed = false;
mCurPosIdx = -1;
this.invalidate();
return true;
case MotionEvent.ACTION_MOVE:
mCurPosIdx =(int)( arg0.getY()/this.getHeight() * mAlphabet.length);
if(mTouchListener != null && mCurPosIdx!=mOldPosIdx){
if((mCurPosIdx>=0) && (mCurPosIdx<mAlphabet.length)) {
mTouchListener.onTouch(mAlphabet[mCurPosIdx]);
this.invalidate();
}
mOldPosIdx = mCurPosIdx;
}
if(mCurPosIdx >= 0 && mCurPosIdx < mAlphabet.length)
{
LetterNotice.setText(mAlphabet[mCurPosIdx]);
LetterNotice.setVisibility(View.VISIBLE);
}
return true;
default:
return super.onTouchEvent(arg0);
}
}
/**
* 接口
*/
public static interface OnTouchBarListener {
void onTouch(String letter);
}
/**
* 向外公开的方法
*/
public void setOnTouchBarListener (OnTouchBarListener listener) {
mTouchListener = listener;
}
}
3、Activity里面对于checkbox的处理
package com.cn.app_bxb.ui;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import com.alibaba.fastjson.JSON;
import com.cn.app_bxb.R;
import com.cn.app_bxb.api.model.User;
import com.cn.app_bxb.view.AlphabetScrollBar;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import bxb.cn.base.BaseActivity;
import bxb.cn.base.injection.Id;
import bxb.cn.base.injection.Layout;
import bxb.cn.base.util.LogUtil;
import bxb.cn.base.util.NullUtil;
import bxb.cn.base.util.PinyinUtils;
@Layout(R.layout.activity_import_address_book)
public class ActImportAddressBook extends BaseActivity {
private static final String TAG = "bxb";
@Id(R.id.tv_selected_number)
private TextView tvSelectedNumber;
@Id(R.id.btn_yes)
private TextView btnImport;
//字母列视图View
@Id(R.id.alphabetscrollbar)
private AlphabetScrollBar side_bar;
//显示选中的字母
@Id(R.id.tv_letter_notice)
private TextView tvFirstLetterNotice;
//联系人的列表
@Id(R.id.ls_contacts_listview)
private ListView contactsListView;
//联系人列表的适配器
private ListAdapter listViewAdapter;
//所有联系人数组
private ArrayList<User> persons = new ArrayList<>();
//被选中联系人数组
private List<User> checkedUsers = new ArrayList<>();
//过滤列表中的联系人数组
ArrayList<User> filterpersons = new ArrayList<User>();
//搜索过滤联系人EditText
@Id(R.id.et_search_edit)
private EditText etSearchEditText;
//没有匹配联系人时显示的TextView
@Id(R.id.pb_nocontacts_notice)
private TextView listEmptyText;
private int checkedNum=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//获取手机中的联系人,并将所有联系人保存perosns数组中
//联系人比较多的话,初始化中会比较耗时,以后再优化
getContacts();
//得到字母列的对象,并设置触摸响应监听器
side_bar.setOnTouchBarListener(new ScrollBarListener());
side_bar.setTextView(tvFirstLetterNotice);
// 根据拼音为联系人数组进行排序
Collections.sort(persons, new UserPinyinComparator());
//得到联系人列表,并设置适配器
listViewAdapter = new ListAdapter(this, persons);
contactsListView.setAdapter(listViewAdapter);
//初始化搜索编辑框,设置文本改变时的监听器
etSearchEditText.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (!"".equals(s.toString().trim())) {
//根据编辑框值过滤联系人并更新联系列表
filterContacts(s.toString().trim());
side_bar.setVisibility(View.GONE);
} else {
side_bar.setVisibility(View.VISIBLE);
listViewAdapter.updateListView(persons);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.tv_selected_number:
break;
case R.id.btn_yes:
updateSelectedUsers();
importsers();
LogUtil.i(TAG,"这些人被选中"+JSON.toJSONString(checkedUsers));
break;
}
super.onClick(v);
}
/**
*更新被选中的人
*/
private void updateSelectedUsers(){
checkedUsers.clear();
for(User user:persons){
if(user.isChecked()&&!checkedUsers.contains(user)){
checkedUsers.add(user);
}
}
for(User user:filterpersons){
if(user.isChecked()&&!checkedUsers.contains(user)){
checkedUsers.add(user);
}
}
}
/**
* TODO 调用导入联系人API
*/
private void importsers(){
LogUtil.d(TAG,"导入联系人");
}
/**
* 按照名字拼音进行排序
*/
public class UserPinyinComparator implements Comparator<User> {
@Override
public int compare(User lhs, User rhs) {
String str1 = lhs.getPinyinName();
String str2 = rhs.getPinyinName();
return str1.compareToIgnoreCase(str2);
}
}
public class ListAdapter extends BaseAdapter {
private LayoutInflater m_inflater;
private ArrayList<User> users;
private Context context;
public ListAdapter(Context context,
ArrayList<User> persons) {
this.m_inflater = LayoutInflater.from(context);
this.users = persons;
this.context = context;
}
//当联系人列表数据发生变化时,用此方法来更新列表
public void updateListView(ArrayList<User> persons) {
this.users = persons;
notifyDataSetChanged();
}
@Override
public int getCount() {
return users.size();
}
@Override
public Object getItem(int position) {
return users.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final int mPosition = position;
LogUtil.d(TAG, "list里面应该展示的" + JSON.toJSONString(users.get(position)));
//获得一个联系人item,下面的所有都是从这个item里面提取
convertView = m_inflater.inflate(R.layout.address_item, null);
//名字
TextView name = (TextView) convertView.findViewById(R.id.contacts_name);
name.setText(users.get(position).getName());
//复选框
final CheckBox checkBox=(CheckBox)convertView.findViewById(R.id.ck_is_checked);
checkBox.setChecked(users.get(position).isChecked());//保证已经被选中的还可以拿得到
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
users.get(mPosition).setChecked(isChecked);
updateSelectedUsers();
tvSelectedNumber.setText("已经被选中"+ checkedUsers.size()+"人");
LogUtil.i(TAG,users.get(mPosition).getName()+": 被改变选中状态");
notifyDataSetChanged();//更新选中数据
listViewAdapter.updateListView(persons);
}
});
//名字第一个字,圆形里面展示用的
TextView firstLetter = (TextView) convertView.findViewById(R.id.contacts_first_letter);
firstLetter.setText(users.get(position).getFirstLetter());
//字母提示textview的显示,就是不同之母之间分解的时候出现的
TextView letterTag = (TextView) convertView.findViewById(R.id.cut_item_LetterTag);
//获得当前姓名的拼音首字母,排序用的,并不展示
String sortLetter = users.get(position).getSortLetter();
//TODO 这儿实现的好巧妙啊啊啊嗷嗷啊啊啊 如果是第1个联系人 那么letterTag始终要显示
if (position == 0) {
letterTag.setVisibility(View.VISIBLE);
letterTag.setText(sortLetter);
} else {
//获得上一个姓名的拼音首字母
String firstLetterPre = users.get(position - 1).getSortLetter();
//比较一下两者是否相同
if (sortLetter.equals(firstLetterPre)) {
letterTag.setVisibility(View.GONE);
} else {
letterTag.setVisibility(View.VISIBLE);
letterTag.setText(sortLetter);
}
}
return convertView;
}
}
//字母列触摸的监听器
private class ScrollBarListener implements AlphabetScrollBar.OnTouchBarListener {
@Override
public void onTouch(String letter) {
//触摸字母列时,将联系人列表更新到首字母出现的位置
for (int i = 0; i < persons.size(); i++) {
if (persons.get(i).getSortLetter().compareToIgnoreCase(letter) == 0) {
contactsListView.setSelection(i);
break;
}
}
}
}
/**
* 读取联系人
*/
public void getContacts() {
ContentResolver contentResolver = getContentResolver();
// 获得所有联系人数据集的游标
Cursor cursor = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
// 循环遍历
if (cursor.moveToFirst()) {
int idColumn = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID);
int displayNameColumn = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
int NumberColumn = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
while (cursor.moveToNext()) {
User person = new User();
// 获得联系人的ID号
String contactId = cursor.getString(idColumn);
// 获得联系人姓名
person.setName(cursor.getString(displayNameColumn));
person.setPinyinName(PinyinUtils.getPingYin(person.getName()));
person.setSortLetter(PinyinUtils.getFirstSpell(person.getName()));
//名字可能是空的,如果是null,就让它是空格吧
person.setFirstLetter(NullUtil.ept(person.getName()) ? "" : person.getName().substring(0, 1));
person.setPhone(cursor.getString(NumberColumn));
LogUtil.d(TAG, JSON.toJSONString(person));
persons.add(person);
}
cursor.close();
}
}
/**
* 过滤联系人
*
* @param filterStr
*/
private void filterContacts(String filterStr) {
//先清空原来的
filterpersons.clear();
//遍历所有联系人数组,筛选出包含关键字的联系人
for (int i = 0; i < persons.size(); i++) {
//过滤的条件
if (isStrInString(persons.get(i).getPhone(), filterStr)
|| isStrInString(persons.get(i).getPinyinName(), filterStr)
|| persons.get(i).getName().contains(filterStr)
|| isStrInString(persons.get(i).getFirstLetter(), filterStr)) {
//将筛选出来的联系人重新添加到filterpersons数组中
filterpersons.add(persons.get(i));
}
}
//如果没有匹配的联系人
if (filterpersons.isEmpty()) {
contactsListView.setEmptyView(listEmptyText);
}
//将列表更新为过滤的联系人
listViewAdapter.updateListView(filterpersons);
}
public boolean isStrInString(String bigStr, String smallStr) {
if (bigStr.toUpperCase().indexOf(smallStr.toUpperCase()) > -1) {
return true;
} else {
return false;
}
}
}