为ExpandableListView的子项设置自定义图片背景
嘿,这事儿不难,我帮你一步步实现这个带自定义子项背景的ExpandableListView!按照你要的效果,咱们分步骤来:
实现带自定义子项背景的ExpandableListView
1. 先写子项的自定义布局
首先给子项单独创建一个布局文件,比如命名为item_child_custom.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:padding="16dp" android:background="@drawable/child_item_bg" <!-- 这里引用咱们后面要写的背景样式 --> android:layout_marginHorizontal="12dp" android:layout_marginVertical="4dp" android:orientation="vertical"> <!-- 子项的内容控件,这里用TextView举例 --> <TextView android:id="@+id/tv_child_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="子项内容" android:textSize="16sp"/> </LinearLayout>
2. 创建自定义背景的Drawable
在res/drawable目录下新建child_item_bg.xml,实现圆角、选中状态和基础样式,完全匹配你要的效果:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 子项被点击/选中时的状态 --> <item android:state_pressed="true"> <shape android:shape="rectangle"> <solid android:color="#E0E0E0"/> <corners android:radius="8dp"/> </shape> </item> <!-- 正常状态下的样式 --> <item> <shape android:shape="rectangle"> <solid android:color="#FFFFFF"/> <corners android:radius="8dp"/> <!-- 可选:给背景加个浅边框模拟阴影感 --> <stroke android:width="1dp" android:color="#F0F0F0"/> </shape> </item> </selector>
3. 自定义ExpandableListAdapter
接下来要写一个适配器,重点在getChildView方法里加载咱们刚才的自定义子项布局:
public class CustomExpandableListAdapter extends BaseExpandableListAdapter { private Context mContext; private List<String> mGroupList; private Map<String, List<String>> mChildMap; public CustomExpandableListAdapter(Context context, List<String> groupList, Map<String, List<String>> childMap) { this.mContext = context; this.mGroupList = groupList; this.mChildMap = childMap; } @Override public int getGroupCount() { return mGroupList.size(); } @Override public int getChildrenCount(int groupPosition) { return mChildMap.get(mGroupList.get(groupPosition)).size(); } @Override public Object getGroup(int groupPosition) { return mGroupList.get(groupPosition); } @Override public Object getChild(int groupPosition, int childPosition) { return mChildMap.get(mGroupList.get(groupPosition)).get(childPosition); } @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 groupTitle = (String) getGroup(groupPosition); if (convertView == null) { LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(android.R.layout.simple_expandable_list_item_1, parent, false); } TextView tvGroup = convertView.findViewById(android.R.id.text1); tvGroup.setText(groupTitle); tvGroup.setTextSize(18sp); tvGroup.setPadding(16, 16, 16, 16); return convertView; } // 加载自定义子项布局的核心方法 @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { String childContent = (String) getChild(groupPosition, childPosition); if (convertView == null) { LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.item_child_custom, parent, false); } TextView tvChild = convertView.findViewById(R.id.tv_child_content); tvChild.setText(childContent); return convertView; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } }
4. 在页面中初始化并设置适配器
最后在你的Activity或者Fragment里,初始化ExpandableListView并绑定适配器:
public class MainActivity extends AppCompatActivity { private ExpandableListView mExpandableListView; private CustomExpandableListAdapter mAdapter; private List<String> mGroupList; private Map<String, List<String>> mChildMap; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mExpandableListView = findViewById(R.id.expandable_list); // 模拟测试数据,实际项目里换成你的真实数据 initTestData(); // 设置自定义适配器 mAdapter = new CustomExpandableListAdapter(this, mGroupList, mChildMap); mExpandableListView.setAdapter(mAdapter); // 可选:去掉默认的子项指示器,避免和自定义样式冲突 mExpandableListView.setChildIndicator(null); // 可选:去掉默认的分割线,让自定义背景更协调 mExpandableListView.setDividerHeight(0); } private void initTestData() { mGroupList = new ArrayList<>(); mChildMap = new HashMap<>(); mGroupList.add("分组1"); mGroupList.add("分组2"); List<String> childGroup1 = new ArrayList<>(); childGroup1.add("子项1-1"); childGroup1.add("子项1-2"); childGroup1.add("子项1-3"); List<String> childGroup2 = new ArrayList<>(); childGroup2.add("子项2-1"); childGroup2.add("子项2-2"); mChildMap.put(mGroupList.get(0), childGroup1); mChildMap.put(mGroupList.get(1), childGroup2); } }
额外小优化
- 如果想要父项也用自定义背景,直接给父项布局设置类似的背景Drawable就行
- 可以根据需求调整子项布局的
margin值,控制子项之间的间距 - 如果需要子项有更复杂的交互状态,比如长按,可以在适配器里给子项控件添加点击事件监听
内容的提问来源于stack exchange,提问作者Afshin
相关产品推荐
相关产品推荐

