Android自带的控件ExpandableListView实现了分组列表功能,本案例在此基础上进行优化,为此控件添加增删改分组及子项的功能,以及列表数据的持久化。

Demo实现效果:

 

 

Demo下载地址:http://download.csdn.net/detail/ericfantastic/9406745

GroupListDemo具体实现:

①demo中将列表页面设计为Fragment页面,方便后期调用;在主界面MainActivity中动态添加GroupListFragment页面;

MainActivity.java

package com.eric.grouplistdemo;import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
import android.widget.RelativeLayout;public class MainActivity extends Activity {public static GroupListFragment fragment;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);fragment = new GroupListFragment();getFragmentManager().beginTransaction().replace(R.id.fragContainer, fragment).commit();}
}

动态添加GroupListFragment实例到界面的fragContainer布局中;将fragment声明为static用于在Adapter中组添加子项时进行调用。

activity_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:orientation="vertical" ><RelativeLayout android:id="@+id/fragContainer"android:layout_width="match_parent"android:layout_height="match_parent"></RelativeLayout>
</LinearLayout>

②实现自定义适配器类MyAdapter,继承自BaseExpandableListAdapter;组项布局及子项布局;

list_item_parent.xml组项布局文件,展开图标及名称,增删图标;

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="50dp"android:background="#0099ff"android:orientation="horizontal"><ImageViewandroid:id="@+id/image_parent"android:layout_width="50dp"android:layout_height="50dp"android:src="@drawable/image_parent1"/><TextView android:id="@+id/text_parent"android:layout_width="wrap_content"android:layout_height="50dp"android:textColor="#FFF"android:textSize="20sp"android:text="parent1"android:layout_toRightOf="@id/image_parent"android:gravity="center"/><ImageView android:id="@+id/image_delete"android:layout_width="40dp"android:layout_height="40dp"android:layout_centerVertical="true"android:layout_alignParentRight="true"android:src="@drawable/delete"/><ImageView android:id="@+id/image_add"android:layout_width="40dp"android:layout_height="40dp"android:layout_centerVertical="true"android:layout_toLeftOf="@id/image_delete"android:src="@drawable/add"/>
</RelativeLayout>

list_item_child.xml子项布局文件,名称及删除图标;

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="40dp"><TextView android:id="@+id/text_child"android:layout_width="wrap_content"android:layout_height="40dp"android:layout_margin="5dp"android:textColor="#0099ff"android:text="child"android:layout_centerInParent="true"android:gravity="center"/><ImageView android:id="@+id/image_delete"android:layout_width="40dp"android:layout_height="40dp"android:layout_alignParentRight="true"android:layout_centerVertical="true"android:src="@drawable/delete"/>
</RelativeLayout>

MyAdapter.java自定义适配器

