在Android开发中,列表可以说是最常见的了,一般都是使用ListView,当涉及到二维数组时,更多的使用到ExpandableListView,然而当数据结构比较复杂时,就需要使用三级菜单或者更多级的菜单来显示,这就让人比较头疼了,最近做的项目就涉及到了三级菜单,遇到了不少问题,虽然不够完美,但是基本需求实现了,在此记录一下。(之前见过有人使用ListView实现4级、5级甚至更多级菜单的,是在Adapter的数据源里定义的结构,根据等级缩进左间距的倍数,链接地址找不到了,有兴趣的可以自己找找)

先上效果图:

简单介绍下重点,为了简便,把第一层ExpandableListView称之为EListOne,相应的Adapter称之为AdpOne;第二层ExpandableListView称之为EListTwo,相应的Adapter称之为AdpTwo。

首先第一个要处理的问题是在AdpOne的getChildView方法中,需要对EListTwo的高度进行动态计算,因为EListTwo展开和关闭时高度是不一样的,所以要在EListTwo的setOnGroupExpandListener和setOnGroupCollapseListener方法中做相应的处理:

/**

* @author Apathy、恒

*

* 子ExpandableListView展开时,因为group只有一项,所以子ExpandableListView的总高度=

* (子ExpandableListView的child数量 + 1 )* 每一项的高度

* */

eListView.setOnGroupExpandListener(new OnGroupExpandListener() {

@Override

public void onGroupExpand(int groupPosition) {

LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,

(child.getChildNames().size() + 1)* (int) mContext.getResources().getDimension(R.dimen.parent_expandable_list_height));

eListView.setLayoutParams(lp);

}

});

/**

* @author Apathy、恒

*

* 子ExpandableListView关闭时,此时只剩下group这一项,所以子ExpandableListView的总高度即为一项的高度

* */

eListView.setOnGroupCollapseListener(new OnGroupCollapseListener() {

@Override

public void onGroupCollapse(int groupPosition) {

LayoutParams lp = new LayoutParams(

ViewGroup.LayoutParams.MATCH_PARENT, (int) mContext

.getResources().getDimension(

R.dimen.parent_expandable_list_height));

eListView.setLayoutParams(lp);

}

});

只展示菜单肯定不是我们的最终需求,我们一般需要点击菜单后进行相应的界面跳转或者数据处理,所以就需要获取所点击的菜单精确下标,获取方法很简单,只需要定义一个接口,在AdpOne的getChildView方法中回调即可:

/**

* @author Apathy、恒

*

* 点击子ExpandableListView子项时,调用回调接口

* */

eListView.setOnChildClickListener(new OnChildClickListener() {

@Override

public boolean onChildClick(ExpandableListView arg0, View arg1,

int groupIndex, int childIndex, long arg4) {

if (mTreeViewClickListener != null) {

mTreeViewClickListener.onClickPosition(groupPosition,

childPosition, childIndex);

}

return false;

}

});

下面是完整的代码:

MainActivity.java:

package com.heng.tree;

import java.util.ArrayList;

import com.heng.tree.R;

import com.heng.tree.adapter.ParentAdapter;

import com.heng.tree.adapter.ParentAdapter.OnChildTreeViewClickListener;

import com.heng.tree.entity.ChildEntity;

import com.heng.tree.entity.ParentEntity;

import android.app.Activity;

import android.content.Context;

import android.graphics.Color;

import android.os.Bundle;

import android.widget.ExpandableListView;

import android.widget.ExpandableListView.OnGroupExpandListener;

import android.widget.Toast;

/**

*

* @author Apathy、恒

*

*

*

* @email shexiaoheng@163.com

*

* @blog

* http://blog.csdn.net/shexiaoheng

*

*

*

*

* @Detail 本Demo为ExpandableListView嵌套ExpandableListView实现三级菜单的例子

*

* #ParentAdapter.OnChildTreeViewClickListener

*

* */

public class MainActivity extends Activity implements OnGroupExpandListener,

OnChildTreeViewClickListener {

private Context mContext;

private ExpandableListView eList;

private ArrayList parents;

private ParentAdapter adapter;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

mContext = this;

setContentView(R.layout.activity_main);

loadData();

initEList();

}

