每行有多个 child 的 ExpandableListView
ExpandableListView with multiple child in each row
我想达到以下效果:
为此,我使用了 ExpandableListView
,但使用它我设法在每一行中只显示一个 child。其实我想要的是每行显示三个children。
有什么方法可以用 ExpandableListView 实现吗?
如果无法使用 ExpandableListView 那么还有其他解决方案吗?
您似乎想要将 GridView 作为可扩展 ListView 的项目获取。下面的博客 post 看起来很有前途。试一试:
https://nishantsh.blogspot.com/2017/05/android-gridview-as-expandablelistview.html
以下是博客提供的内容post:
- 首先制作一个名为MyCustomGridView.java的自定义gridViewclass,并向其中添加以下代码片段:
public class MyCustomGridView extends GridView {
private final Context mContext;
int mHeight;
public MyCustomGridView(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
}
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int desiredWidth = 100;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int width;
// Measure Width
if (widthMode == MeasureSpec.EXACTLY) {
// Must be this size
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
// Can't be bigger than...
width = Math.min(desiredWidth, widthSize);
} else { // Be whatever you want
width = desiredWidth;
}
// MUST CALL THIS
setMeasuredDimension(width, mHeight);
getGridViewSpanCount(width, mHeight);
}
public void setGridViewItemHeight(int height) {
mHeight = height;
}
}
- 现在创建名为 gridview_item.xml 的布局文件,它将用作 GridView 的项目:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/item_gridView_imgView"
android:layout_width="@dimen/dimen_img_width"
android:layout_height="@dimen/dimen_img_height"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/item_gridView_txtView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:textAlignment="center"
android:textColor="@color/black"
android:textSize="16sp" />
</RelativeLayout>
- 现在创建名为 MyCustomGridViewAdapter.java 的适配器,用于在您的 gridView 中设置视图,如下所示:
public class MyCustomGridViewAdapter extends BaseAdapter {
private Context mContext;
private final ArrayList<YOUR_CLASS_TYPE> arrayList;
public MyCustomGridViewAdapter(Context context, ArrayList<YOUR_CLASS_TYPE> arrayList) {
this.mContext = context;
this.arrayList = arrayList;
}
@Override
public int getCount() {
return arrayList.size();
}
@Override
public YOUR_CLASS_TYPE getItem(int position) {
return arrayList.get(position);
}
@Override
public long getItemId(int arg0) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.gridview_item, parent, false);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.item_gridView_txtView);
holder.imageView = (ImageView) convertView.findViewById(R.id.item_gridView_imgView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText(arrayList.get(position).getName());
// Glide is the library used to laod an image into an imageView
Glide.with(mContext).load(arrayList.get(position).getThumbnail_url())
.asBitmap().centerCrop()
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.into(holder.imageView);
return convertView;
}
private static class ViewHolder {
TextView text;
ImageView imageView;
}
}
- 现在创建一个名为 ExpandableListViewFragment.java 的片段并添加以下代码片段:
public class ExpandableListViewFragment extends Fragment implements GridViewItemClickInterface {
private List<String> listDataHeader;
private HashMap<String, ArrayList<YOUR_CLASS_TYPE>> listDataChild;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.layout_fragment_expandable_listvw, container, false);
ExpandableListView mExpandablelistView = (ExpandableListView) rootView.findViewById(R.id.fragment_expandable_listview);
prepareListData();
CustomExpandableListAdapter mExpandableListAdapter = new CustomExpandableListAdapter(getActivity(), listDataHeader, listDataChild, this);
mExpandablelistView.setAdapter(mExpandableListAdapter);
mExpandablelistView.setOnGroupClickListener(new OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
// This way the expander cannot be collapsed
// on click event of group item
return false;
}
});
return rootView;
}
private void prepareListData() {
listDataHeader = new ArrayList<>();
listDataHeader.add("Folder 1");
listDataHeader.add("Folder 2");
listDataChild = new HashMap<>();
ArrayList<YOUR_CLASS_TYPE> details = new ArrayList<YOUR_CLASS_TYPE>();// fill the data as per your requirements
listDataChild.put(listDataHeader.get(0), details);
listDataChild.put(listDataHeader.get(1), null); // just to show null item view
}
@Override
public void onGridViewItemClick(YOUR_CLASS_TYPE item) {
Toast.makeText(getActivity(), "Currently selected is: " + item.getName(), Toast.LENGTH_SHORT).show();
}
}
- 上述片段的布局文件如下:layout_fragment_expandable_listvw.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:layout_width="match_parent"
android:layout_height="match_parent">
<ExpandableListView
android:id="@+id/fragment_expandable_listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@color/transparent"
android:listSelector="@color/transparent" />
</RelativeLayout>
</LinearLayout>
- 现在使用以下代码片段创建名为 CustomExpandableListAdapter.java 的适配器文件:
public class CustomExpandableListAdapter extends BaseExpandableListAdapter {
private Context mContext;
private List<String> mListDataHeader;
private HashMap<String, ArrayList<YOUR_CLASS_TYPE>> mListDataChild;
private LayoutInflater mInflater;
private GridViewItemClickInterface gridViewItemClickListener;
private int columnsCount = 3;
public CustomExpandableListAdapter(Context context, List<String> listDataHeader, HashMap<String, ArrayList<YOUR_CLASS_TYPE>> listChildData, GridViewItemClickInterface listener) {
this.mContext = context;
this.mListDataHeader = listDataHeader;
this.mListDataChild = listChildData;
this.mInflater = LayoutInflater.from(context);
this.gridViewItemClickListener = listener;
}
@Override
public int getGroupCount() {
return mListDataHeader.size();
}
@Override
public int getChildrenCount(int groupPosition) {
return 1;
}
@Override
public Object getGroup(int groupPosition) {
return mListDataHeader.get(groupPosition);
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return mListDataChild.get(this.mListDataHeader.get(groupPosition))
.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
String headerTitle = (String) getGroup(groupPosition);
if (convertView == null) {
// layout view of header group
convertView = mInflater.inflate(R.layout.expandable_listvw_header, null);
}
TextView headerLabel = (TextView) convertView.findViewById(R.id.txtView_header);
headerLabel.setTypeface(null, Typeface.BOLD);
headerLabel.setText(headerTitle);
return convertView;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
convertView = mInflater.inflate(R.layout.expandable_listvw_item, null);
final ArrayList<YOUR_CLASS_TYPE> items = mListDataChild.get(mListDataHeader.get(groupPosition));
if (items.size() > 0) {
MyCustomGridView gridView = (MyCustomGridView) convertView.findViewById(R.id.item_custom_gridView);
gridView.setNumColumns(columnsCount);
gridView.setVerticalSpacing(10);
gridView.setHorizontalSpacing(10);
MyCustomGridViewAdapter adapter = new MyCustomGridViewAdapter(mContext, items);
gridView.setAdapter(adapter);
int totalHeight = 0;
// This is to get the actual size of gridView at runtime while filling the items into it
for (int size = 0; size < adapter.getCount(); size++) {
RelativeLayout relativeLayout = (RelativeLayout) adapter.getView(size, null, gridView);
relativeLayout.measure(0, 0);
totalHeight += relativeLayout.getMeasuredHeight();
}
gridView.setGridViewItemHeight(v);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
gridViewItemClickListener.onGridViewItemClick(items.get(position));
}
});
} else {
convertView = mInflater.inflate(R.layout.layout_blank, null);
}
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
- ExpandableListView组和item的布局文件如下:
a) expandable_listvw_header.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="vertical">
<TextView
android:id="@+id/txtView_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/colorBlack"
android:textSize="22sp" />
</LinearLayout>
b) expandable_listvw_item.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">
<com.nishant.sample.ExpandableListPac.MyCustomGridView
android:id="@+id/item_custom_gridView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
c) layout_blank.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/item_txt_no_items"
android:layout_width="match_parent"
android:layout_height="80dp"
android:gravity="center_horizontal|center_vertical"
android:text="No items available"
android:textSize="22sp" />
</LinearLayout>
- 界面classGridViewItemClickInterface.java如下:
public interface GridViewItemClickInterface {
void onGridViewItemClick(YOUR_CLASS_TYPE item);
}
我想达到以下效果:
为此,我使用了 ExpandableListView
,但使用它我设法在每一行中只显示一个 child。其实我想要的是每行显示三个children。
有什么方法可以用 ExpandableListView 实现吗? 如果无法使用 ExpandableListView 那么还有其他解决方案吗?
您似乎想要将 GridView 作为可扩展 ListView 的项目获取。下面的博客 post 看起来很有前途。试一试:
https://nishantsh.blogspot.com/2017/05/android-gridview-as-expandablelistview.html
以下是博客提供的内容post:
- 首先制作一个名为MyCustomGridView.java的自定义gridViewclass,并向其中添加以下代码片段:
public class MyCustomGridView extends GridView {
private final Context mContext;
int mHeight;
public MyCustomGridView(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
}
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int desiredWidth = 100;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int width;
// Measure Width
if (widthMode == MeasureSpec.EXACTLY) {
// Must be this size
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
// Can't be bigger than...
width = Math.min(desiredWidth, widthSize);
} else { // Be whatever you want
width = desiredWidth;
}
// MUST CALL THIS
setMeasuredDimension(width, mHeight);
getGridViewSpanCount(width, mHeight);
}
public void setGridViewItemHeight(int height) {
mHeight = height;
}
}
- 现在创建名为 gridview_item.xml 的布局文件,它将用作 GridView 的项目:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/item_gridView_imgView"
android:layout_width="@dimen/dimen_img_width"
android:layout_height="@dimen/dimen_img_height"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/item_gridView_txtView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:textAlignment="center"
android:textColor="@color/black"
android:textSize="16sp" />
</RelativeLayout>
- 现在创建名为 MyCustomGridViewAdapter.java 的适配器,用于在您的 gridView 中设置视图,如下所示:
public class MyCustomGridViewAdapter extends BaseAdapter {
private Context mContext;
private final ArrayList<YOUR_CLASS_TYPE> arrayList;
public MyCustomGridViewAdapter(Context context, ArrayList<YOUR_CLASS_TYPE> arrayList) {
this.mContext = context;
this.arrayList = arrayList;
}
@Override
public int getCount() {
return arrayList.size();
}
@Override
public YOUR_CLASS_TYPE getItem(int position) {
return arrayList.get(position);
}
@Override
public long getItemId(int arg0) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.gridview_item, parent, false);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.item_gridView_txtView);
holder.imageView = (ImageView) convertView.findViewById(R.id.item_gridView_imgView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText(arrayList.get(position).getName());
// Glide is the library used to laod an image into an imageView
Glide.with(mContext).load(arrayList.get(position).getThumbnail_url())
.asBitmap().centerCrop()
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.into(holder.imageView);
return convertView;
}
private static class ViewHolder {
TextView text;
ImageView imageView;
}
}
- 现在创建一个名为 ExpandableListViewFragment.java 的片段并添加以下代码片段:
public class ExpandableListViewFragment extends Fragment implements GridViewItemClickInterface {
private List<String> listDataHeader;
private HashMap<String, ArrayList<YOUR_CLASS_TYPE>> listDataChild;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.layout_fragment_expandable_listvw, container, false);
ExpandableListView mExpandablelistView = (ExpandableListView) rootView.findViewById(R.id.fragment_expandable_listview);
prepareListData();
CustomExpandableListAdapter mExpandableListAdapter = new CustomExpandableListAdapter(getActivity(), listDataHeader, listDataChild, this);
mExpandablelistView.setAdapter(mExpandableListAdapter);
mExpandablelistView.setOnGroupClickListener(new OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
// This way the expander cannot be collapsed
// on click event of group item
return false;
}
});
return rootView;
}
private void prepareListData() {
listDataHeader = new ArrayList<>();
listDataHeader.add("Folder 1");
listDataHeader.add("Folder 2");
listDataChild = new HashMap<>();
ArrayList<YOUR_CLASS_TYPE> details = new ArrayList<YOUR_CLASS_TYPE>();// fill the data as per your requirements
listDataChild.put(listDataHeader.get(0), details);
listDataChild.put(listDataHeader.get(1), null); // just to show null item view
}
@Override
public void onGridViewItemClick(YOUR_CLASS_TYPE item) {
Toast.makeText(getActivity(), "Currently selected is: " + item.getName(), Toast.LENGTH_SHORT).show();
}
}
- 上述片段的布局文件如下:layout_fragment_expandable_listvw.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:layout_width="match_parent"
android:layout_height="match_parent">
<ExpandableListView
android:id="@+id/fragment_expandable_listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@color/transparent"
android:listSelector="@color/transparent" />
</RelativeLayout>
</LinearLayout>
- 现在使用以下代码片段创建名为 CustomExpandableListAdapter.java 的适配器文件:
public class CustomExpandableListAdapter extends BaseExpandableListAdapter {
private Context mContext;
private List<String> mListDataHeader;
private HashMap<String, ArrayList<YOUR_CLASS_TYPE>> mListDataChild;
private LayoutInflater mInflater;
private GridViewItemClickInterface gridViewItemClickListener;
private int columnsCount = 3;
public CustomExpandableListAdapter(Context context, List<String> listDataHeader, HashMap<String, ArrayList<YOUR_CLASS_TYPE>> listChildData, GridViewItemClickInterface listener) {
this.mContext = context;
this.mListDataHeader = listDataHeader;
this.mListDataChild = listChildData;
this.mInflater = LayoutInflater.from(context);
this.gridViewItemClickListener = listener;
}
@Override
public int getGroupCount() {
return mListDataHeader.size();
}
@Override
public int getChildrenCount(int groupPosition) {
return 1;
}
@Override
public Object getGroup(int groupPosition) {
return mListDataHeader.get(groupPosition);
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return mListDataChild.get(this.mListDataHeader.get(groupPosition))
.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
String headerTitle = (String) getGroup(groupPosition);
if (convertView == null) {
// layout view of header group
convertView = mInflater.inflate(R.layout.expandable_listvw_header, null);
}
TextView headerLabel = (TextView) convertView.findViewById(R.id.txtView_header);
headerLabel.setTypeface(null, Typeface.BOLD);
headerLabel.setText(headerTitle);
return convertView;
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
convertView = mInflater.inflate(R.layout.expandable_listvw_item, null);
final ArrayList<YOUR_CLASS_TYPE> items = mListDataChild.get(mListDataHeader.get(groupPosition));
if (items.size() > 0) {
MyCustomGridView gridView = (MyCustomGridView) convertView.findViewById(R.id.item_custom_gridView);
gridView.setNumColumns(columnsCount);
gridView.setVerticalSpacing(10);
gridView.setHorizontalSpacing(10);
MyCustomGridViewAdapter adapter = new MyCustomGridViewAdapter(mContext, items);
gridView.setAdapter(adapter);
int totalHeight = 0;
// This is to get the actual size of gridView at runtime while filling the items into it
for (int size = 0; size < adapter.getCount(); size++) {
RelativeLayout relativeLayout = (RelativeLayout) adapter.getView(size, null, gridView);
relativeLayout.measure(0, 0);
totalHeight += relativeLayout.getMeasuredHeight();
}
gridView.setGridViewItemHeight(v);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
gridViewItemClickListener.onGridViewItemClick(items.get(position));
}
});
} else {
convertView = mInflater.inflate(R.layout.layout_blank, null);
}
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
- ExpandableListView组和item的布局文件如下:
a) expandable_listvw_header.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="vertical">
<TextView
android:id="@+id/txtView_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/colorBlack"
android:textSize="22sp" />
</LinearLayout>
b) expandable_listvw_item.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">
<com.nishant.sample.ExpandableListPac.MyCustomGridView
android:id="@+id/item_custom_gridView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
c) layout_blank.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/item_txt_no_items"
android:layout_width="match_parent"
android:layout_height="80dp"
android:gravity="center_horizontal|center_vertical"
android:text="No items available"
android:textSize="22sp" />
</LinearLayout>
- 界面classGridViewItemClickInterface.java如下:
public interface GridViewItemClickInterface {
void onGridViewItemClick(YOUR_CLASS_TYPE item);
}