package com.eric.grouplistdemo;import java.util.List;
import java.util.Map;import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;/**@author Eric *@2016-1-13下午3:30:43*/
public class MyAdapter extends BaseExpandableListAdapter{private List<String> parentList;private Map<String,List<String>> map;private Context context;private EditText edit_modify;private ModifyDialog dialog;//构造函数public MyAdapter(Context context, List<String> parentList, Map<String,List<String>> map) {this.context = context;this.parentList = parentList;this.map = map;}//获取分组数@Overridepublic int getGroupCount() {return parentList.size();}//获取当前组的子项数@Overridepublic int getChildrenCount(int groupPosition) {String groupName = parentList.get(groupPosition);int childCount = map.get(groupName).size();return childCount;}//获取当前组对象@Overridepublic Object getGroup(int groupPosition) {String groupName = parentList.get(groupPosition);return groupName;}//获取当前子项对象@Overridepublic Object getChild(int groupPosition, int childPosition) {String groupName = parentList.get(groupPosition);String chidlName = map.get(groupName).get(childPosition);return chidlName;}//获取组ID@Overridepublic long getGroupId(int groupPosition) {return groupPosition;}//获取子项ID@Overridepublic long getChildId(int groupPosition, int childPosition) {return childPosition;}@Overridepublic boolean hasStableIds() {return true;}//组视图初始化@Overridepublic View getGroupView(int groupPosition, boolean isExpanded,View convertView, ViewGroup parent) {final int groupPos = groupPosition;if(convertView == null){convertView = LayoutInflater.from(context).inflate(R.layout.list_item_parent, null);}ImageView image = (ImageView) convertView.findViewById(R.id.image_parent);ImageView image_add = (ImageView) convertView.findViewById(R.id.image_add);ImageView image_delete = (ImageView) convertView.findViewById(R.id.image_delete);if(isExpanded){image.setImageResource(R.drawable.image_parent2);}else{image.setImageResource(R.drawable.image_parent1);}image_add.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {alertAddDialog(MainActivity.fragment.getActivity(), "新增子项", groupPos);}});image_delete.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {GroupListFragment.deleteGroup(groupPos);}});TextView parentText = (TextView) convertView.findViewById(R.id.text_parent);parentText.setText(parentList.get(groupPosition));return convertView;}//子项视图初始化@Overridepublic View getChildView(int groupPosition, int childPosition,boolean isLastChild, View convertView, ViewGroup parent) {final int groupPos = groupPosition;final int childPos = childPosition;if(convertView == null){convertView = LayoutInflater.from(context).inflate(R.layout.list_item_child, null);}TextView childText = (TextView) convertView.findViewById(R.id.text_child);ImageView image_delete = (ImageView) convertView.findViewById(R.id.image_delete);String parentName = parentList.get(groupPosition);String childName = map.get(parentName).get(childPosition);childText.setText(childName);image_delete.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {GroupListFragment.deleteChild(groupPos, childPos);}});return convertView;}@Overridepublic boolean isChildSelectable(int groupPosition, int childPosition) {return true;}//弹新增子项对话框public void alertAddDialog(Context context, String title, int currentGroup){final int group = currentGroup;dialog = new ModifyDialog(context, title, null);edit_modify = dialog.getEditText();dialog.setOnClickCommitListener(new OnClickListener() {@Overridepublic void onClick(View v) {GroupListFragment.addChild(group, edit_modify.getText().toString());dialog.dismiss();}});dialog.show();}
}

构造函数:将传入的parentList和map进行数据同步,parentList保存组数据,map保存对应组及其子项list数据;

获取分组数及子项数等很简单,就不介绍了,主要讲述一下,组视图初始化和子项视图初始化这两个函数;

组视图初始化getGroupView():尽量复用convertView防止内存泄露,首先是进行判断,若convertView为空,则进行组视图初始化,加载list_item_parent子项布局;获取到相应的组布局控件:展开图标image、添加图标image_add、删除图标image_delete;通过传递过来的布尔类型参数isExpanded,进行判断给image赋值展开图标或合并图标;分别给添加图标和删除图标添加点击事件,分别调用GroupListFragment中的弹出添加窗口函数alertAddDialog()和删除组函数deleteGroup();

子项视图初始化getChildView():同样尽量复用convertView防止内存泄露,首先是进行判断,若convertView为空,则进行子项视图初始化,加载list_item_child子项布局;获取到相应的子布局控件:内容文本ChildText和删除图标Image_delete;从parentList和map中分别获取到,当前子项的组名parentName和子项名childName,赋值ChildText,删除图标添加点击事件,调用删除子项函数deleteChild();

③实现自定义对话框类ModifyDialog,继承自Dialog类,对输入修改内容,或新增项内容进行过渡;

no_title_dialog.xml,在values目录下自定义Dialog的style类型xml,除去Dialog的标题栏;

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android"><style name="noTitleDialog" parent="android:style/Theme.Dialog"><item name="android:width">300dp</item><item name="android:height">40dp</item><item name="android:windowNoTitle">true</item></style>
</resources>

dialog_modify.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:orientation="vertical" ><TextView android:id="@+id/text_title"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:gravity="center"android:background="#0099ff"android:text="修改名称"android:textColor="#FFF"android:textSize="20sp"/><EditText android:id="@+id/edit_modify"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="组名称"/><Button android:id="@+id/btn_commit"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="确定"android:textColor="#FFF"android:background="#0099ff"/>
</LinearLayout>

ModifyDialog.java

