【Android之微信朋友圈UI实现--ExpandableListView+GridView】大鹏一日同风起,扶摇直上九万里。这篇文章主要讲述Android之微信朋友圈UI实现--ExpandableListView+GridView相关的知识,希望能为你提供帮助。
PS:我们都知道微信,更是知道朋友圈,很多人在朋友圈里卖起了化妆品,打入广告等为自己做一下推广,里面会附带一写好看的图片,上面有标题,有描述,整体布局每场的美观,那么这是怎么实现的呢,有些人可能会单个使用ListView,也会使用GridView,那么listview嵌套gridview你使用过吗,现在先看一张图,
文章图片
这张图是不是很熟悉,没错这个就是朋友圈,里面有一个,里面的布局我都画出来了,我不知道微信具体怎么实现的,但是我们会用安卓原生的方法去实现这样的布局,并有实实在在的数据。
思路:
首页这是一个可以滑动的view,但是分为标题(用户名)和内容,并且内容下面还有图片,图片也是不确定的。这里就用ExpandableListView+GridView,如果有人不了解这个ExpandableListView的话,看完这篇基本用法就会了。
步骤:
- 总布局的创建,里面只要一个ExpandableListView控件。
- ExpandableListView的item布局创建,本布局用最传统的做法分为Group和Child布局。
- Group布局只显示一个用户名
- Child布局就要为描述内容和GridView(存放图片)。
- ExpandableListView适配器创建。
- 数据加载。
文章图片
1: 总布局的创建,里面只要一个ExpandableListView控件。这里文件非常简单,只有一个控件,当然ExpandableListView也是有很多属性的。这里都没有写,去掉箭头,在Activity中动态添加。这里布局文件我都省去了根布局LinearLayout。
< ExpandableListView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/id_elv"/>
2:ExpandableListView的item布局创建,本布局用最传统的做法分为Group和Child布局 2.1:这个就比较多了文件,首先来写一下Group的布局,名字你随便起,我这里叫grouplayout.xml
< ImageView android:id="@+id/id_group_img" android:layout_width="40dp" android:layout_height="40dp" android:src="https://www.songbingjia.com/android/@mipmap/ic_launcher"/> < TextView android:id="@+id/id_group_name" android:layout_width="wrap_content" android:layout_height="40dp" android:gravity="center" android:textSize="40px" android:layout_marginLeft="10dp" android:text="name"/>
2.2:其次是Child的布局,名字也是随便起,我这里叫childlayout.xml
< TextView android:id="@+id/id_dec" android:layout_width="wrap_content" android:layout_height="40dp" android:gravity="center" android:textSize="35px" android:layout_marginLeft="10dp" android:text="describe"/> < GridView android:layout_width="match_parent" android:layout_height="match_parent" android:numColumns="3" android:id="@+id/id_gv"> < /GridView>
2.3:还有一个布局文件,那就是GridView的item布局
< ImageView android:id="@+id/id_img" android:src="https://www.songbingjia.com/android/@mipmap/ic_launcher" android:layout_width="match_parent" android:layout_margin="20dp" android:layout_height="100dp" />
3:ExpandableListView适配器创建适配器的创建才是重点,首先我们对ExpandableListView自定义适配器,然后再在里面嵌套一个GridView的自定义适配器,当然你也可以调用系统的,不过个人觉得自定义有更好的灵活性。在这之前呢,我们需要创建几个bean类,group里有img图片和text文字,child有text文字和img图片数组。因为用户可能会多发几张照片,不光是一个。下面有两个class,稍微看一下就Ok了,不用太在意非要一样。
package mus.cn.shopeffect; /** * Created by cMusketeer on 18/5/23. * * @author 刘志通 */public class GroupBean { String groupImg,name; public String getGroupImg() { return groupImg; }public void setGroupImg(String groupImg) { this.groupImg = groupImg; }public String getName() { return name; }public void setName(String name) { this.name = name; } }
import java.util.List; /** * Created by cMusketeer on 18/5/23. * * @author 刘志通 */public class ChildBean { public String childDesc; public List< String> childImg; public String getChildDesc() { return childDesc; }public void setChildDesc(String childDesc) { this.childDesc = childDesc; }public List< String> getChildImg() { return childImg; }public void setChildImg(List< String> childImg) { this.childImg = childImg; } }
创建Adapter,首先我们要继承adapter,这里和以前的就不一样了,我们要继承BaseExpandableListAdapter,当你继承后,系统就会让你重写里面的方法,方法有很多,不用全部,有如下几个就行了(有的小伙伴系统提示的全部继承,还缺一个)。
3.1:方法作用详情(没有先后顺序,古无序号)
首先定义变量(这里listChild为什么list里泛型还是list,我在Activity中解释)
public Context context; public List< GroupBean> listGroup; public List< List< ChildBean> > listChild;
组Group(父)的长度
@Override public int getGroupCount() { return listGroup.size(); }
某个组中child(子)的长度
@Override public int getChildrenCount(int groupPosition) { return listChild.get(groupPosition).size(); }
拿到父的项
@Override public Object getGroup(int groupPosition) { return listGroup.get(groupPosition); }
拿到组(父)中子的项
@Override public Object getChild(int groupPosition, int childPosition) { return listChild.get(groupPosition).get(childPosition); }
拿到父、子id
@Override public long getGroupId(int groupPosition) { return groupPosition; }@Override public long getChildId(int groupPosition, int childPosition) { return childPosition; }
组和子元素是否持有稳定的ID。
@Override public boolean hasStableIds() { return false; }
返回值:如果当前适配器不包含任何数据则返回True。经常用来决定一个空视图是否应该被显示。
@Override public boolean isEmpty() { return false; }
子项是否可以选中
@Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; }
3.2:补充:这里还有一些方法,你如果是没有用的话,就不用写。
public abstract void onGroupCollapsed (int groupPosition) 当组收缩状态的时候此方法被调用。 参数: groupPosition 收缩状态的组索引 public abstract void onGroupExpanded(int groupPosition) 当组展开状态的时候此方法被调用。
3.3:下面才是重点,分别是getGroupView和getChildView用来显示视图。具体看注释。
图片加载库Glide依赖:compile \'com.github.bumptech.glide:glide:3.7.0\'
@Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { ViewHoldeGroup viewHoldeGroup; if (convertView == null) {//没有视图时创建 convertView = LayoutInflater.from(context).inflate(R.layout.grouplayout, null); //添加布局文件 viewHoldeGroup = new ViewHoldeGroup(); //创建holder对象 viewHoldeGroup.imageView = (ImageView) convertView.findViewById(R.id.id_group_img); //拿到控件 viewHoldeGroup.textView = (TextView) convertView.findViewById(R.id.id_group_name); convertView.setTag(viewHoldeGroup); } else { viewHoldeGroup = (ViewHoldeGroup) convertView.getTag(); }//这里我用的Glide框架,用来加载网络图片的。 Glide.with(context).load(listGroup.get(groupPosition).getGroupImg()).asBitmap().into(viewHoldeGroup.imageView); viewHoldeGroup.textView.setText(listGroup.get(groupPosition).getName()); return convertView; }class ViewHoldeGroup { ImageView imageView; TextView textView; }@Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { ViewHoldeChild viewHoldeChild; GVAdapter gvAdapter; if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.childlayout, null); viewHoldeChild = new ViewHoldeChild(); viewHoldeChild.gridView = (GridView) convertView.findViewById(R.id.id_gv); viewHoldeChild.textView = (TextView) convertView.findViewById(R.id.id_dec); convertView.setTag(viewHoldeChild); } else { viewHoldeChild = (ViewHoldeChild) convertView.getTag(); } viewHoldeChild.textView.setText(listChild.get(groupPosition).get(childPosition).getChildDesc()); gvAdapter = new GVAdapter(context, listChild.get(groupPosition).get(childPosition).getChildImg()); //适配器 viewHoldeChild.gridView.setAdapter(gvAdapter); return convertView; }class ViewHoldeChild { TextView textView; GridView gridView; }
到这里呢我们可以看到Gridview的适配器,写在了ExpandableListView适配器的里面,数据还是一样的传递。GridView的适配器我就不写了,太简单,写上代码量就大了。
4:数据加载 4.1:Activity中最后一步,下面有解释。
//添加组数据 List< GroupBean> listGroup = new ArrayList< > (); GroupBean groupBean; for (int i = 0; i < 10; i++) { groupBean = new GroupBean(); groupBean.setGroupImg("https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1116338067,147640299& fm=27& gp=0.jpg"); groupBean.setName("测试"); listGroup.add(groupBean); } //添加组中子的数据,这里我解释一下list嵌套list,比如说一共是10个组,每个组里有一个子项目,每个子项目中又有2个图片 List< List< ChildBean> > listChild = new ArrayList< > (); List< ChildBean> list; //子的数据 List< String> liImg; //子中图片的数据 ChildBean childBean; for (int i = 0; i < 10; i++) { list = new ArrayList< > (); for (int j = 0; j < 1; j++) { childBean = new ChildBean(); liImg = new ArrayList< > (); for (int k = 0; k < 2; k++) {//图片加载 liImg.add("https://timgsa.baidu.com/timg?image& quality=80& size=b9999_10000& sec=1527344951394& di=6dc7f379165a02c45e8df43106dbb153& imgtype=0& src=https://www.songbingjia.com/android/http%3A%2F%2Fimg.sc115.com%2Fuploads%2Fsc%2Fjpgs%2F1407%2Fapic4833_sc115.com.jpg"); } childBean.setChildImg(liImg); childBean.setChildDesc("我是一个描述,我在图片的上面"); list.add(childBean); //添加到子中 } listChild.add(list); }ExpandableAdapter expandableAdapter = new ExpandableAdapter(this, listGroup, listChild); lv.setAdapter(expandableAdapter); //默认展开 if (expandableAdapter != null) { for (int i = 0; i < listGroup.size(); i++) { lv.expandGroup(i); } } //去除箭头 lv.setGroupIndicator(null);
List< List< ChildBean> > 解释,红色的是组,里面的是子,每个组里不一定有几个子(这里画了两个)。
文章图片
完
推荐阅读
- SpringMVC_Controller注解与RequestMapping
- 双平台真实开发GitHub App React Native技术全面掌握
- Android (checkBox)
- Entity FrameWork和Dapper的使用
- Android 两种方式实现类似水波扩散效果
- AndroidManifest 配置主活动
- android studio 模拟器不能使用的解决方案
- 英语背单词app
- Android_(控件)使用自定义控件在屏幕中绘制一条虚线