当前位置: 移动技术网 > IT编程>移动开发>Android > Android之联系人PinnedHeaderListView使用介绍

Android之联系人PinnedHeaderListView使用介绍

2019年07月24日  | 移动技术网IT编程  | 我要评论

天网恢恢小品,人鱼粗鲁,大兵赵卫国小品

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,我就不贴出来了,有兴趣的朋友可以

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网