package com.eric.grouplistdemo;import android.app.Dialog;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;/**@author Eric *@2016-1-14下午2:16:39*/
public class ModifyDialog extends Dialog{private TextView text_title;private EditText edit_modify;private Button btn_commit;public ModifyDialog(Context context, String title, String name) {super(context, R.style.noTitleDialog);View view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_modify, null);text_title = (TextView) view.findViewById(R.id.text_title);edit_modify = (EditText)view.findViewById(R.id.edit_modify);btn_commit = (Button) view.findViewById(R.id.btn_commit);text_title.setText(title);edit_modify.setText(name);super.setContentView(view);}public EditText getEditText(){return edit_modify;}public void setOnClickCommitListener(View.OnClickListener listener){btn_commit.setOnClickListener(listener);}
}

ModifyDialog自定义构造函数中,通过super()加载刚刚自定义的no_title_dialog.xml,声明View加载layout布局dialog_modify.xml;并且获取布局中的相应控件,将构造函数中传来的字符串title和name,分别赋值到标题文本和输入框控件中;最后调用setContentView()初始化对话框视图;

添加一个返回输入框控件的函数getEditText(),用于获取输入框输入的内容;

还需要一个自定义的点击事件监听器,绑定在确定按钮上;

④准备工作都完成了,下面就实现GroupListFragment,包括数据的初始化及持久化保存,组项和子项的增删改操作,列表子项点击事件,列表组项和子项的长按事件;

fragment_group_list.xml 页面的布局文件ExpandableListView列表以及一个添加组图标;

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><ExpandableListView android:id="@+id/expandablelistview"android:layout_width="match_parent"android:layout_height="match_parent"android:groupIndicator="@null"></ExpandableListView><ImageView android:id="@+id/image_add"android:layout_width="40dp"android:layout_height="40dp"android:layout_centerHorizontal="true"android:layout_alignParentBottom="true"android:src="@drawable/add"/>
</RelativeLayout>

这里需要将ExpandableListView的groupIndicator属性设置为@null,不使用其自带的展开图标;

GroupListFragment.java 加载列表的页面