/**

* @author Apathy、恒

*

* 初始化菜单数据源

* */

private void loadData() {

parents = new ArrayList();

for (int i = 0; i < 10; i++) {

ParentEntity parent = new ParentEntity();

parent.setGroupName("父类父分组第" + i + "项");

parent.setGroupColor(getResources().getColor(

android.R.color.holo_red_light));

ArrayList childs = new ArrayList();

for (int j = 0; j < 8; j++) {

ChildEntity child = new ChildEntity();

child.setGroupName("子类父分组第" + j + "项");

child.setGroupColor(Color.parseColor("#ff00ff"));

ArrayList childNames = new ArrayList();

ArrayList childColors = new ArrayList();

for (int k = 0; k < 5; k++) {

childNames.add("子类第" + k + "项");

childColors.add(Color.parseColor("#ff00ff"));

}

child.setChildNames(childNames);

childs.add(child);

}

parent.setChilds(childs);

parents.add(parent);

}

}

/**

* @author Apathy、恒

*

* 初始化ExpandableListView

* */

private void initEList() {

eList = (ExpandableListView) findViewById(R.id.eList);

eList.setOnGroupExpandListener(this);

adapter = new ParentAdapter(mContext, parents);

eList.setAdapter(adapter);

adapter.setOnChildTreeViewClickListener(this);

}

/**

* @author Apathy、恒

*

* 点击子ExpandableListView的子项时,回调本方法,根据下标获取值来做相应的操作

* */

@Override

public void onClickPosition(int parentPosition, int groupPosition,

int childPosition) {

// do something

String childName = parents.get(parentPosition).getChilds()

.get(groupPosition).getChildNames().get(childPosition)

.toString();

Toast.makeText(

mContext,

"点击的下标为: parentPosition=" + parentPosition

+ " groupPosition=" + groupPosition

+ " childPosition=" + childPosition + "\n点击的是:"

+ childName, Toast.LENGTH_SHORT).show();

}

/**

* @author Apathy、恒

*

* 展开一项,关闭其他项,保证每次只能展开一项

* */

@Override

public void onGroupExpand(int groupPosition) {

for (int i = 0; i < parents.size(); i++) {

if (i != groupPosition) {

eList.collapseGroup(i);

}

}

}

}

ParentAdapter.java

package com.heng.tree.adapter;

import java.util.ArrayList;

import android.content.Context;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseExpandableListAdapter;

import android.widget.ExpandableListView;

import android.widget.ExpandableListView.OnChildClickListener;

import android.widget.ExpandableListView.OnGroupCollapseListener;

import android.widget.ExpandableListView.OnGroupExpandListener;

import android.widget.AbsListView.LayoutParams;

import android.widget.TextView;

import com.heng.tree.R;

import com.heng.tree.entity.ChildEntity;

import com.heng.tree.entity.ParentEntity;

/**

*

* @author Apathy、恒

*

* 父类分组的适配器

*

*

*

*

* 方法 {@link #getChildView(int, int, boolean, View, ViewGroup)}

* color='#ff00ff' size='2'>极其重要

*

* */

