最近搞一个项目,需要用到类似于新浪微博的消息流,即每一项有文字、有九宫格图片,因此这就涉及到ListView或者ScrollView嵌套GridView的问题。其中GridView的高度问题在网上都很容易找到答案,即覆写onMeasure方法,然后设置高度的MeasureSpec。但是宽度问题确实没有什么资料,这里所说的宽度问题是比如GridView的列数为3,那么即使只有一张图片,gridview的宽度也是match_parent的,导致用户点击在图片范围外但是在gridview范围内时ListView的点击事件不能捕获。

如图 :

出现的问题截图如上,当只有一个图标时GridView的宽度(灰色区域)也是match_parent的,这个时候点击gridview区域是ListView是不能响应的,但是如果GridView的背景色与ListView的背景一致,用户是看不到GridView的宽度,当用户点击图片以外的区域,可能的操作就是进入到该条消息的详情页,但是由于此时GridView是match_parent的,所以ListView根本不会获取到点击事件,这样的体验很不好。我们需要的效果是这样的 :

即GridView的大小刚好能够包含图片的大小,这样当GridView的背景色为默认时,用户点击图片以外的区域就是点击了ListView的Item。

我们看看如何解决这个问题吧,首先布局方面就不讲了,主要还是讲讲GridView的宽高问题吧。解决GridView的高度问题,需要覆写GridView的onMeasure方法,代码如下 :

public class MGridView extends GridView {

    public boolean hasScrollBar = true;

    /**
* @param context
*/
public MGridView(Context context) {
this(context, null);
} public MGridView(Context context, AttributeSet attrs) {
super(context, attrs, );
} public MGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = heightMeasureSpec;
if (hasScrollBar) {
expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> ,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);// 注意这里,这里的意思是直接测量出GridView的高度
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
} }

在onMeasure方法中,因为hasScrollBase为true, 我们会注意到代码中有注释的分支。这里实际上就是在onMeasure的时候计算出GridView的高度,而不是只计算其中几个View的高度。如果没有这一步,那么GridView的高度将显示不全。将GridView的高度计算出来,这样就不需要上下滑动来显示其它的item了,因为问题所在就是GridView嵌套在了ScrollView或者包含ScrollView的组件中,从而引发的冲突。

下面解决宽度的问题,思路就是在ListView的getView方法中手动计算每个GridView的图片个数,如果图片个数小于GridView每行的列数,则手动计算每个child view所需的宽度,然后GridView的宽度 = child个数 * 每个child view的宽度。为了避免重复计算,我们会缓存计算结果。计算代码如下 :

/**
* @author mrsimple
*/
public final class GridViewUtils {
/**
* 存储宽度
*/
static SparseIntArray mGvWidth = new SparseIntArray(); /**
* 计算GridView的高度
*
* @param gridView 要计算的GridView
*/
public static void updateGridViewLayoutParams(MGridView gridView, int maxColumn) {
int childs = gridView.getAdapter().getCount(); if (childs > ) {
int columns = childs < maxColumn ? childs % maxColumn : maxColumn;
gridView.setNumColumns(columns);
int width = ;
int cacheWidth = mGvWidth.get(columns);
if (cacheWidth != ) {
width = cacheWidth;
} else { // 计算gridview每行的宽度, 如果item小于3则计算所有item的宽度;
// 否则只计算3个child宽度,因此一行最多3个child。 (这里我们以3为例)
int rowCounts = childs < maxColumn ? childs : maxColumn;
for (int i = ; i < rowCounts; i++) {
View childView = gridView.getAdapter().getView(i, null, gridView);
childView.measure(, );
width += childView.getMeasuredWidth();
}
} ViewGroup.LayoutParams params = gridView.getLayoutParams();
params.width = width;
gridView.setLayoutParams(params);
if (mGvWidth.get(columns) == ) {
mGvWidth.append(columns, width);
}
}
}

ListView的getView方法如下 :

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null; if (convertView == null) {
convertView = mInflater.inflate(R.layout.listview_item, parent, false);
viewHolder = new ViewHolder();
viewHolder.mGridView = (MGridView) convertView.findViewById(R.id.my_gridview);
viewHolder.mTextView = (TextView) convertView.findViewById(R.id.my_tv);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
} final ListViewItem item = getItem(position);
// 设置GridView的Adapter
viewHolder.mGridView.setAdapter(new GridViewAdapter(mContext, item.mImages));
// 计算GridView宽度, 设置默认为numColumns为3.
GridViewUtils.updateGridViewLayoutParams(viewHolder.mGridView, );
viewHolder.mTextView.setText(item.mText);
return convertView;
}

这样,我们就解决了消息流的宽高问题。

