本文实例为大家分享了android ui仿qq好友列表分组悬浮效果的具体代码,供大家参考,具体内容如下
楼主是在平板上測试的。图片略微有点大,大家看看效果就好
接下来贴源代码:
pinnedheaderexpandablelistview.java
要注意的是 在 ongroupclick方法中parent.setselectedgroup(groupposition)这句代码的作用是点击分组置顶,
我这边不须要这个效果。qq也没实用到,所以给凝视了。大家假设须要能够解开凝视
package com.xiaos.view; import android.content.context; import android.graphics.canvas; import android.util.attributeset; import android.view.motionevent; import android.view.view; import android.view.viewgroup; import android.widget.abslistview; import android.widget.abslistview.onscrolllistener; import android.widget.expandablelistadapter; import android.widget.expandablelistview; import android.widget.expandablelistview.ongroupclicklistener; public class pinnedheaderexpandablelistview extends expandablelistview implements onscrolllistener,ongroupclicklistener { public pinnedheaderexpandablelistview(context context, attributeset attrs, int defstyle) { super(context, attrs, defstyle); registerlistener(); } public pinnedheaderexpandablelistview(context context, attributeset attrs) { super(context, attrs); registerlistener(); } public pinnedheaderexpandablelistview(context context) { super(context); registerlistener(); } /** * adapter 接口 . 列表必须实现此接口 . */ public interface headeradapter { 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; /** * 获取 header 的状态 * @param groupposition * @param childposition * @return pinned_header_gone,pinned_header_visible,pinned_header_pushed_up 当中之中的一个 */ int getheaderstate(int groupposition, int childposition); /** * 配置 header, 让 header 知道显示的内容 * @param header * @param groupposition * @param childposition * @param alpha */ void configureheader(view header, int groupposition,int childposition, int alpha); /** * 设置组按下的状态 * @param groupposition * @param status */ void setgroupclickstatus(int groupposition, int status); /** * 获取组按下的状态 * @param groupposition * @return */ int getgroupclickstatus(int groupposition); } private static final int max_alpha = 255; private headeradapter madapter; /** * 用于在列表头显示的 view,mheaderviewvisible 为 true 才可见 */ private view mheaderview; /** * 列表头是否可见 */ private boolean mheaderviewvisible; private int mheaderviewwidth; private int mheaderviewheight; public void setheaderview(view view) { mheaderview = view; abslistview.layoutparams lp = new abslistview.layoutparams( viewgroup.layoutparams.match_parent, viewgroup.layoutparams.wrap_content); view.setlayoutparams(lp); if (mheaderview != null) { setfadingedgelength(0); } requestlayout(); } private void registerlistener() { setonscrolllistener(this); setongroupclicklistener(this); } /** * 点击 headerview 触发的事件 */ private void headerviewclick() { long packedposition = getexpandablelistposition(this.getfirstvisibleposition()); int groupposition = expandablelistview.getpackedpositiongroup(packedposition); if (madapter.getgroupclickstatus(groupposition) == 1) { this.collapsegroup(groupposition); madapter.setgroupclickstatus(groupposition, 0); } else{ this.expandgroup(groupposition); madapter.setgroupclickstatus(groupposition, 1); } this.setselectedgroup(groupposition); } private float mdownx; private float mdowny; /** * 假设 headerview 是可见的 , 此函数用于推断是否点击了 headerview, 并对做对应的处理 , * 由于 headerview 是画上去的 , 所以设置事件监听是无效的 , 仅仅有自行控制 . */ @override public boolean ontouchevent(motionevent ev) { if (mheaderviewvisible) { switch (ev.getaction()) { case motionevent.action_down: mdownx = ev.getx(); mdowny = ev.gety(); if (mdownx <= mheaderviewwidth && mdowny <= mheaderviewheight) { return true; } break; case motionevent.action_up: float x = ev.getx(); float y = ev.gety(); float offsetx = math.abs(x - mdownx); float offsety = math.abs(y - mdowny); // 假设 headerview 是可见的 , 点击在 headerview 内 , 那么触发 headerclick() if (x <= mheaderviewwidth && y <= mheaderviewheight && offsetx <= mheaderviewwidth && offsety <= mheaderviewheight) { if (mheaderview != null) { headerviewclick(); } return true; } break; default: break; } } return super.ontouchevent(ev); } @override public void setadapter(expandablelistadapter adapter) { super.setadapter(adapter); madapter = (headeradapter) adapter; } /** * * 点击了 group 触发的事件 , 要依据依据当前点击 group 的状态来 */ @override public boolean ongroupclick(expandablelistview parent,view v,int groupposition,long id) { if (madapter.getgroupclickstatus(groupposition) == 0) { madapter.setgroupclickstatus(groupposition, 1); parent.expandgroup(groupposition); //header自己主动置顶 //parent.setselectedgroup(groupposition); } else if (madapter.getgroupclickstatus(groupposition) == 1) { madapter.setgroupclickstatus(groupposition, 0); parent.collapsegroup(groupposition); } // 返回 true 才干够弹回第一行 , 不知道为什么 return true; } @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { super.onmeasure(widthmeasurespec, heightmeasurespec); if (mheaderview != null) { measurechild(mheaderview, widthmeasurespec, heightmeasurespec); mheaderviewwidth = mheaderview.getmeasuredwidth(); mheaderviewheight = mheaderview.getmeasuredheight(); } } private int moldstate = -1; @override protected void onlayout(boolean changed, int left, int top, int right,int bottom) { super.onlayout(changed, left, top, right, bottom); final long flatpostion = getexpandablelistposition(getfirstvisibleposition()); final int grouppos = expandablelistview.getpackedpositiongroup(flatpostion); final int childpos = expandablelistview.getpackedpositionchild(flatpostion); int state = madapter.getheaderstate(grouppos, childpos); if (mheaderview != null && madapter != null && state != moldstate) { moldstate = state; mheaderview.layout(0, 0, mheaderviewwidth, mheaderviewheight); } configureheaderview(grouppos, childpos); } public void configureheaderview(int groupposition, int childposition) { if (mheaderview == null || madapter == null || ((expandablelistadapter) madapter).getgroupcount() == 0) { return; } int state = madapter.getheaderstate(groupposition, childposition); switch (state) { case headeradapter.pinned_header_gone: { mheaderviewvisible = false; break; } case headeradapter.pinned_header_visible: { madapter.configureheader(mheaderview, groupposition,childposition, max_alpha); if (mheaderview.gettop() != 0){ mheaderview.layout(0, 0, mheaderviewwidth, mheaderviewheight); } mheaderviewvisible = true; break; } case headeradapter.pinned_header_pushed_up: { view firstview = getchildat(0); int bottom = firstview.getbottom(); // intitemheight = firstview.getheight(); 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.configureheader(mheaderview, groupposition,childposition, alpha); if (mheaderview.gettop() != y) { mheaderview.layout(0, y, mheaderviewwidth, mheaderviewheight + y); } mheaderviewvisible = true; break; } } } @override /** * 列表界面更新时调用该方法(如滚动时) */ protected void dispatchdraw(canvas canvas) { super.dispatchdraw(canvas); if (mheaderviewvisible) { //分组栏是直接绘制到界面中。而不是增加到viewgroup中 drawchild(canvas, mheaderview, getdrawingtime()); } } @override public void onscroll(abslistview view, int firstvisibleitem,int visibleitemcount, int totalitemcount) { final long flatpos = getexpandablelistposition(firstvisibleitem); int groupposition = expandablelistview.getpackedpositiongroup(flatpos); int childposition = expandablelistview.getpackedpositionchild(flatpos); configureheaderview(groupposition, childposition); } @override public void onscrollstatechanged(abslistview view, int scrollstate) { } }
pinnedheaderexpandableadapter.java 适配器
实现了pinnedheaderexpandablelistview中headeradapter接口
package com.xiaos.adapter; import android.content.context; import android.util.sparseintarray; import android.view.layoutinflater; import android.view.view; import android.view.viewgroup; import android.widget.baseexpandablelistadapter; import android.widget.imageview; import android.widget.textview; import com.xiaos.pinnedheaderexpandable.r; import com.xiaos.view.pinnedheaderexpandablelistview; import com.xiaos.view.pinnedheaderexpandablelistview.headeradapter; public class pinnedheaderexpandableadapter extends baseexpandablelistadapter implements headeradapter{ private string[][] childrendata; private string[] groupdata; private context context; private pinnedheaderexpandablelistview listview; private layoutinflater inflater; public pinnedheaderexpandableadapter(string[][] childrendata,string[] groupdata ,context context,pinnedheaderexpandablelistview listview){ this.groupdata = groupdata; this.childrendata = childrendata; this.context = context; this.listview = listview; inflater = layoutinflater.from(this.context); } @override public object getchild(int groupposition, int childposition) { return childrendata[groupposition][childposition]; } @override public long getchildid(int groupposition, int childposition) { return 0; } @override public view getchildview(int groupposition, int childposition, boolean islastchild, view convertview, viewgroup parent) { view view = null; if (convertview != null) { view = convertview; } else { view = createchildrenview(); } textview text = (textview)view.findviewbyid(r.id.childto); text.settext(childrendata[groupposition][childposition]); return view; } @override public int getchildrencount(int groupposition) { return childrendata[groupposition].length; } @override public object getgroup(int groupposition) { return groupdata[groupposition]; } @override public int getgroupcount() { return groupdata.length; } @override public long getgroupid(int groupposition) { return 0; } @override public view getgroupview(int groupposition, boolean isexpanded, view convertview, viewgroup parent) { view view = null; if (convertview != null) { view = convertview; } else { view = creategroupview(); } imageview iv = (imageview)view.findviewbyid(r.id.groupicon); if (isexpanded) { iv.setimageresource(r.drawable.btn_browser2); } else{ iv.setimageresource(r.drawable.btn_browser); } textview text = (textview)view.findviewbyid(r.id.groupto); text.settext(groupdata[groupposition]); return view; } @override public boolean hasstableids() { return true; } @override public boolean ischildselectable(int groupposition, int childposition) { return true; } private view createchildrenview() { return inflater.inflate(r.layout.child, null); } private view creategroupview() { return inflater.inflate(r.layout.group, null); } @override public int getheaderstate(int groupposition, int childposition) { final int childcount = getchildrencount(groupposition); if (childposition == childcount - 1) { return pinned_header_pushed_up; } else if (childposition == -1 && !listview.isgroupexpanded(groupposition)) { return pinned_header_gone; } else { return pinned_header_visible; } } @override public void configureheader(view header, int groupposition, int childposition, int alpha) { string groupdata = this.groupdata[groupposition]; ((textview) header.findviewbyid(r.id.groupto)).settext(groupdata); } private sparseintarray groupstatusmap = new sparseintarray(); @override public void setgroupclickstatus(int groupposition, int status) { groupstatusmap.put(groupposition, status); } @override public int getgroupclickstatus(int groupposition) { if (groupstatusmap.keyat(groupposition)>=0) { return groupstatusmap.get(groupposition); } else { return 0; } } }
mainactivity.java主activity
package com.xiaos.pinnedheaderexpandable; import android.app.activity; import android.os.bundle; import android.view.view; import android.widget.expandablelistview; import android.widget.expandablelistview.ongroupclicklistener; import com.xiaos.adapter.pinnedheaderexpandableadapter; import com.xiaos.view.pinnedheaderexpandablelistview; public class mainactivity extends activity{ private pinnedheaderexpandablelistview explistview; private string[][] childrendata = new string[10][10]; private string[] groupdata = new string[10]; private int expandflag = -1;//控制列表的展开 private pinnedheaderexpandableadapter adapter; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.layout_main); initview(); initdata(); } /** * 初始化view */ private void initview() { explistview = (pinnedheaderexpandablelistview)findviewbyid(r.id.explistview); } /** * 初始化数据 */ private void initdata() { for(int i=0;i<10;i++){ groupdata[i] = "分组"+i; } for(int i=0;i<10;i++){ for(int j=0;j<10;j++){ childrendata[i][j] = "好友"+i+"-"+j; } } //设置悬浮头部view explistview.setheaderview(getlayoutinflater().inflate(r.layout.group_head, explistview, false)); adapter = new pinnedheaderexpandableadapter(childrendata, groupdata, getapplicationcontext(),explistview); explistview.setadapter(adapter); //设置单个分组展开 //explistview.setongroupclicklistener(new groupclicklistener()); } class groupclicklistener implements ongroupclicklistener{ @override public boolean ongroupclick(expandablelistview parent, view v, int groupposition, long id) { if (expandflag == -1) { // 展开被选的group explistview.expandgroup(groupposition); // 设置被选中的group置于顶端 explistview.setselectedgroup(groupposition); expandflag = groupposition; } else if (expandflag == groupposition) { explistview.collapsegroup(expandflag); expandflag = -1; } else { explistview.collapsegroup(expandflag); // 展开被选的group explistview.expandgroup(groupposition); // 设置被选中的group置于顶端 explistview.setselectedgroup(groupposition); expandflag = groupposition; } return true; } } }
布局文件
child.xml
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="40dip" android:background="#ffffff" > <imageview android:id="@+id/groupicon" android:layout_width="40dp" android:layout_height="40dp" android:paddingleft="10dp" android:src="@null" /> <textview android:id="@+id/childto" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingleft="10dp" android:paddingtop="10dip" android:textcolor="#000000" android:textsize="16sp" /> </linearlayout>
group_head.xml
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:background="#b8e6fa" android:gravity="center_vertical"> <imageview android:id="@+id/groupicon" android:layout_width="50dp" android:layout_height="50dp" android:contentdescription="@null" android:layout_marginleft="10dp" android:src="@drawable/btn_browser2"/> <textview android:id="@+id/groupto" android:layout_width="match_parent" android:layout_height="50dp" android:textcolor="#000000" android:textsize="18sp" android:gravity="center_vertical|left"/> </linearlayout>
group.xml
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:background="#b8e6fa" android:gravity="center_vertical"> <imageview android:id="@+id/groupicon" android:layout_width="50dp" android:layout_height="50dp" android:contentdescription="@null" android:layout_marginleft="10dp" android:src="@drawable/btn_browser"/> <textview android:id="@+id/groupto" android:layout_width="match_parent" android:layout_height="50dp" android:textcolor="#000000" android:textsize="18sp" android:gravity="center_vertical|left"/> </linearlayout>
layout_main.xml
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#f0f0f0" android:orientation="vertical" > <com.xiaos.view.pinnedheaderexpandablelistview android:id="@+id/explistview" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginleft="0.0dip" android:cachecolorhint="#00000000" android:choicemode="singlechoice" android:drawselectorontop="false" android:fastscrollenabled="false" android:footerdividersenabled="true" android:groupindicator="@null" android:scrollbars="vertical" android:scrollingcache="true" /> </linearlayout>
androidmanifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xiaos.pinnedheaderexpandable" android:versioncode="1" android:versionname="1.0" > <uses-sdk android:minsdkversion="8" android:targetsdkversion="19" /> <application android:allowbackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/apptheme" > <activity android:name=".mainactivity" android:icon="@drawable/ic_launcher"> <intent-filter> <action android:name="android.intent.action.main"/> <category android:name="android.intent.category.launcher"/> </intent-filter> </activity> </application> </manifest>
两张图片:
下载地址:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。
如对本文有疑问, 点击进行留言回复!!
LongClick原理、上下文菜单原理、EditText长按弹窗原理、WebView长按弹窗自定义、修复WebView全选重复bug ———————————————— 版权声明:本文为CSDN博主「
JobScheduler 实现 特定时间,特定条件(系统空闲,电池电量,磁盘空间 ……)下执行任务
温习Android基础知识——《第一行代码(第三版)》读书笔记 Chapter 10 Service
网友评论