iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >Android之联系人PinnedHeaderListView使用介绍
  • 769
分享到

Android之联系人PinnedHeaderListView使用介绍

联系Android 2022-06-06 10:06:59 769人浏览 泡泡鱼
摘要

Android联系人中的ListView是做得比较独特的,但是源码写得比较复制,当我们想使用他的时候再从源码中提取,实属不易啊,而且容易出错,这几天,我把他提取出来了,写成一个

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_wid th="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,我就不贴出来了,有兴趣的朋友可以下载源码 您可能感兴趣的文章:Android编程实现通讯录中联系人的读取,查询,添加功能示例Android手机联系人快速索引(手机通讯录)Android获取手机通讯录、sim卡联系人及调用拨号界面方法使用adb命令向Android模拟器中导入通讯录联系人的方法Android系统联系人全特效实现(上)分组导航和挤压动画(附源码)Android根据电话号码获得联系人头像实例代码Android仿微信联系人按字母排序android 加载本地联系人实现方法Android保存联系人到通讯录的方法


--结束END--

本文标题: Android之联系人PinnedHeaderListView使用介绍

本文链接: https://www.lsjlt.com/news/27564.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 3 Linux之“男人”使用介绍
    每日一句:马哥你的每日一句呢!!! 果断搬出座右铭:宝剑锋从磨砺出,梅花香自苦寒来(=.=!)内部命令所谓内部命令,就是bash环境自带的命令,通过type COMMAND可查询内部命令可通过 help COMMAND 查看帮助[]:中括号...
    99+
    2023-01-31
    男人 Linux
  • Android WorkManager使用介绍
    一、引言   WorkManager 是google提供的异步执行任务的管理框架,是 Android Jetpack 的一部分,会根据手机的API版本和应用程序的状态来选择适当的方式执行任务。   在...
    99+
    2023-09-07
    android
  • Android ViewBinding使用介绍
    目录一、kotlin-android-extensions二、ViewBinding使用1.gradle配置2.在Activity 使用3.在Fragment使用4.在Adapter...
    99+
    2024-04-02
  • Android使用SimpleDateFormat警告介绍
    目录一、代码:二、警告内容:三、原因分析:四、解决方案:方法一:方法二:五、API一、代码: SimpleDateFormat simpleDateFormat = new S...
    99+
    2024-04-02
  • jQuery之$(document).ready()使用介绍
    $(document).ready()是一个jQuery的方法,用于在DOM加载完成后执行指定的代码。它的作用是确保在页面元素完全加载后再执行jQuery代码,以避免在DOM还未完全加载时执行代码导致的错误。使用$(document)....
    99+
    2023-08-09
    jQuery
  • Android中ListView使用示例介绍
    目录一、具体思路1、创建Listview控件3、写入4、读取5、创建对象,构造器,GETSET方法二、具体实施1、适配器2、数据库3、对象4、等等等等三、案例分享activity_m...
    99+
    2024-04-02
  • iOS砸壳系列之三:Frida介绍和使用
    当涉及从App Store下载应用程序时,它们都是已安装的iOS应用(IPA)存储在设备上。这些应用程序通常带有保护的代码和资源,以限制用户对其进行修改或者逆向工程。 然而,有时候,为了进行调试、制作...
    99+
    2023-10-09
    ios cocoa macos iOS逆向 objective-c
  • Android利用ContentProvider获取联系人信息
    本文实例为大家分享了Android利用ContentProvider获取联系人信息的具体代码,供大家参考,具体内容如下 在写代码前我们首先看一下运行的效果 运行效果如下: 点了获取...
    99+
    2024-04-02
  • Android使用AsyncQueryHandler实现获取手机联系人功能
    利用AsyncQueryHandler能异步任务获取手机联系人,增加用户体验,使用起来也很方便。不多说,上干货。布局文件main.xml<?xml version="1.0" encoding="utf-8"?>...
    99+
    2023-05-30
    android asyncqueryhandler 联系人
  • Android基础之常用控件属性介绍
    目录常用控件之常用属性控件可见性TextViewButtonEditTextImageViewProgressBarAlertDialogProgressDialogToastMen...
    99+
    2024-04-02
  • Android Q Labs 通用系统映像介绍
    Android Q Labs 通用系统映像是一种用于开发和测试Android Q系统的镜像文件。这个映像文件包含了Android Q...
    99+
    2023-09-21
    Android
  • Android传感器使用实例介绍
    目录传感器磁场传感器加速度传感器方向传感器传感器 1.mainActivity 实现SensorEventListerner 方法 2. 定义:SensorManage 对象 3. ...
    99+
    2022-12-16
    Android传感器开发 Android传感器
  • Android中Protobuf的基本使用介绍
    目录前言一、Proto文件示例二、在Android中的使用1、 plugin配置2.、基本调用总结前言 Protobuf,类似于json和xml,是一种序列化结构数据机制,可以用于数...
    99+
    2024-04-02
  • Android MaterialCardView的使用介绍与示例
    Android—MaterialCardView的使用 我们的征程是星辰大海,而非人间烟尘 文章目录 Android---MaterialCardView的使用演示xml布局其他的...
    99+
    2024-04-02
  • PHPYii2框架的关联模型使用介绍
    目录声明关联关系访问关联数据设置别名关联查询Active Record 可以将相关数据集中进来, 使其可以通过原始数据轻松访问。 例如,客户数据与订单数据相关 因为一个客户可能已经存...
    99+
    2024-04-02
  • 如何在Android应用中调用系统联系人界面
    今天就跟大家聊聊有关如何在Android应用中调用系统联系人界面,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一、添加联系人Intent addIntent =&...
    99+
    2023-05-31
    android roi
  • Python 之plt.plot()的介绍以及使用
    文章目录 介绍代码实例 介绍 plt.plot() 是Matplotlib库中用于绘制线图(折线图)的主要函数之一。它的作用是将一组数据点连接起来,以可视化数据的趋势、关系或模式。以下是...
    99+
    2023-10-23
    python 开发语言
  • Android内置SQLite的使用详细介绍
    目录一、创建数据库  1、新建数据库帮助类2、在数据库帮助类中输入代码3、代码讲解  二、添加数据1、界面效果2、准备工作3、布局界面 activity_main...
    99+
    2024-04-02
  • Android Studio Flamingo新版本Logcat使用介绍
    Android Studio更新后Logcat日志样式大变样了,和之前版本差别很大 下面就介绍下新版本的Logcat: 一、切换设备 可以选择切换当前打印日志的设备 二、日志过滤 和之前版本最大的区...
    99+
    2023-09-16
    android studio android ide
  • java基础之NIO介绍及使用
    目录一、NIO二、三大组件三、ByteBuffer的使用四、测试Demo五、Channel的使用六、网络编程七、Selector八、网络编程(多路复用)一、NIO java.nio...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作