Android中ListView嵌套GridView的简单消息流UI(解决宽高问题)的更多相关文章

  1. 【Android】listview 嵌套gridview报错,代码:”during second layout pass: posting in next frame

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985, QQ986945193 公众号:程序员小冰 说明:本人曾经在listview嵌套gridview出现 ...

  2. Android中ScrollView嵌套GridView,解决GridView显示不全的问题

    /** * 自定义gridview,解决ScrollView中嵌套gridview显示不正常的问题(1行半) * */ public class MyGridView extends GridView ...

  3. Android中ListView嵌套进ScrollView时高度很小的解决方案

    package com.example.test.util; import android.view.View; import android.view.ViewGroup; import andro ...

  4. android中listview的item滑动删除效果(已解决listview点击问题)

    领导看到iphone上tableview有个滑动删除的效果,要求在android上也实现,搜了下资料,实现起来比较简单,可弄到后面,居然不能点击了,把一篇文章中的代码修改了一下,捣鼓了一番,搞定,下面 ...

  5. android中ListView控件最简单的用法

    创建一个活动,在xml文件中添加一个ListView控件,id定义为list1,并且设置为满屏显示,代码如下: <ListView android:id="@+id/list1&quo ...

  6. Android 中 ListView Adapter getView 被多次调用问题 解决方法

    执行多次原因是因为每显示一个VIew,它都去测量view的高度,执行measure方法,导致getView执行多次. 解决方法是将 ListView 的 layout_width 设置为 fill_p ...

  7. android listView嵌套gridview的使用心得

    在开发的过程中可能需要用到listview嵌套gridview的场景,但是在Android中, 不能在一个拥有Scrollbar的组件中嵌入另一个拥有Scrollbar的组件,因为这不科学,会混淆滑动 ...

  8. ScrollView嵌套ListView嵌套GridView的上下拉以及加载更多

    ScrollView 效果 ScrollView 说明 一个ScrollView 嵌套ListView 嵌套GridView的上拉加载更多,下拉刷新的demo. 主要是重写了GridView和Lsit ...

  9. ListView嵌套GridView

    首先,我们通过两个实例来了解下本篇文章所讲的重点,看下图: 微博: 陌陌: 大家应该对这两款软件并不陌生,接下来,我将列举下本文将要实现的几个点: 1.ListView嵌套GridView,互不冲突, ...

随机推荐

  1. <php>统计目录数和文件数

    $dirn = 0; //目录数 $filen = 0; //文件数 //用来统计一个目录下的文件和目录的个数 function getdirnum($file) { global $dirn; gl ...

  2. Android 按二次后退键退出应用程序

    前言          欢迎大家我分享和推荐好用的代码段~~ 声明          欢迎转载,但请保留文章原始出处:          CSDN:http://www.csdn.net        ...

  3. 信息熵(Entropy)究竟是用来衡量什么的?

    信息熵(Entropy)究竟是用来衡量什么的? ——与Philip ZHANG商榷 思明 Philip ZHANG先生在反驳彭小明的时候,提出一个观点,他说:“ 就语言文 字来说,总体效率不是用民族主 ...

  4. 【计算机视觉】基于行为的ReID演示

    帮老师做了一个简单的基于行为(主要是步态)的ReID问题的Demo,效果例如以下图: 以下是提取的集中特征,前三个都是GEI系的,后几个是基于光流场的.然后右边是识别出的几个对象的排序,由于没有角度和 ...

  5. javascript-Blob文件对象

    一个Blob对象就是一个包含有只读原始数据的类文件对象.Blob对象中的数据并不一定得是JavaScript中的原生形式.File接口基于Blob,继承了Blob的功能,并且扩展支持了用户计算机上的本 ...

  6. 学习okhttp wiki--Connections.

    Connections 尽管你只提供了URL,OkHttp使用三种类型来创建它和你的web服务器的连接:URL,地址(Address)和路由(Route). URLs URLs (例如 https:/ ...

  7. Mac_配置adb环境变量

    1.打开终端Terminal. 2.进入HOME目录:命令行输入 echo(这之间有一个空格) $HOME 3.创建.bash_profile文件:命令行输入 touch(这之间有一个空格).bash ...

  8. ul li a active jquery.cookie.js

    div class="righter nav-navicon" id="admin-nav"> <div class="mainer&qu ...

  9. ubuntu中安装eclipse

    1.下载eclipse安装包 http://mirror.neu.edu.cn/eclipse/technology/epp/downloads/release/kepler/SR2/eclipse- ...

  10. js delete 用法

    1,对象属性删除   function fun(){ this.name = 'mm'; } var obj = new fun(); console.log(obj.name);//mm delet ...