Android 分组ListView+索引条
来源:互联网 发布:mac os x10.10iso镜像 编辑:程序博客网 时间:2024/05/21 04:00
前言
之前没有实现过这样的功能,最近刚好在做通讯方面的项目, 所以联系人这块需要一个分组和索引的功能, 今天我们来一起学习.
分组ListView
实现的方法有两种:
每一个ItemView都有一个Header, 通过数据俩控制其显示或隐藏
使用不同类型的View.
我这里用了一个巧妙的方法.
代码:
Adapter
可以看到这里实现了SectionIndexer接口, 这个接口用来控制ListView的分组的, 我们只要实现其中两个方法就好了, 分别是getPositionForSection(int position)和getSectionForPosition(int i).
public class GroupListViewAdapter extends BaseAdapter implements SectionIndexer { private List<SortEntity> mEntities; private Context mContext; public GroupListViewAdapter(List<SortEntity> 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<SortEntity> { 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()); }}
SideBar
通过上面的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<SortEntity> 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<SortEntity> fillData(String[] data) { List<SortEntity> 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; }}
最终效果
项目地址: https://github.com/thatnight/GroupListView_SideBar
0 0
- Android 分组ListView+索引条
- Android ListView实现分组字母索引排序
- android实现分组字母索引显示的listview
- android实现分组字母索引显示的listview
- android之ListView分组及字母索引导航
- Android ListView列表分组
- android ListView简单分组
- Android ListView分组布局
- Android listView分组
- Android ListView列表分组
- Android ListView列表分组
- Android listView分组
- Android ListView分组
- android ListView分组显示
- Android listview实现分组
- Win10开发:ListView实现分组和索引
- ListView分组显示,设置悬浮条
- android之ListView分组及字母索引导航(2)重构-接口
- [Algorithm]九章三:Binary Tree & Divide Conquer
- FEP: 测试 lineage, 获得 CPU, MEMORY 统计信息
- 线程池的submit和execute的区别
- C语言链表使用详解
- FEP: 测试 docker matrix, 获得 CPU, MEMORY, 网络性能的 统计信息
- Android 分组ListView+索引条
- 利用jsoup爬取网页信息
- PAT-A-1039. Course List for Student (25)
- java设计模式之建造者模式
- 如何指定html中select控件的宽度?
- activity之间及fragment之间切换的动画效果
- 构造KD树,并用KD树求最近邻点
- YII框架的依赖注入容器
- 网页添加icon小图标