android:clickable=“true”
android:padding=“5dp”
android:src=“@drawable/ic_leftnav_down” />
layout/layout_expand_item.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”
android:background=“@drawable/slidingmenu_item_selector”
android:minHeight=“?android:attr/listPreferredItemHeight” >
<TextView
android:id=“@+id/tv_item_text”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:layout_centerVertical=“true”
android:layout_marginLeft=“75dp”
android:text=“时局”
android:textColor=“@drawable/slidingmenu_item_text_selector”
android:textSize=“15sp”
android:clickable=“true”
/>
<View
android:id=“@+id/item_devider”
android:layout_width=“match_parent”
android:layout_height=“0.5dp”
android:layout_alignParentBottom=“true”
android:layout_marginLeft=“59dp”
android:layout_marginRight=“10dp”
android:background=“@color/listview_divider”
android:visibility=“visible” />
自定义Adapter
- 继承BaseExpandableListAdapter并实现以下方法
- getGroupCount(获取组项的个数)
- getChildrenCount(获取子项个数)
- getGroup(获取组对象)
- getChild(获取子对象)
- getGroupId(获取组项id)
- getChildId(获取子项id)
- hasStableIds(组和子元素是否持有稳定的ID)
- getGroupView(获取显示指定组的视图对象)
- getChildView(获取显示指定项的视图对象)
- isChildSelectable(子项是否可选中)
- 传入组项列表(如:List<GroupItem>
)
- 传入子项列表(如:List<List<Category>>
)
适配器代码:
com.devilwwj.androiddevelopcourse.adapters.ExpandableListViewAdapter
package com.devilwwj.androiddevelopcourse.adapters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.devilwwj.androiddevelopcourse.R;
import com.devilwwj.androiddevelopcourse.domain.Category;
import com.devilwwj.androiddevelopcourse.domain.GroupItem;
import java.util.HashMap;
import java.util.List;
/**
- 自定义可展开列表的适配器
*/
public class ExpandableListViewAdapter extends BaseExpandableListAdapter {
private Context mContext;// 上下文
private ExpandableListView expandableListView; // 可展开列表对象
private List groupList; // 组列表
private List<List> childList; // 子项列表
private LayoutInflater inflater;
// 自定义接口回调监听器
private OnGroupExpandListener OnGroupExpandListener;
private OnGroupClickListener onGroupClickListener;
private OnChildItemClickListener onChildClickListener;
private HashMap<Integer, Boolean> maps = new HashMap<Integer, Boolean>();
private boolean expandStateAtPosition = false;
public OnGroupClickListener getOnGroupClickListener() {
return onGroupClickListener;
}
public void setOnGroupClickListener(
OnGroupClickListener onGroupClickListener) {
this.onGroupClickListener = onGroupClickListener;
}
public OnGroupExpandListener getOnGroupExpandListener() {
return OnGroupExpandListener;
}
public void setOnGroupExpandListener(
OnGroupExpandListener onGroupExpandListener) {
OnGroupExpandListener = onGroupExpandListener;
}
public OnChildItemClickListener getOnChildClickListener() {
return onChildClickListener;
}
public void setOnChildClickListener(
OnChildItemClickListener onChildClickListener) {
this.onChildClickListener = onChildClickListener;
}
private int mExpandedGroupPosition;
public int getExpandedGroupPosition() {
return mExpandedGroupPosition;
}
public void setExpandedGroupPosition(int mExpandedGroupPosition) {
this.mExpandedGroupPosition = mExpandedGroupPosition;
}
public ExpandableListViewAdapter(Context context,
ExpandableListView expandableListView, List groupList,
List<List> childList) {
super();
this.mContext = context;
this.expandableListView = expandableListView;
this.groupList = groupList;
this.childList = childList;
inflater = LayoutInflater.from(context);
// 初始化列表展开状态
for (int i = 0; i < groupList.size(); i++) {
maps.put(i, false);
}
}
private int mGroupPosition = 0;
private int mChildPosition = 0;
/**
-
设置子项被选中方法
-
@param groupPosition
-
@param childPosition
*/
public void setItemChecked(int groupPosition, int childPosition) {
if (expandableListView == null) {
return;
}
this.mGroupPosition = groupPosition;
this.mChildPosition = childPosition;
int numberOfGroupThatIsOpened = 0;
for (int i = 0; i < groupPosition; i++) {
if (expandableListView.isGroupExpanded(i)) {
numberOfGroupThatIsOpened += this.getChildrenCount(i);
}
}
int position = numberOfGroupThatIsOpened + groupPosition
- childPosition + 1;
if (!expandableListView.isItemChecked(position)) {
expandableListView.setItemChecked(position, true);
}
}
@Override
public int getGroupCount() {
return groupList.size();
}
@Override
public int getChildrenCount(int groupPosition) {
return childList.get(groupPosition).size();
}
/*
-
获得组项 (non-Javadoc)
-
@see android.widget.ExpandableListAdapter#getGroup(int)
*/
@Override
public GroupItem getGroup(int groupPosition) {
return groupList.get(groupPosition);
}
@Override
public Category getChild(int groupPosition, int childPosition) {
return childList.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(final int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
final GroupViewHolder groupViewHolder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.layout_expand_group, parent,
false);
groupViewHolder = new GroupViewHolder(convertView);
convertView.setTag(groupViewHolder);
} else {
groupViewHolder = (GroupViewHolder) convertView.getTag();
}
GroupItem groupItem = groupList.get(groupPosition);
groupViewHolder.itemGroupIcon.setBackgroundResource(groupItem
.getDrawableId());
groupViewHolder.itemGroupText.setText(groupItem.getText());
// 如果该组没有子项,则不显示箭头
if (childList.get(groupPosition).size() == 0) {
groupViewHolder.itemArrow.setVisibility(View.GONE);
groupViewHolder.itemGroupLayout
.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onGroupClickListener.onGroupClick(groupPosition);
}
});
} else {
groupViewHolder.itemArrow.setVisibility(View.VISIBLE);
groupViewHolder.itemGroupLayout
.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
OnGroupExpandListener.onGroupExpand(groupPosition);
}
});
}
groupViewHolder.itemGroupText.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onGroupClickListener.onGroupClick(groupPosition);
}
});
groupViewHolder.itemArrow.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
OnGroupExpandListener.onGroupExpand(groupPosition);
}
});
// 判断isExpanded就可以控制按下还是关闭,同时更换图片,这里使用属性动画来控制旋转
if (isExpanded) {
groupViewHolder.itemArrow
.setImageResource(R.drawable.ic_leftnav_up);
// 没有孩子项就不隐藏分割线
if (childList.get(groupPosition).size() > 0) {
groupViewHolder.itemDivider.setVisibility(View.INVISIBLE);
} else {
groupViewHolder.itemDivider.setVisibility(View.VISIBLE);
}
} else {
groupViewHolder.itemArrow
.setImageResource(R.drawable.ic_leftnav_down);
groupViewHolder.itemDivider.setVisibility(View.VISIBLE);
}
return convertView;
}
@Override
public View getChildView(final int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final ChildViewHolder childViewHolder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.layout_expand_item,
parent, false);
childViewHolder = new ChildViewHolder(convertView);
convertView.setTag(childViewHolder);
} else {
childViewHolder = (ChildViewHolder) convertView.getTag();
}
String content = childList.get(groupPosition).get(childPosition)
.getTitle();
// 设置内容
childViewHolder.itemChildText.setText(content);
// 设置文本点击事件
childViewHolder.itemChildText.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onChildClickListener.onChildItemClick(groupPosition,
childPosition);
}
});
if (childPosition == childList.get(groupPosition).size() - 1) {
childViewHolder.itemDivider.setVisibility(View.VISIBLE);
} else {
childViewHolder.itemDivider.setVisibility(View.GONE);
}
// 设置子项被选中的状态
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
// 设置孩子项可选中
return true;
}
private static class GroupViewHolder {
RelativeLayout itemGroupLayout;
ImageView itemGroupIcon;
TextView itemGroupText;
ImageView itemArrow;
View itemDivider;
public GroupViewHolder(View convertView) {
itemGroupLayout = (RelativeLayout) convertView
.findViewById(R.id.group_layout);
itemGroupIcon = (ImageView) convertView
.findViewById(R.id.iv_group_icon);
itemGroupText = (TextView) convertView
.findViewById(R.id.tv_group_text);
itemArrow = (ImageView) convertView.findViewById(R.id.iv_expand);
itemDivider = (View) convertView
.findViewById(R.id.item_group_devider);
}
}
private static class ChildViewHolder {
TextView itemChildText;
View itemDivider;
public ChildViewHolder(View convertView) {
itemChildText = (TextView) convertView
.findViewById(R.id.tv_item_text);
itemDivider = (View) convertView.findViewById(R.id.item_devider);
}
}
public interface OnGroupExpandListener {
void onGroupExpand(int position);
}
public interface OnGroupClickListener {
void onGroupClick(int position);
}
public interface OnChildItemClickListener {
void onChildItemClick(int groupPosition, int childPosition);
}
public boolean getExpandStateAtPosition(int groupPosition) {
// 获得当前位置的展开状态
expandStateAtPosition = maps.get(groupPosition).booleanValue();
return expandStateAtPosition;
}
public void setExpandStateAtPosition(int groupPosition,
boolean expandStateAtPosition) {
this.expandStateAtPosition = expandStateAtPosition;
maps.put(groupPosition, expandStateAtPosition);
}
}
解析一下上面的代码,我们可以看到ExpandableListView除了一个组项,每个组项下面有若干个子项,我们在使用的时候首先要确定要展示的数据结构,组项有groupPosition来标识位置,然而子项需要根据groupPosition和ChildPosition来标识位置,我们设置数据的时候分别在getGroupView和getChildView方法来设置组视图和子项视图数据,最后返回填充数据的视图对象,一些逻辑控制的代码也是在这两个方法中进行,比如控制组项的展开、组项的点击、子项的点击、子项被选中效果等等,这里笔者是自定义了回调接口来满足业务的需求,Android API也提供的类似的方法,大家可以查看官方文档。
Activity代码
com.devilwwj.androiddevelopcourse.activities.ExpandableListViewTestActivity
package com.devilwwj.androiddevelopcourse.activities;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.ExpandableListView;
import com.devilwwj.androiddevelopcourse.R;
import com.devilwwj.androiddevelopcourse.adapters.ExpandableListViewAdapter;
import com.devilwwj.androiddevelopcourse.domain.Category;
import com.devilwwj.androiddevelopcourse.domain.GroupItem;
import com.devilwwj.androiddevelopcourse.utils.ResourceUtil;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
/**
-
A022-列表容器之ExpandableListView
-
@author devilwwj
*/
public class ExpandableListViewTestActivity extends ActionBarActivity implements ExpandableListViewAdapter.OnGroupClickListener, ExpandableListViewAdapter.OnGroupExpandListener
, ExpandableListViewAdapter.OnChildItemClickListener {
private ExpandableListView expandableListView;
private Context mContext;
private ExpandableListViewAdapter expandAdapter;
private List groupList;
private List<List> childList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_expandablelistview);
mContext = ExpandableListViewTestActivity.this;
expandableListView = (ExpandableListView) this.findViewById(R.id.expandablelistview);
expandableListView.setGroupIndicator(null); // 去掉默认指示器
// 设置展开列表数据
setExpandableListView();
}
private void setExpandableListView() {
try {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
最后
今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。
最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司20年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
【算法合集】
【延伸Android必备知识点】
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
5601202)]
[外链图片转存中…(img-c8T0aNSs-1713705601202)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
[外链图片转存中…(img-QUqp38qW-1713705601203)]
最后
今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。
最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司20年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
[外链图片转存中…(img-t3Lu6efr-1713705601204)]
【算法合集】
[外链图片转存中…(img-4mVTmixr-1713705601204)]
【延伸Android必备知识点】
[外链图片转存中…(img-120UQmj5-1713705601205)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!