package com.eric.grouplistdemo;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;import android.R.integer;
import android.app.Fragment;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.ImageView;
import android.widget.Toast;
/**@author Eric *@2016-1-13上午11:08:07*/
public class GroupListFragment extends Fragment{private View view;private ExpandableListView expandableListView;public static MyAdapter adapter;public static List<String> parentList;public static  Map<String,List<String>> map;private ModifyDialog dialog;private EditText edit_modify;private ImageView image_add;private int currentGroup,currentChild;public static SharedPreferences sp;public static Editor editor;public static String dataMap,dataParentList;@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {view = inflater.inflate(R.layout.fragment_group_list, container, false);expandableListView = (ExpandableListView) view.findViewById(R.id.expandablelistview);image_add = (ImageView) view.findViewById(R.id.image_add);image_add.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {alertAddDialog(getActivity(), "新增组");}});initData();adapter = new MyAdapter(getActivity().getApplicationContext(), parentList, map);expandableListView.setAdapter(adapter);//设置子项点击事件MyOnClickListener myListener = new MyOnClickListener();expandableListView.setOnChildClickListener(myListener);//设置长按点击事件MyOnLongClickListener myLongListener = new MyOnLongClickListener();expandableListView.setOnItemLongClickListener(myLongListener);return view;}public void initData(){map = new HashMap<String, List<String>>();parentList = new ArrayList<String>();sp = getActivity().getApplicationContext().getSharedPreferences("spfile", getActivity().MODE_PRIVATE);dataMap = sp.getString("dataMap", null);dataParentList = sp.getString("dataParentList", null);if(dataMap == null || dataParentList == null){parentList = new ArrayList<String>();parentList.add("客厅");parentList.add("厨房");parentList.add("卧室");List<String> list1 = new ArrayList<String>();list1.add("客厅空调");list1.add("客厅电视");list1.add("客厅电灯");map.put("客厅", list1);List<String> list2 = new ArrayList<String>();list2.add("厨房油烟机");list2.add("厨房电灯");list2.add("厨房电器");map.put("厨房", list2);List<String> list3 = new ArrayList<String>();list3.add("卧室空调");list3.add("卧室灯光");list3.add("卧室电视");map.put("卧室", list3);}else{try {//初始化parentListJSONArray jsonArray = new JSONArray(dataParentList);for (int i = 0; i < jsonArray.length(); i++) {parentList.add(jsonArray.get(i).toString());}//初始化mapJSONObject jsonObject = new JSONObject(dataMap);for (int i = 0; i < jsonObject.length(); i++) {String key = jsonObject.getString(parentList.get(i));JSONArray array = new JSONArray(key);List<String> list = new ArrayList<String>();for (int j = 0; j < array.length(); j++) {list.add(array.get(j).toString());}map.put(parentList.get(i), list);}Log.d("eric", "①:"+map+"②:"+parentList);} catch (JSONException e) {e.printStackTrace();Log.e("eric","String转Map或List出错"+e);}}Log.e("eric", dataMap+"!&&!"+dataParentList);saveData();}//自定义点击监听事件public class MyOnClickListener implements ExpandableListView.OnChildClickListener{@Overridepublic boolean onChildClick(ExpandableListView parent, View v,int groupPosition, int childPosition, long id) {String str = "choose"+groupPosition+"-"+childPosition;Toast.makeText(getActivity(), str, Toast.LENGTH_SHORT).show();return false;}}//自定义长按监听事件public class MyOnLongClickListener implements AdapterView.OnItemLongClickListener{@Overridepublic boolean onItemLongClick(AdapterView<?> parent, View view,int position, long id) {//长按子项if (ExpandableListView.getPackedPositionType(id) == ExpandableListView.PACKED_POSITION_TYPE_CHILD){long packedPos = ((ExpandableListView) parent).getExpandableListPosition(position);int groupPosition = ExpandableListView.getPackedPositionGroup(packedPos);int childPosition = ExpandableListView.getPackedPositionChild(packedPos);currentGroup = groupPosition;currentChild = childPosition;String str = (String)adapter.getChild(groupPosition, childPosition);alertModifyDialog("修改此项名称",str);Toast.makeText(getActivity(),str,Toast.LENGTH_SHORT).show();return true;//长按组}else if(ExpandableListView.getPackedPositionType(id) == ExpandableListView.PACKED_POSITION_TYPE_GROUP){long packedPos = ((ExpandableListView) parent).getExpandableListPosition(position);int groupPosition = ExpandableListView.getPackedPositionGroup(packedPos);int childPosition = ExpandableListView.getPackedPositionChild(packedPos);currentGroup = groupPosition;currentChild = childPosition;String group = parentList.get(groupPosition);alertModifyDialog("修改组名称", group);String str = (String)adapter.getGroup(groupPosition);Toast.makeText(getActivity(),str,Toast.LENGTH_SHORT).show();}return false;}}//新增组public static void addGroup(String newGroupName){parentList.add(newGroupName);List<String> list = new ArrayList<String>();map.put(newGroupName, list);adapter.notifyDataSetChanged();saveData();}//新增子项到指定组public static void addChild(int groupPosition, String newChildName){String groupName = parentList.get(groupPosition);List<String> list = map.get(groupName);list.add(newChildName);adapter.notifyDataSetChanged();saveData();}//删除指定组public static void deleteGroup(int groupPos){String groupName = parentList.get(groupPos);map.remove(groupName);parentList.remove(groupPos);adapter.notifyDataSetChanged();saveData();}//删除指定子项public static void deleteChild(int groupPos, int childPos){String groupName = parentList.get(groupPos);List<String> list = map.get(groupName);list.remove(childPos);adapter.notifyDataSetChanged();saveData();}//修改该项名称public void modifyName(int groupPosition, int childPosition, String modifyName){Toast.makeText(getActivity(), String.valueOf(groupPosition)+'-'+String.valueOf(childPosition), Toast.LENGTH_SHORT).show();if(childPosition<0){//修改组名称String groupName = parentList.get(groupPosition);if(!groupName.equals(modifyName)){map.put(modifyName, map.get(groupName));map.remove(groupName);parentList.set(groupPosition, modifyName);}}else{//修改子项名称String group = parentList.get(groupPosition);List<String> list =map.get(group);list.set(childPosition, modifyName);map.put(group, list);}adapter.notifyDataSetChanged();saveData();}//弹修改对话框public void alertModifyDialog(String title, String name){dialog = new ModifyDialog(getActivity(), title, name);edit_modify = dialog.getEditText();dialog.setOnClickCommitListener(new OnClickListener() {@Overridepublic void onClick(View v) {modifyName(currentGroup, currentChild, edit_modify.getText().toString());dialog.dismiss();}});dialog.show();}//弹新增组对话框public void alertAddDialog(Context context, String title){dialog = new ModifyDialog(context, title, null);edit_modify = dialog.getEditText();dialog.setOnClickCommitListener(new OnClickListener() {@Overridepublic void onClick(View v) {addGroup(edit_modify.getText().toString());dialog.dismiss();}});dialog.show();}//保存数据public static void saveData(){JSONObject jsonObject = new JSONObject(map);dataMap = jsonObject.toString();dataParentList = parentList.toString();editor = sp.edit();editor.putString("dataMap", dataMap);editor.putString("dataParentList", dataParentList);editor.commit();}}

