之前没有实现过这样的功能,最近刚好在做通讯方面的项目, 所以联系人这块需要一个分组和索引的功能, 今天我们来一起学习.
实现的方法有两种:
每一个ItemView都有一个Header, 通过数据俩控制其显示或隐藏
使用不同类型的View.
我这里用了一个巧妙的方法.
可以看到这里实现了SectionIndexer接口, 这个接口用来控制ListView的分组的, 我们只要实现其中两个方法就好了, 分别是getPositionForSection(int position)和getSectionForPosition(int i).
public class GroupListViewAdapter extends BaseAdapter implements SectionIndexer {
private List mEntities;
private Context mContext;
public GroupListViewAdapter(List entities, Context context) {
mEntities = entities;
mContext = context;
}
@Override
public int getCount() {
return mEntities.size();
}
@Override
public Object getItem(int i) {
return mEntities.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder = null;
SortEntity sortEntity = mEntities.get(i);
if (view == null) {
viewHolder = new ViewHolder();
view = LayoutInflater.from(mContext).inflate(R.layout.layout_item_lv, null);
viewHolder.mTvLetter = (TextView) view.findViewById(R.id.tv_item_letter);
viewHolder.mTvTitle = (TextView) view.findViewById(R.id.tv_item_title);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
//下面就是来给字母分组
int section = getSectionForPosition(i);
if (i == getPositionForSection(section)) {
viewHolder.mTvLetter.setVisibility(View.VISIBLE);
viewHolder.mTvLetter.setText(sortEntity.getSortLetters());
} else {
viewHolder.mTvLetter.setVisibility(View.GONE);
}
viewHolder.mTvTitle.setText(sortEntity.getName());
return view;
}
class ViewHolder {
TextView mTvTitle;
TextView mTvLetter;
}
@Override
public Object[] getSections() {
return null;
}
//通过首字母的ascii码来获取在Listview中第一次出现该首字母的位置
@Override
public int getPositionForSection(int position) {
for (int i = 0; i < getCount(); i++) {
String sortStr = mEntities.get(i).getSortLetters();
char firstChar = sortStr.toUpperCase().charAt(0);
if (firstChar == position) {
return i;
}
}
return -1;
}
//根据ListView的position来获取该位置的首字母的ASCII码值
@Override
public int getSectionForPosition(int i) {
return mEntities.get(i).getSortLetters().charAt(0);
}
}
SortEntity
算是一个实体类, 实现了一个排序接口
public class SortEntity implements Comparator {
private String mName;
private String mSortLetters;
public String getName() {
return mName;
}
public void setName(String name) {
mName = name;
}
public String getSortLetters() {
return mSortLetters;
}
public void setSortLetters(String sortLetters) {
mSortLetters = sortLetters;
}
@Override
public int compare(SortEntity t1, SortEntity t2) {
return t1.getSortLetters().compareTo(t2.getSortLetters());
}
}
通过上面的ListView我们很方便的就可以实现这个索引栏
自定义的View, 实现如下:
public class SideBar extends View {
//分类字母
private static String[] sSideBarTitle;
private int mChoose = -1; //选择标记
private Paint mPaint; //画笔
private TextView mTvDialog; //显示框
private OnTouchLetterChangeListener mListener; //回调接口
int mHeight = 0;
int mWidth = 0;
int mSingleTextHeight;
public SideBar(Context context) {
super(context);
initView();
}
public SideBar(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initView();
}
public SideBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
private void initView() {
sSideBarTitle = getResources().getStringArray(R.array.sidebar);
mPaint = new Paint();
setPaint();
}
private void setPaint() {
mPaint.reset();
mPaint.setColor(Color.WHITE);
mPaint.setAntiAlias(true);
mPaint.setTypeface(Typeface.DEFAULT_BOLD);
mPaint.setTextSize(30);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mHeight = getMeasuredHeight();
mWidth = getMeasuredWidth();
mSingleTextHeight = mHeight / sSideBarTitle.length;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < sSideBarTitle.length; i++) {
if (i == mChoose) {
mPaint.setColor(getResources().getColor(R.color.colorAccent));
mPaint.setFakeBoldText(true);
}
float xPos = mWidth / 2 - mPaint.measureText(sSideBarTitle[i]) / 2;
float yPos = mSingleTextHeight * i + mSingleTextHeight;
canvas.drawText(sSideBarTitle[i], xPos, yPos, mPaint);
setPaint();
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
int action = event.getAction();
float y = event.getY();
int lastChoose = mChoose;
int scale = (int) (y / getHeight() * sSideBarTitle.length);
switch (action) {
case MotionEvent.ACTION_UP:
mChoose = -1;
if (mTvDialog != null) {
mTvDialog.setVisibility(View.INVISIBLE);
}
break;
default:
if (lastChoose != scale) {
if (scale >= 0 && scale < sSideBarTitle.length) {
if (mListener != null) {
mListener.letterChange(sSideBarTitle[scale]);
}
if (mTvDialog != null) {
mTvDialog.setText(sSideBarTitle[scale]);
mTvDialog.setVisibility(View.VISIBLE);
}
mChoose = scale;
}
}
break;
}
invalidate();
return true;
}
public void setOnTouchLetterChangeListener(OnTouchLetterChangeListener onTouchLetterChangeListener) {
this.mListener = onTouchLetterChangeListener;
}
public interface OnTouchLetterChangeListener {
void letterChange(String s);
}
public void setTvDialog(TextView tvDialog) {
mTvDialog = tvDialog;
}
}
MainActivity
主要就是数据的处理, 和接口的回调
public class MainActivity extends AppCompatActivity {
private ListView mLvFriends;
private Toolbar mTb;
private List mFriends;
private Handler mHandler;
private String mUserId;
private GroupListViewAdapter mAdapter;
private SortEntity mSortEntity;
private SideBar mSideBar;
private TextView mTvDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initEvent();
}
private void initView(){
mLvFriends = (ListView) findViewById(R.id.lv_main);
mSideBar = (SideBar) findViewById(R.id.sidebar);
mTvDialog = (TextView) findViewById(R.id.tv_dialog);
mSideBar.setTvDialog(mTvDialog);
mSortEntity = new SortEntity();
}
private void initEvent(){
mFriends = fillData(getResources().getStringArray(R.array.title));
Collections.sort(mFriends, mSortEntity); //对list排序
mAdapter = new GroupListViewAdapter(mFriends, this);
//接口的回调
mSideBar.setOnTouchLetterChangeListener(new SideBar.OnTouchLetterChangeListener() {
@Override
public void letterChange(String s) {
int position = mAdapter.getPositionForSection(s.charAt(0));
if (position != -1) {
mLvFriends.setSelection(position);
}
}
});
mLvFriends.setAdapter(mAdapter);
}
//填充数据
private List fillData(String[] data) {
List entities = new ArrayList<>();
for (int i = 0; i < data.length; i++) {
SortEntity sortEntity = new SortEntity();
sortEntity.setName(data[i]);
sortEntity.setSortLetters(data[i].substring(0, 1).toUpperCase());
entities.add(sortEntity);
}
return entities;
}
}