public class ParentAdapter extends BaseExpandableListAdapter {

private Context mContext;// 上下文

private ArrayList mParents;// 数据源

private OnChildTreeViewClickListener mTreeViewClickListener;// 点击子ExpandableListView子项的监听

public ParentAdapter(Context context, ArrayList parents) {

this.mContext = context;

this.mParents = parents;

}

@Override

public ChildEntity getChild(int groupPosition, int childPosition) {

return mParents.get(groupPosition).getChilds().get(childPosition);

}

@Override

public long getChildId(int groupPosition, int childPosition) {

return childPosition;

}

@Override

public int getChildrenCount(int groupPosition) {

return mParents.get(groupPosition).getChilds() != null ? mParents

.get(groupPosition).getChilds().size() : 0;

}

@Override

public View getChildView(final int groupPosition, final int childPosition,

boolean isExpanded, View convertView, ViewGroup parent) {

final ExpandableListView eListView = getExpandableListView();

ArrayList childs = new ArrayList();

final ChildEntity child = getChild(groupPosition, childPosition);

childs.add(child);

final ChildAdapter childAdapter = new ChildAdapter(this.mContext,

childs);

eListView.setAdapter(childAdapter);

/**

* @author Apathy、恒

*

* 点击子ExpandableListView子项时,调用回调接口

* */

eListView.setOnChildClickListener(new OnChildClickListener() {

@Override

public boolean onChildClick(ExpandableListView arg0, View arg1,

int groupIndex, int childIndex, long arg4) {

if (mTreeViewClickListener != null) {

mTreeViewClickListener.onClickPosition(groupPosition,

childPosition, childIndex);

}

return false;

}

});

/**

* @author Apathy、恒

*

* 子ExpandableListView展开时,因为group只有一项,所以子ExpandableListView的总高度=

* (子ExpandableListView的child数量 + 1 )* 每一项的高度

* */

eListView.setOnGroupExpandListener(new OnGroupExpandListener() {

@Override

public void onGroupExpand(int groupPosition) {

LayoutParams lp = new LayoutParams(

ViewGroup.LayoutParams.MATCH_PARENT, (child

.getChildNames().size() + 1)

* (int) mContext.getResources().getDimension(

R.dimen.parent_expandable_list_height));

eListView.setLayoutParams(lp);

}

});

/**

* @author Apathy、恒

*

* 子ExpandableListView关闭时,此时只剩下group这一项,

* 所以子ExpandableListView的总高度即为一项的高度

* */

eListView.setOnGroupCollapseListener(new OnGroupCollapseListener() {

@Override

public void onGroupCollapse(int groupPosition) {

LayoutParams lp = new LayoutParams(

ViewGroup.LayoutParams.MATCH_PARENT, (int) mContext

.getResources().getDimension(

R.dimen.parent_expandable_list_height));

eListView.setLayoutParams(lp);

}

});

return eListView;

}

/**

* @author Apathy、恒

*

* 动态创建子ExpandableListView

* */

public ExpandableListView getExpandableListView() {

ExpandableListView mExpandableListView = new ExpandableListView(

mContext);

LayoutParams lp = new LayoutParams(

ViewGroup.LayoutParams.MATCH_PARENT, (int) mContext

.getResources().getDimension(

R.dimen.parent_expandable_list_height));

mExpandableListView.setLayoutParams(lp);

mExpandableListView.setDividerHeight(0);// 取消group项的分割线

mExpandableListView.setChildDivider(null);// 取消child项的分割线

mExpandableListView.setGroupIndicator(null);// 取消展开折叠的指示图标

return mExpandableListView;

}

@Override

public Object getGroup(int groupPosition) {

return mParents.get(groupPosition);

}

@Override

public int getGroupCount() {

return mParents != null ? mParents.size() : 0;

}

@Override

public long getGroupId(int groupPosition) {

return groupPosition;

}

@Override

public View getGroupView(int groupPosition, boolean isExpanded,

View convertView, ViewGroup parent) {

GroupHolder holder = null;

if (convertView == null) {

convertView = LayoutInflater.from(mContext).inflate(

R.layout.parent_group_item, null);

holder = new GroupHolder(convertView);

convertView.setTag(holder);

} else {

holder = (GroupHolder) convertView.getTag();

}

holder.update(mParents.get(groupPosition));

return convertView;

}

/**

* @author Apathy、恒

*

* Holder优化

* */

class GroupHolder {

private TextView parentGroupTV;

public GroupHolder(View v) {

parentGroupTV = (TextView) v.findViewById(R.id.parentGroupTV);

}

public void update(ParentEntity model) {

parentGroupTV.setText(model.getGroupName());

parentGroupTV.setTextColor(model.getGroupColor());

}

}

@Override

public boolean hasStableIds() {

return false;

}

@Override

public boolean isChildSelectable(int groupPosition, int childPosition) {

return false;

}

/**

* @author Apathy、恒

*

* 设置点击子ExpandableListView子项的监听

* */

public void setOnChildTreeViewClickListener(

OnChildTreeViewClickListener treeViewClickListener) {

this.mTreeViewClickListener = treeViewClickListener;

}

/**

* @author Apathy、恒

*

* 点击子ExpandableListView子项的回调接口

* */

public interface OnChildTreeViewClickListener {

void onClickPosition(int parentPosition, int groupPosition,

int childPosition);

}

}