内容有点多,一个个来:

初始化Fragment页面函数onCreateView():

首先,要进行layout布局fragment_group_list.xml加载,获取相应控件的实例,expandableListView列表控件以及添加组图标image_add,添加组图标添加点击事件;调用initData()方法进行组数据parentList和组对应子项map的初始化;然后,实例化adapter传入parentList和map数据到自定义适配器MyAdapter中,并将其绑定到expandableListView上;最后,给expandableListView添加自定义子项点击事件监听器,组项和子项长按事件监听器;

初始化数据函数initData():该函数通过ShareReference来保存数据;

首先,实例化parentList和map,从ShareReference中获取到保存的String类型的parentList和map实际数据,赋值到dataMap和dataParentList中,若当中数据不存在,默认返回null,第一次运行程序的时候肯定是没有数据的,故进行判断,若没获取到数据,那就给parentList和Map赋值“客厅”、“厨房”、“卧室”等一系列数据;如果有数据的话,那就得进行数据的转换,因为之前保存的String类型数据,parentList初始化:将dataParentList转换为JSONArray类型,通过循环将数据赋值到parentList中;同理,将dataMap转换为JSONObject类型,通过两层for循环将数据赋值到map中。

自定义点击子项监听其类MyOnClickListener:实现ExpandableListView.OnChildClickListener接口,这里就简单的进行Toast操作,读者可以修改为跳转等其他自定义功能;

自定义长按组项或子项监听器类MyOnLongClickListener:实现AdapterView.OnItemLongClickListener接口,通过调用ExpandableListView的getPackedPositionType()方法来判断此时长按的是组项还是子项;这里将长按组和子项分离出来,方便根据功能修改;无论是组项还是子项长按后,都调用alertModifyDialog()弹修改对话框,传入当前项的名称;
新增组addGroup函数:将传递过来的newGroupName,添加parentList中,且定义一个空的list,绑定newGroupName,将这对string和list,添加到map中;最后,调用adapter.notifyDataSetChanged()刷新列表,调用saveData()保存数据到ShareReference;

同理,新增子项到指定组addChild(),删除指定组deleteGroup(),删除指定子项deleteChild(),都是对parentList和map进行操作,最后刷新列表和保存数据;

修改该项名称modifyName():通过传递过来childPosition进行判断,当修改项为组项时,childPosition的值为-1,以此区分组项和子项;这里遇到一个问题,当组项提交的名称与原名称相同会报错,故添加一个判断,仅提交的名称不同时才进行修改操作;修改的具体实现还是对parentList和map的操作,以修改组项为例,同新增组,添加一个modifyName的组,其对应的List为原来组名对应的List数据,然后再将原来的groupName组及其对应的list删除,实现修改;最后同样要刷新列表和保存数据;

弹修改对话框alertModifyDialog()函数:首先对自定义的dialog进行实例化,初始化标题和输入框中的数据;调用getEditText()函数获取输入框实例,添加提交按钮点击事件,调用modifyName方法传入当前组和子项数据,以及输入框中提交的文本;
弹新增组对话框alertAddDialog()函数:同样,实例化dialog,获取输入框控件,点击事件中调用addGroup()方法添加数据;

保存数据saveData()函数:将parentList和map数据转化为String类型,分别赋值,保存至ShareReference的Editor中并提交;

