Android之联系人PinnedHeaderListView使用介绍

Android之联系人PinnedHeaderListView使用介绍,第1张

概述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,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,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,Alpha);
if (mheaderVIEw.gettop() != y) {
mheaderVIEw.layout(0,y,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,int defStyle) {
super(context,defStyle);
}
public BladeVIEw(Context 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);
}
}
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 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之联系人PinnedHeaderListView使用介绍全部内容,希望文章能够帮你解决Android之联系人PinnedHeaderListView使用介绍所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1142526.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存