ChildAdapter.java

package com.heng.tree.adapter;

import java.util.ArrayList;

import com.heng.tree.R;

import com.heng.tree.entity.ChildEntity;

import android.content.Context;

import android.graphics.Color;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseExpandableListAdapter;

import android.widget.TextView;

/**

*

* @author Apathy、恒

*

*

*

*

* 子类分组的适配器

*

*

*

*

* 方法{@link #isChildSelectable(int,int)}

* size='2'>必须返回true

*

* */

public class ChildAdapter extends BaseExpandableListAdapter {

private Context mContext;// 上下文

private ArrayList mChilds;// 数据源

public ChildAdapter(Context context, ArrayList childs) {

this.mContext = context;

this.mChilds = childs;

}

@Override

public int getChildrenCount(int groupPosition) {

return mChilds.get(groupPosition).getChildNames() != null ? mChilds

.get(groupPosition).getChildNames().size() : 0;

}

@Override

public String getChild(int groupPosition, int childPosition) {

if (mChilds.get(groupPosition).getChildNames() != null

&& mChilds.get(groupPosition).getChildNames().size() > 0)

return mChilds.get(groupPosition).getChildNames()

.get(childPosition).toString();

return null;

}

@Override

public long getChildId(int groupPosition, int childPosition) {

return childPosition;

}

@Override

public View getChildView(int groupPosition, int childPosition,

boolean isExpanded, View convertView, ViewGroup parent) {

ChildHolder holder = null;

if (convertView == null) {

convertView = LayoutInflater.from(mContext).inflate(

R.layout.child_child_item, null);

holder = new ChildHolder(convertView);

convertView.setTag(holder);

} else {

holder = (ChildHolder) convertView.getTag();

}

holder.update(getChild(groupPosition, childPosition));

return convertView;

}

/**

* @author Apathy、恒

*

* Holder优化

* */

class ChildHolder {

private TextView childChildTV;

public ChildHolder(View v) {

childChildTV = (TextView) v.findViewById(R.id.childChildTV);

}

public void update(String str) {

childChildTV.setText(str);

childChildTV.setTextColor(Color.parseColor("#00ffff"));

}

}

@Override

public Object getGroup(int groupPosition) {

if (mChilds != null && mChilds.size() > 0)

return mChilds.get(groupPosition);

return null;

}

@Override

public int getGroupCount() {

return mChilds != null ? mChilds.size() : 0;

}

@Override

public long getGroupId(int groupPosition) {

return groupPosition;

}

@Override

public View getGroupView(int groupPosition, boolean isExpanded,

View convertView, ViewGroup parent) {

GroupHolder holder = null;

if (convertView == null) {

convertView = LayoutInflater.from(mContext).inflate(

R.layout.child_group_item, null);

holder = new GroupHolder(convertView);

convertView.setTag(holder);

} else {

holder = (GroupHolder) convertView.getTag();

}

holder.update(mChilds.get(groupPosition));

return convertView;

}

/**

* @author Apathy、恒

*

* Holder优化

* */

class GroupHolder {

private TextView childGroupTV;

public GroupHolder(View v) {

childGroupTV = (TextView) v.findViewById(R.id.childGroupTV);

}

public void update(ChildEntity model) {

childGroupTV.setText(model.getGroupName());

childGroupTV.setTextColor(model.getGroupColor());

}

}

@Override

public boolean hasStableIds() {

return false;

}

@Override

public boolean isChildSelectable(int groupPosition, int childPosition) {

/**

* ==============================================

* 此处必须返回true,否则无法响应子项的点击事件===============

* ==============================================

**/

return true;

}

}

CListAdapter.java

package com.heng.tree.adapter;

import java.util.ArrayList;

import com.heng.tree.R;

import com.heng.tree.entity.ChildEntity;

import android.content.Context;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.TextView;

/**

*

* @author Apathy、恒

*

* 子类子类列表的适配器

*

* */

