samck判断双向好友,显示好友列表
1.ExpandableListView控件的使用
①效果
②相关布局
MainActivity布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:orientation="vertical"> <ExpandableListView android:id="@+id/expandable_list" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
分组布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="40dp"> <TextView android:id="@+id/group_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="水果" android:layout_gravity="center_vertical" android:paddingLeft="30dp"/> </LinearLayout>
子分组布局(分组项目)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="40dp"> <TextView android:id="@+id/group_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="水果" android:layout_gravity="center_vertical" android:paddingLeft="30dp"/> </LinearLayout>
③adapter,继承自BaseExpandableListAdapter
class MyExpandableListAdapter:BaseExpandableListAdapter{ //groups对应java类型String[],表示分组 //items对应java类型String[][],表示分组下的条目 //比如groups和items信息如下: //group=arrayListOf("fruit","vegetables","drink") //items={{"apple","orange","peach","pear"},{"Chinese cabbage","broccoli","tomato"},{"milk","coffee","tear","water")} private var groups=ArrayList<String>() private var items=ArrayList<ArrayList<String>>() constructor(groups:ArrayList<String>,items:ArrayList<ArrayList<String>>,context:Context):super(){ this.groups.addAll(groups) this.items.addAll(items) } override fun getGroup(groupPosition: Int): Any { //返回分组比如:Fruit return groups[groupPosition] } override fun isChildSelectable(groupPosition: Int, childPosition: Int): Boolean { return true //item是否可以被选中点击 } override fun hasStableIds(): Boolean { return true } override fun getGroupView( groupPosition: Int, isExpanded: Boolean, convertView: View?, parent: ViewGroup? ): View { //setTag & getTag @see https://www.cnblogs.com/zgqys1980/p/5110882.html var mConvertView=convertView var groupHolder=GroupHolder() if(mConvertView==null){ mConvertView=LayoutInflater.from(parent!!.context).inflate(R.layout.item_elv_group,parent,false) groupHolder.textView=mConvertView.findViewById<TextView>(R.id.group_name) mConvertView.setTag(groupHolder) }else{ groupHolder= mConvertView.tag as GroupHolder } //设置分组名字 groupHolder.textView?.text=groups[groupPosition] //判断是否为展开状态 if(isExpanded){ //可以设置展开状态的图标之类的 }else{ //可以设置闭合状态的图标 } return mConvertView!! } override fun getChildrenCount(groupPosition: Int): Int { return items[groupPosition].size //具体某个分组里item个数 } override fun getChild(groupPosition: Int, childPosition: Int): Any { return items[groupPosition][childPosition] } override fun getGroupId(groupPosition: Int): Long { return groupPosition.toLong() } override fun getChildView( groupPosition: Int, childPosition: Int, isLastChild: Boolean, convertView: View?, parent: ViewGroup? ): View { //和重写getGroupView类似 var mConvertView=convertView var itemHolder:ItemHolder=ItemHolder() if(mConvertView==null){ mConvertView=LayoutInflater.from(parent!!.context).inflate(R.layout.item_elv_item,parent,false) itemHolder.textView=mConvertView.findViewById(R.id.item_name) mConvertView.tag = itemHolder }else{ itemHolder=mConvertView.tag as ItemHolder } itemHolder.textView?.text=items[groupPosition][childPosition] return mConvertView!! } override fun getChildId(groupPosition: Int, childPosition: Int): Long { return childPosition.toLong() } override fun getGroupCount(): Int { return groups.size //分组个数 } class GroupHolder{ var textView:TextView?=null } class ItemHolder{ var textView:TextView?=null } }
④在MainActivity中初始化数据和为ExpandableListView设置适配器
class MainActivity : AppCompatActivity() { private var groups=ArrayList<String>() private var items=ArrayList<ArrayList<String>>() private var adapter:ExpandableListAdapter?=null init{ this.groups= arrayListOf("fruit","vegetables","drink") this.items.add(arrayListOf("apple","orange","peach","pear")) this.items.add(arrayListOf("Chinese cabbage","broccoli","tomato")) this.items.add(arrayListOf("milk","coffee","tear","water")) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) //var expandable_lv=findViewById<ExpandableListView>(R.id.expandable_list) adapter=MyExpandableListAdapter(groups,items,this) //expandable_lv.setAdapter(adapter) //error:required ListAdapter! //expandable_list.adapter=adapter expandable_list.setAdapter(adapter) } }
⑤关于监听事件
//关闭未选中的分组 expandable_list.setOnGroupExpandListener { for(pos in 0 until groups.size){ if(pos!=it){ expandable_list.collapseGroup(pos) } } } //分组点击监听 expandable_list.setOnGroupClickListener(object:ExpandableListView.OnGroupClickListener{ override fun onGroupClick( parent: ExpandableListView?, v: View?, groupPosition: Int, id: Long ): Boolean { Toast.makeText(this@MainActivity, groups[groupPosition],Toast.LENGTH_SHORT).show() return false } }) //分组子条目点击监听 expandable_list.setOnChildClickListener { parent, v, groupPosition, childPosition, id -> Toast.makeText(this@MainActivity, items[groupPosition][childPosition],Toast.LENGTH_SHORT).show() false }
⑥注意事项
a.在分组布局中,ExpandableListView默认展开显示向上箭头图标,闭合显示向下箭头图标。分组名所在的TextView应该设置paddingLeft属性,从而与默认图标保持一定距离,否则默认图标和分组名会重合
b.kotlin中,为ExpandableListView设置适配器的时候,使用静态方法 .adapter需要传入一个ListAdapter!类型参数;而使用动态方法setAdapter方法,传入一个ExpandableListAdapter类型参数就可以了。这里使用动态方法
2.smack判断双向好友
RosterEntry类型的type.name方法如果为“both”则是双向好友
if(TextUtils.equals("both",friend.type.name)){ // }
3.显示好友列表
可以在RosterManage中定义两个函数
//获得所有分组 fun getAllGroup():Collection<RosterGroup>{ var groups:Collection<RosterGroup> =roster!!.groups return groups } //获得分组好友 fun getGroupFriends(group:RosterGroup):List<RosterEntry>{ if (!roster!!.isLoaded) try { roster!!.reloadAndWait() } catch (e: Exception) { e.printStackTrace() } var friends:List<RosterEntry> =group.entries return friends }
在activity调用这两个函数初始化gourps和items变量,详细的可以参考ExpandableListView的使用
private var conn:XMPPTCPConnection?=null private var rosterManager:RosterManager?=null private var adapter: ExpandableListAdapter?=null private var groups=ArrayList<String>() private var items=ArrayList<ArrayList<String>>() init{ conn=ConnectionManage.smackConnection.getConnection() rosterManager=RosterManager(conn!!) //获得分组和分组好友 var rosterGroups:Collection<RosterGroup> =rosterManager!!.getAllGroup() var itemList=ArrayList<String>() for(group in rosterGroups){ groups.add(group.name) var rosterEntries= rosterManager!!.getGroupFriends(group) for(friend in rosterEntries){ //判断是双向好友~ if(TextUtils.equals("both",friend.type.name)){ itemList.add(friend.name) } } items.add(itemList) } }
运行:
未完成
①传给ExpandableListView的groups不应该是字符串数组(如ArrayList<String>),而应该是对象Group的数组列表,Group可以是自定义的类似于javabean类,用于保存分组的各种信息;
同样items,也应该是类似于ArrayList<ArrayList<Friend>>这样的类型,Friend可以保存好友的头像,签名,用户名,昵称等信息。但是这里省事起见,就用字符串类型只保存其用户名了
②有新好友添加之后,更新数据和控件