实现listview展开与隐藏item的思路:
在item布局里面在写一个布局,使用布局方式根据需要来(如果需要展开的item在点击的item上面,就使用相对布局或者帧布局;如果需要展开的item在点击的item下面,就是线性布局的垂直布局)
效果图:
import java.util.ArrayList;
import java.util.HashMap;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity {
private ListView listview;
private Context mContext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
initView();
initData();
}
private void initView() {
listview = (ListView) findViewById(R.id.listview);
}
private void initData() {
ArrayList<HashMap<String, String>> datas = new ArrayList<HashMap<String, String>>();
for (int i = 1; i < 50; i++) {
HashMap<String, String> item = new HashMap<String, String>();
item.put("phone", (i + 10) + "");
item.put("expand", (i + 10) + "'");
datas.add(item);
ListviewExpand adapter = new ListviewExpand(mContext, datas);
listview.setAdapter(adapter);
}
}
private class ListviewExpand extends BaseAdapter {
private Context mContext;
private ArrayList<HashMap<String, String>> list;
private int currentItem = -1; // 用于记录点击的 Item 的 position,是控制 item 展开的核心
public ListviewExpand(Context mContext,
ArrayList<HashMap<String, String>> datas) {
this.mContext = mContext;
this.list = datas;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Viewholder holder;
if (convertView == null) {
holder = new Viewholder();
convertView = LayoutInflater.from(mContext).inflate(
R.layout.item, null);
holder.textview = (TextView) convertView
.findViewById(R.id.textview);
holder.expand = (TextView) convertView
.findViewById(R.id.expand);
convertView.setTag(holder);
} else {
holder = (Viewholder) convertView.getTag();
}
// 注意:我们在此给响应点击事件的区域)添加Tag,为了记录点击的 position,我们正好用 position 设置 Tag
holder.textview.setTag(position);
holder.textview.setText(list.get(position).get("phone"));
holder.expand.setText(list.get(position).get("expand"));
if (currentItem == position) {
holder.expand.setVisibility(View.VISIBLE);
} else {
holder.expand.setVisibility(View.GONE);
}
holder.textview.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
// 用 currentItem 记录点击位置
int tag = (Integer) view.getTag();
if (tag == currentItem) { // 再次点击
currentItem = -1; // 给 currentItem 一个无效值
} else {
currentItem = tag;
}
// 通知adapter数据改变需要重新加载
notifyDataSetChanged(); // 必须有的一步
}
});
return convertView;
}
class Viewholder {
private TextView textview;
private TextView expand;
}
}
}
主界面就是一个listview,就不写了
item布局:
<?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/textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:gravity="center" />
<TextView
android:id="@+id/expand"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_margin="10dp"
android:background="#AAAAAA"
android:gravity="center" />
</LinearLayout>
另外,展开的布局可以有很多,简单的复杂的都可以,现在说一下如果展开的是gridview
即:listview嵌套gridview,这种情况可能会出现展开的gridview高度会有问题
解决方法:实现自定义gridview,重写onMeasure即可
public class MyGridView extends GridView {
public MyGridView(Context context) {
super(context);
}
public MyGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* 设置不滚动
*/
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
若还不行,还可以动态设置gridview高度,根据gridview所有子item的高度来设置gridview高度
/**
* 动态获取gridview高度
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static void setGridViewHeightBasedOnChildren(GridView listView,
int num) {
// 获取listview的adapter
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
return;
}
// 固定列宽,有多少列
int col = num;// listView.getNumColumns();
int totalHeight = 0;
// i每次加4,相当于listAdapter.getCount()小于等于4时 循环一次,计算一次item的高度,
// listAdapter.getCount()小于等于8时计算两次高度相加
for (int i = 0; i < listAdapter.getCount(); i += col) {
// 获取listview的每一个item
View listItem = listAdapter.getView(i, null, listView);
int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(),
MeasureSpec.EXACTLY);
listItem.measure(desiredWidth, 0);
// 获取item的高度和
totalHeight += listItem.getMeasuredHeight();
}
// 获取listview的布局参数
ViewGroup.LayoutParams params = listView.getLayoutParams();
// 设置高度
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
if (num == 3) {
params.height = totalHeight
+ ((listAdapter.getCount() / 3) * 15);
} else {
params.height = totalHeight;
}
return;
} else {
params.height = totalHeight
+ (listView.getVerticalSpacing() * (listAdapter.getCount() / num));
}
// 设置参数
listView.setLayoutParams(params);
}