public class CListAdapter extends BaseAdapter {

private Context mContext;

private ArrayList mChilds;

public CListAdapter(Context context, ArrayList childs) {

this.mContext = context;

this.mChilds = childs;

}

@Override

public int getCount() {

return mChilds != null ? mChilds.size() : 0;

}

@Override

public Object getItem(int position) {

if ((getCount() > 0) && (position > 0 && position < mChilds.size())) {

return mChilds.get(position);

}

return null;

}

@Override

public long getItemId(int position) {

return position;

}

@Override

public View getView(int position, View convertView, ViewGroup parent) {

Holder holder = null;

if (convertView == null) {

convertView = LayoutInflater.from(mContext).inflate(

R.layout.child_child_item, null);

holder = new Holder(convertView);

convertView.setTag(holder);

} else {

holder = (Holder) convertView.getTag();

}

holder.update(mChilds.get(position).getGroupName());

return convertView;

}

class Holder {

private TextView tv;

public Holder(View v) {

tv = (TextView) v.findViewById(R.id.childChildTV);

}

public void update(String text) {

tv.setText(text);

}

}

}

ParentEntity.java

package com.heng.tree.entity;

import java.util.ArrayList;

/**

*

* @author Apathy、恒

*

* 子类分组的实体

*

* */

public class ParentEntity {

private int groupColor;

private String groupName;

private ArrayList childs;

/* ==========================================================

* ======================= get method =======================

* ========================================================== */

public int getGroupColor() {

return groupColor;

}

public String getGroupName() {

return groupName;

}

public ArrayList getChilds() {

return childs;

}

/* ==========================================================

* ======================= set method =======================

* ========================================================== */

public void setGroupColor(int groupColor) {

this.groupColor = groupColor;

}

public void setGroupName(String groupName) {

this.groupName = groupName;

}

public void setChilds(ArrayList childs) {

this.childs = childs;

}

}

ChildEntity.java

package com.heng.tree.entity;

import java.util.ArrayList;

/**

*

* @author Apathy、恒

*

* 父类分组的实体

*

* */

public class ChildEntity {

private int groupColor;

private String groupName;

private ArrayList childNames;

/* ==========================================================

* ======================= get method =======================

* ========================================================== */

public int getGroupColor() {

return groupColor;

}

public String getGroupName() {

return groupName;

}

public ArrayList getChildNames() {

return childNames;

}

/* ==========================================================

* ======================= set method =======================

* ========================================================== */

public void setGroupColor(int groupColor) {

this.groupColor = groupColor;

}

public void setGroupName(String groupName) {

this.groupName = groupName;

}

public void setChildNames(ArrayList childNames) {

this.childNames = childNames;

}

}

activity_main.xml

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent" >

android:id="@+id/eList"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:groupIndicator="@null" />

parent_group_item.xml

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:paddingLeft="@dimen/parent_expandable_list_group_padding_left" >

android:id="@+id/parentGroupTV"

android:layout_width="wrap_content"

android:layout_height="@dimen/parent_expandable_list_height"

android:gravity="center_vertical" />

child_group_item.xml

android:layout_width="match_parent"

android:layout_height="wrap_content" >

android:layout_width="match_parent"

android:layout_height="@dimen/parent_expandable_list_height" >

android:id="@+id/childGroupTV"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_centerVertical="true"

android:paddingLeft="@dimen/child_expandable_list_group_padding_left" />

child_child_item.xml

android:layout_width="match_parent"

android:layout_height="wrap_content" >

android:layout_width="match_parent"

android:layout_height="@dimen/parent_expandable_list_height" >

android:id="@+id/childChildTV"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_centerVertical="true"

android:paddingLeft="@dimen/child_expandable_list_child_padding_left" />

dimens.xml

50dp

10dp

40dp

75dp

点此下载demo

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

