Android之联系人PinnedHeaderListView使用
来源:互联网 发布:淘宝咸鱼官方下载 编辑:程序博客网 时间:2024/04/30 22:18
Android联系人中的ListView是做得比较独特的,但是源码写得比较复制,当我们想使用他的时候再从源码中提取,实属不易啊,而且容易出错,这几天,我把他提取出来了,写成一个简单的例子,一是给自己备忘,而是跟大家分享一下,好了,先来看看效果图:
首先是封装好的带头部的PinnedHeaderListView:
- public class PinnedHeaderListView extends ListView {
- public interface PinnedHeaderAdapter {
- public static final int PINNED_HEADER_GONE = 0;
- public static final int PINNED_HEADER_VISIBLE = 1;
- public static final int PINNED_HEADER_PUSHED_UP = 2;
- int getPinnedHeaderState(int position);
- void configurePinnedHeader(View header, int position, int alpha);
- }
- private static final int MAX_ALPHA = 255;
- private PinnedHeaderAdapter mAdapter;
- private View mHeaderView;
- private boolean mHeaderViewVisible;
- private int mHeaderViewWidth;
- private int mHeaderViewHeight;
- public PinnedHeaderListView(Context context) {
- super(context);
- }
- public PinnedHeaderListView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- public PinnedHeaderListView(Context context, AttributeSet attrs,
- int defStyle) {
- super(context, attrs, defStyle);
- }
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- if (mHeaderView != null) {
- mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);
- configureHeaderView(getFirstVisiblePosition());
- }
- }
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- if (mHeaderView != null) {
- measureChild(mHeaderView, widthMeasureSpec, heightMeasureSpec);
- mHeaderViewWidth = mHeaderView.getMeasuredWidth();
- mHeaderViewHeight = mHeaderView.getMeasuredHeight();
- }
- }
- public void setPinnedHeaderView(View view) {
- mHeaderView = view;
- if (mHeaderView != null) {
- setFadingEdgeLength(0);
- }
- requestLayout();
- }
- public void setAdapter(ListAdapter adapter) {
- super.setAdapter(adapter);
- mAdapter = (PinnedHeaderAdapter)adapter;
- }
- public void configureHeaderView(int position) {
- if (mHeaderView == null) {
- return;
- }
- int state = mAdapter.getPinnedHeaderState(position);
- switch (state) {
- case PinnedHeaderAdapter.PINNED_HEADER_GONE: {
- mHeaderViewVisible = false;
- break;
- }
- case PinnedHeaderAdapter.PINNED_HEADER_VISIBLE: {
- mAdapter.configurePinnedHeader(mHeaderView, position, MAX_ALPHA);
- if (mHeaderView.getTop() != 0) {
- mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);
- }
- mHeaderViewVisible = true;
- break;
- }
- case PinnedHeaderAdapter.PINNED_HEADER_PUSHED_UP: {
- View firstView = getChildAt(0);
- int bottom = firstView.getBottom();
- int headerHeight = mHeaderView.getHeight();
- int y;
- int alpha;
- if (bottom < headerHeight) {
- y = (bottom - headerHeight);
- alpha = MAX_ALPHA * (headerHeight + y) / headerHeight;
- } else {
- y = 0;
- alpha = MAX_ALPHA;
- }
- mAdapter.configurePinnedHeader(mHeaderView, position, alpha);
- if (mHeaderView.getTop() != y) {
- mHeaderView.layout(0, y, mHeaderViewWidth, mHeaderViewHeight
- + y);
- }
- mHeaderViewVisible = true;
- break;
- }
- }
- }
- protected void dispatchDraw(Canvas canvas) {
- super.dispatchDraw(canvas);
- if (mHeaderViewVisible) {
- drawChild(canvas, mHeaderView, getDrawingTime());
- }
- }
- }
然后是旁边那个快速导航BladeView(刀锋):
- public class BladeView extends View {
- private OnItemClickListener mOnItemClickListener;
- String[] b = { "#", "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" };
- int choose = -1;
- Paint paint = new Paint();
- boolean showBkg = false;
- private PopupWindow mPopupWindow;
- private TextView mPopupText;
- private Handler handler = new Handler();
- public BladeView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
- public BladeView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- public BladeView(Context context) {
- super(context);
- }
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (showBkg) {
- canvas.drawColor(Color.parseColor("#00000000"));
- }
- int height = getHeight();
- int width = getWidth();
- int singleHeight = height / b.length;
- for (int i = 0; i < b.length; i++) {
- paint.setColor(Color.BLACK);
- paint.setTypeface(Typeface.DEFAULT_BOLD);
- paint.setFakeBoldText(true);
- paint.setAntiAlias(true);
- if (i == choose) {
- paint.setColor(Color.parseColor("#3399ff"));
- }
- float xPos = width / 2 - paint.measureText(b[i]) / 2;
- float yPos = singleHeight * i + singleHeight;
- canvas.drawText(b[i], xPos, yPos, paint);
- paint.reset();
- }
- }
- @Override
- public boolean dispatchTouchEvent(MotionEvent event) {
- final int action = event.getAction();
- final float y = event.getY();
- final int oldChoose = choose;
- final int c = (int) (y / getHeight() * b.length);
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- showBkg = true;
- if (oldChoose != c) {
- if (c > 0 && c < b.length) {
- performItemClicked(c);
- choose = c;
- invalidate();
- }
- }
- break;
- case MotionEvent.ACTION_MOVE:
- if (oldChoose != c) {
- if (c > 0 && c < b.length) {
- performItemClicked(c);
- choose = c;
- invalidate();
- }
- }
- break;
- case MotionEvent.ACTION_UP:
- showBkg = false;
- choose = -1;
- dismissPopup();
- invalidate();
- break;
- }
- return true;
- }
- private void showPopup(int item) {
- if (mPopupWindow == null) {
- handler.removeCallbacks(dismissRunnable);
- mPopupText = new TextView(getContext());
- mPopupText.setBackgroundColor(Color.GRAY);
- mPopupText.setTextColor(Color.CYAN);
- mPopupText.setTextSize(50);
- mPopupText.setGravity(Gravity.CENTER_HORIZONTAL
- | Gravity.CENTER_VERTICAL);
- mPopupWindow = new PopupWindow(mPopupText, 100, 100);
- }
- String text = "";
- if (item == 0) {
- text = "#";
- } else {
- text = Character.toString((char) ('A' + item - 1));
- }
- mPopupText.setText(text);
- if (mPopupWindow.isShowing()) {
- mPopupWindow.update();
- } else {
- mPopupWindow.showAtLocation(getRootView(),
- Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL, 0, 0);
- }
- }
- private void dismissPopup() {
- handler.postDelayed(dismissRunnable, 800);
- }
- Runnable dismissRunnable = new Runnable() {
- @Override
- public void run() {
- // TODO Auto-generated method stub
- if (mPopupWindow != null) {
- mPopupWindow.dismiss();
- }
- }
- };
- public boolean onTouchEvent(MotionEvent event) {
- return super.onTouchEvent(event);
- }
- public void setOnItemClickListener(OnItemClickListener listener) {
- mOnItemClickListener = listener;
- }
- private void performItemClicked(int item) {
- if (mOnItemClickListener != null) {
- mOnItemClickListener.onItemClick(b[item]);
- showPopup(item);
- }
- }
- public interface OnItemClickListener {
- void onItemClick(String s);
- }
- }
接下来就是使用了,先在布局文件中声明activity_main.xml:
- <RelativeLayout 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"
- tools:context=".MainActivity" >
- <com.way.view.PinnedHeaderListView
- android:id="@+id/friends_display"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:cacheColorHint="#00000000"
- android:divider="@null"
- android:footerDividersEnabled="false"
- android:headerDividersEnabled="false" />
- <com.way.view.BladeView
- android:id="@+id/friends_myletterlistview"
- android:layout_width="30dip"
- android:layout_height="fill_parent"
- android:layout_alignParentRight="true"
- android:background="#00000000" />
- </RelativeLayout>
然后是一个独立Adapter,这次我没有作为内部类放在MainActivity中:
- public class FriendsAdapter extends BaseAdapter implements SectionIndexer,
- PinnedHeaderAdapter, OnScrollListener {
- private int mLocationPosition = -1;
- private String[] mDatas;
- // 首字母集
- private List<String> mFriendsSections;
- private List<Integer> mFriendsPositions;
- private LayoutInflater inflater;
- public FriendsAdapter(Context context,String[] datas, List<String> friendsSections,
- List<Integer> friendsPositions) {
- // TODO Auto-generated constructor stub
- inflater = LayoutInflater.from(context);
- mDatas = datas;
- mFriendsSections = friendsSections;
- mFriendsPositions = friendsPositions;
- }
- @Override
- public int getCount() {
- // TODO Auto-generated method stub
- return mDatas.length;
- }
- @Override
- public Object getItem(int position) {
- // TODO Auto-generated method stub
- return mDatas[position];
- }
- @Override
- public long getItemId(int position) {
- // TODO Auto-generated method stub
- return position;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- // TODO Auto-generated method stub
- int section = getSectionForPosition(position);
- if (convertView == null) {
- convertView = inflater.inflate(R.layout.listview_item, null);
- }
- LinearLayout mHeaderParent = (LinearLayout) convertView
- .findViewById(R.id.friends_item_header_parent);
- TextView mHeaderText = (TextView) convertView
- .findViewById(R.id.friends_item_header_text);
- if (getPositionForSection(section) == position) {
- mHeaderParent.setVisibility(View.VISIBLE);
- mHeaderText.setText(mFriendsSections.get(section));
- } else {
- mHeaderParent.setVisibility(View.GONE);
- }
- TextView textView = (TextView) convertView
- .findViewById(R.id.friends_item);
- textView.setText(mDatas[position]);
- return convertView;
- }
- @Override
- public void onScrollStateChanged(AbsListView view, int scrollState) {
- // TODO Auto-generated method stub
- }
- @Override
- public void onScroll(AbsListView view, int firstVisibleItem,
- int visibleItemCount, int totalItemCount) {
- // TODO Auto-generated method stub
- if (view instanceof PinnedHeaderListView) {
- ((PinnedHeaderListView) view).configureHeaderView(firstVisibleItem);
- }
- }
- @Override
- public int getPinnedHeaderState(int position) {
- int realPosition = position;
- if (realPosition < 0
- || (mLocationPosition != -1 && mLocationPosition == realPosition)) {
- return PINNED_HEADER_GONE;
- }
- mLocationPosition = -1;
- int section = getSectionForPosition(realPosition);
- int nextSectionPosition = getPositionForSection(section + 1);
- if (nextSectionPosition != -1
- && realPosition == nextSectionPosition - 1) {
- return PINNED_HEADER_PUSHED_UP;
- }
- return PINNED_HEADER_VISIBLE;
- }
- @Override
- public void configurePinnedHeader(View header, int position, int alpha) {
- // TODO Auto-generated method stub
- int realPosition = position;
- int section = getSectionForPosition(realPosition);
- String title = (String) getSections()[section];
- ((TextView) header.findViewById(R.id.friends_list_header_text))
- .setText(title);
- }
- @Override
- public Object[] getSections() {
- // TODO Auto-generated method stub
- return mFriendsSections.toArray();
- }
- @Override
- public int getPositionForSection(int section) {
- if (section < 0 || section >= mFriendsSections.size()) {
- return -1;
- }
- return mFriendsPositions.get(section);
- }
- @Override
- public int getSectionForPosition(int position) {
- // TODO Auto-generated method stub
- if (position < 0 || position >= getCount()) {
- return -1;
- }
- int index = Arrays.binarySearch(mFriendsPositions.toArray(), position);
- return index >= 0 ? index : -index - 2;
- }
- }
最后就是MainActivity中的处理了:
- public class MainActivity extends Activity {
- private static final String FORMAT = "^[a-z,A-Z].*$";
- private PinnedHeaderListView mListView;
- private BladeView mLetter;
- private FriendsAdapter mAdapter;
- private String[] datas;
- // 首字母集
- private List<String> mSections;
- // 根据首字母存放数据
- private Map<String, List<String>> mMap;
- // 首字母位置集
- private List<Integer> mPositions;
- // 首字母对应的位置
- private Map<String, Integer> mIndexer;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- initData();
- initView();
- }
- private void initData() {
- datas = getResources().getStringArray(R.array.countries);
- mSections = new ArrayList<String>();
- mMap = new HashMap<String, List<String>>();
- mPositions = new ArrayList<Integer>();
- mIndexer = new HashMap<String, Integer>();
- for (int i = 0; i < datas.length; i++) {
- String firstName = datas[i].substring(0, 1);
- if (firstName.matches(FORMAT)) {
- if (mSections.contains(firstName)) {
- mMap.get(firstName).add(datas[i]);
- } else {
- mSections.add(firstName);
- List<String> list = new ArrayList<String>();
- list.add(datas[i]);
- mMap.put(firstName, list);
- }
- } else {
- if (mSections.contains("#")) {
- mMap.get("#").add(datas[i]);
- } else {
- mSections.add("#");
- List<String> list = new ArrayList<String>();
- list.add(datas[i]);
- mMap.put("#", list);
- }
- }
- }
- Collections.sort(mSections);
- int position = 0;
- for (int i = 0; i < mSections.size(); i++) {
- mIndexer.put(mSections.get(i), position);// 存入map中,key为首字母字符串,value为首字母在listview中位置
- mPositions.add(position);// 首字母在listview中位置,存入list中
- position += mMap.get(mSections.get(i)).size();// 计算下一个首字母在listview的位置
- }
- }
- private void initView() {
- // TODO Auto-generated method stub
- mListView = (PinnedHeaderListView) findViewById(R.id.friends_display);
- mLetter = (BladeView) findViewById(R.id.friends_myletterlistview);
- mLetter.setOnItemClickListener(new OnItemClickListener() {
- @Override
- public void onItemClick(String s) {
- if (mIndexer.get(s) != null) {
- mListView.setSelection(mIndexer.get(s));
- }
- }
- });
- mAdapter = new FriendsAdapter(this, datas, mSections, mPositions);
- mListView.setAdapter(mAdapter);
- mListView.setOnScrollListener(mAdapter);
- mListView.setPinnedHeaderView(LayoutInflater.from(this).inflate(
- R.layout.listview_head, mListView, false));
- }
- }
还有一个数据arrays.xml,我就不贴出来了,有兴趣的朋友可以下源码看看:http://download.csdn.net/detail/weidi1989/5576125
1 0
- Android之联系人PinnedHeaderListView使用
- Android之联系人PinnedHeaderListView使用
- Android之联系人PinnedHeaderListView使用
- Android之联系人PinnedHeaderListView使用
- Android之联系人PinnedHeaderListView使用
- Android之联系人PinnedHeaderListView使用
- Android学习之联系人PinnedHeaderListView(通讯录)
- Android 联系人PinnedHeaderListView
- Android 联系人 PinnedHeaderListView
- Android_联系人PinnedHeaderListView使用
- Android下PinnedHeaderListView使用
- Android自定义View之PinnedHeaderListView
- Android仿联系人列表分组悬浮列表,PinnedHeaderListView源码解析
- Android——UI篇:使用pinnedheaderlistview实现联系人头部滑动到顶部定住的功能
- Android仿联系人列表分组悬浮列表实现,自定义PinnedHeaderListView实现
- Android Lollipop联系人之PinnedListView简单使用
- Android PinnedHeaderListView 详解
- PinnedHeaderListView
- projecteuler---->problem=16----Power digit sum
- SSH证书登陆配置详解
- [Java笔记]枚举的用法
- Servlet过滤器
- fedora下vim的安装
- Android之联系人PinnedHeaderListView使用
- android launcher添加一个app,如何知道classname
- HDU1237,简单计算器,Stack<Double>
- 全局变量与局部变量
- scala 读写文本设置字符编码
- bootargs 和 bootcmd 解析
- 台位数量超过9时,知识竞赛软件如何进行前期设置?
- 安慰安慰发完发违法
- 禁止多按钮触发