Android仿QQ好友列表分组实现增删改及持久化相关推荐

  1. java如何实现qq分组_Android仿QQ好友列表分组实现增删改及持久化

    Android自带的控件ExpandableListView实现了分组列表功能,本案例在此基础上进行优化,为此控件添加增删改分组及子项的功能,以及列表数据的持久化. Demo实现效果: GroupLi ...

  2. android 仿qq好友列表分组效果及联系人分组效果

     历史记录仿QQ好友列表的动态效果 以及联系人的分组效果 QQ朋友分组的功能做的不错,大家都很认可,那么到底他的分组并且滑动的时候,标题能停留在顶部是如何实现的呢?今天从网上搜索了一下资料,自己运行了 ...

  3. android 仿qq好友动态,Android UI仿QQ好友列表分组悬浮效果

    本文实例为大家分享了Android UI仿QQ好友列表分组悬浮效果的具体代码,供大家参考,具体内容如下 楼主是在平板上測试的.图片略微有点大,大家看看效果就好 接下来贴源代码: PinnedHeade ...

  4. 仿QQ好友列表分组折叠效果

    最近要一个类似QQ好友列表分组折叠效果,经过网友提醒应该使用ExpandableListView,因为其就集成了这个功能,我到网上随便找了文章一看,果然如此,因为工作需要和兴趣的推动,下班做完事后决定 ...

  5. Android UI视图效果篇之仿QQ好友列表分组悬浮PinnedHeaderExpandableListView

    楼主是在平板上测试的,图片稍微有点大,大家看看效果就好 接下来贴源码: PinnedHeaderExpandableListView.java 要注意的是 在 onGroupClick方法中paren ...

  6. iOS之仿QQ好友列表展开收缩效果的实现

    使用UICollectionView实现 思路 很明显整体它是一个列表,它的分组是一个列表,它里面的好友列表也是一个列表,所以就可以使用组头来设置分组列表,使用cell设置好友列表: 当点击组头的时候 ...

  7. android 实现QQ好友列表(扩展listview:ExpandableListView)

    在某些android开发群里,看到有些新手问怎么实现QQ好友列表,其实网上一搜挺多的.接触Android,也才一年的时间,大部分时间花在工作上(解bug...),界面上开发很少参与.自己维护的系统应用 ...

  8. android 实现QQ好友列表

    在某些android开发群里,看到有些新手问怎么实现QQ好友列表,其实网上一搜挺多的.接触Android,也才一年的时间,大部分时间花在工作上(解bug...),界面上开发很少参与.自己维护的系统应用 ...

  9. android的实现关注好友功能,android仿微信好友列表功能

    android studio实现微信好友列表功能,注意有一个jar包我没有放上来,请大家到MainActivity中的那个网址里面下载即可,然后把pinyin4j-2.5.0.jar复制粘贴到项目的a ...

最新文章

  1. mybatis mysql方言_MyBatis 方言支持 - Mysql to 华为高斯数据库(gaussdb)
  2. 2021年,作为算法工程师的你们会在CV业务落地上用Transformer吗?
  3. Redis基础知识之—— hset 和hsetnx 的区别
  4. 调试.NET CORE代码
  5. 如果在docker中部署tomcat,并且部署java应用程序
  6. 简书 android底部导航,使用recyclerView封装底部导航栏
  7. 【Elasticsearch】match_phrase搜不出来,怎么办
  8. C语言基础知识之#pragma once
  9. 应对需求变更的软件的设计——我的想法
  10. Top 10 tough core Java interview questions answers programming
  11. 科学计算机算度数,计算器问题科学计算器有分角度制和弧度制,身 – 手机爱问...
  12. 写给Python社群的第1课:初识Python,开篇知识点就选字符串吧~
  13. docker 仓库镜像 替换_Docker如何制作自己镜像并上传dockerhub
  14. CloudComparePCL 点云OOB包围盒
  15. 数字信息时代中国面临两个机遇
  16. 口袋西游背包数组分析
  17. cdh+dolphinscheduler开启kerberos
  18. matlab psk瑞利信道,求救 :Matlab的8psk瑞利信道仿真
  19. Hadoop运行模式
  20. ReactJS 傻瓜教程

热门文章

  1. HashMap 的长度为什么是 2 的幂次方
  2. AIX操作系统vi命令的使用方式
  3. Excel如何对比两表格差异
  4. Vue 源码 思维导图
  5. 知乎高赞:什么能力很重要,但大多数人都没有?
  6. Linux系统下修改mysql数据库密码
  7. 出No core dump will be written. Minidumps are not enabled by default on client versions of Windows
  8. 简单移动平均线(Simple Moving Average,SMA) 定义及使用
  9. c语言标准输入输出ppt,C语言版输入输出.ppt
  10. 超强:Unix道德经(英文版) 1