android 嵌套分组拖动_Android ExpandableListView双层嵌套实现三级树形菜单相关推荐

  1. android 嵌套分组拖动_Android NestedScrolling嵌套滑动机制

    Android NestedScrolling嵌套滑动机制 最近项目要用到官网的下拉刷新SwipeRefreshLayout,它是个容器,包裹各种控件实现下拉,不像以前自己要实现事件的拦截,都是通过对 ...

  2. android 嵌套分组拖动_GitHub - Mosect/DragLayout: Android拖拽控件,支持上下左右滑动、折叠或者嵌套ListView、RecyclerView等...

    DragLayout Android拖拽布局,包括以下布局: DragLayout 基础布局类 FlowLayout 可折叠布局,继承DragLayout DragRefreshLayout 拖拽刷新 ...

  3. Android 多级树形菜单

    在Android里要实现树形菜单,都是用ExpandableList(也有高手自己继承ListView或者LinearLayout来做),但是ExpandableList一般只能实现2级树形菜单... ...

  4. Android提高十七篇之多级树形菜单的实现

    本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处! 在Android里要实现树形菜单,都是用ExpandableList(也有高手自己继承ListView或者Li ...

  5. Android 解决ViewPager双层嵌套的滑动问题

    Android 解决ViewPager双层嵌套的滑动问题 参考文章: (1)Android 解决ViewPager双层嵌套的滑动问题 (2)https://www.cnblogs.com/zhujia ...

  6. 计算机2级公务员考试成绩嵌套,2020广东公务员考试行测:双层嵌套式假言命题等价命题思路点拨...

    假言命题是国考.市考和事业单位的逻辑判断中比较常见考察的一个知识点,我们通常掌握好假言命题的推出关系,根据题干中的关联词准确表达出推理规则,结合原命题和逆否命题的表述选择与题干等价的命题就可以了.那么 ...

  7. HashMap双层嵌套

    HashMap双层嵌套 需求:对于HashMap实现双层嵌套:先存入元素,再遍历元素. /** HashMap嵌套HashMap* * 传播* jc 基础班* 陈1 20* 陈2 22* jy 就业班 ...

  8. 027 Android 可扩展的listview:ExpandableListView的使用案例

    1.ExpandableListView简介 ExpandableListView是一种用于垂直滚动展示两级列表的视图,和 ListView 的不同之处就是它可以展示两级列表,分组可以单独展开显示子选 ...

  9. Android之用 ExpandableListView使用解析(三级列表的实现)

     Android之用 ExpandableListView使用解析(三级列表的实现) 下载地址如下:http://download.csdn.net/download/u011068702/983 ...

最新文章

  1. 三极管hFE参数随着Ic,Vc的变化情况
  2. 如何在另一个JavaScript文件中包含一个JavaScript文件?
  3. 注射“基因剪刀”治疗罕见遗传病,患者28天内无明显不良反应,诺奖得主很激动...
  4. python基础知识整理-python爬虫基础知识点整理
  5. 路由表(FIB)内容的生成(一)
  6. (Abstract Factory)抽象工厂模式的Java实现
  7. 毕设题目:Matlab图像加密
  8. 如何使用Xshell连接linux服务器
  9. 优秀的WMS仓库管理系统应该具备哪些条件
  10. python实现QQ自动发送信息
  11. c语言qq自动回复,QQ自动回复
  12. python运势预测程序_运势.py · Scar/Python-Spider - Gitee.com
  13. 数据分析之Excel
  14. 洛谷 P5594 【XR-4】模拟赛 记录
  15. INSERT INTO和INSERT IGNORE INTO 以及REPLACE INTO的区别
  16. Spring Security总结之如何让认证失败消息自定义在前端页面显示(一)
  17. SSH三大框架笔面试总结
  18. ubuntu 中文 极点五笔 qt
  19. IT人的地摊不就是开源么
  20. 100元的C 软件开发培训班

热门文章

  1. 有趣的23000----整理(07)A词根
  2. 神武授权位置服务器,太古封魔录神武获得,神武服务器入口
  3. 详述Android马甲包
  4. 100个python算法超详细讲解2.1:三色球
  5. 32.【C/C++ 结构体全类型 (详解)】
  6. 【JAVAEE框架】浅谈 Spring 框架的两大核心思想 AOP 与 IOP
  7. python 捕捉键盘操作
  8. 【HDU 5755】Gambler Bo(高斯消元)
  9. 喝酸奶八大误区[zt]
  10. kali安装Netspeed