Google HeaderGridView中的坑

Android的GridView不能添加HeaderView,谷歌在Galley中已经实现了为GridView添加HeaderView的实现,源码:https://android.googlesource.com/platform/packages/apps/Gallery2/+/idea133/src/com/android/photos/views/HeaderGridView.java

该方案能较完美的解决为GridView添加HeaderView,适用大部分情况,但有种特殊需求不能满足:

问题一:HeaderView需要左,右都顶到父布局,列表项需要有左右边距和horizontalSpacing,这时候如果对HeaderGridView设置paddingLeft和paddingRight会发现HeaderView也有左右边距,未能左右顶到父布局,如果不设置paddingLeft和paddingRight,列表项又有左右边距,很难完美解决HeaderView和itemView对Padding的不同需求。

原因分析:该HeaderGridView是通过新建一个Adapter封装原来的Adapter,在新的Adapter中的getView根据需要,有一个headerView就将headerView添加到一个宽度和gridview同宽的ViewGroup中,然后返回这个ViewGroup作为该行的第一个item项,然后同行的后面位置用空view返回(其实ListView添加HeaderView和footerView也是封装Adapter的方式实现的),也就是说HeaderView还是GridView的item,会受到GridView的padding属性的影响,所以会出现该问题。

解决方案:HeaderGridView不设置padding和horizontalSpacing,满足HeaderView的需求,这是GridView会把item进行等分,在Adapter的初始化中计算每个item的宽度和边距,然后在getView中对item的位置进行判断来设置item的边距和宽度,代码如下:

public MyAdapter extends BaseAdapter {
    
    ViewGroup.LayoutParams ItemLp;// 局部复用的item布局参数
    int padding;// 用以重新计算每个Item项内部的padding全局padding
    int columns;// GridView的列数
    
    public MyAdapter() {
        原初始化逻辑
        initItemWidth();
    }
    
    private void initItemWidth() {
        int parentWidht = mGridView.getMeasureWidth();
        columns = mGridView.getNumColumns();
        padding = mContext.getResources().getDimensionPixelOffset(R.dimen.grid_item_padding);// dimen.xml文件中设置的girdview的左右边距和gridview的水平间距
        int itemWidth = (parentWidht - padding * (colums + 1)) / colums;// 总宽度减去columns + 1份padding进行columns等分
        ItemLp = new ViewGroup.LayoutParams(itemWidth, ViewGroup.LayoutParams.MATCH_PARENT);
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    
        ...原getView处理逻辑
        
        int index = positon % colums;// 计算item在每行的位置
        for (int i = 0; i < colums; i ++) {
            if (i = index) {
                // 通过观察示意图可以得出item的paddingLeft值得表达式,推导过程:
                // 每个item左右padding的总和:itemPading = parentView / columns - itemWidth;
                // 第i个item的paddingRight加下一item的paddingLeft的和为padding;
                // 第一个item的paddingLeft = padding;
                // 根据这些条件推导出第i个item的paddingLeft公式为:padding * (columns - i) / columns
                convertView.setPadding(padding * (columns - i) / columns, 0 , 0, 0);
            }
        }
        viewHolder.layout_item.setLayoutParams(ItemLp);// viewHolder.layout_item为item布局的中添加的第二层布局
        return convertView;
    }

    原Adapter其他处理逻辑
}
最后能实现所需要的展示效果。

问题二:对HeaderGridView设置onItemClickListener列表项点击监听的时候,当有HeaderView的情况下,点击HeaderView以及同行的其他隐藏View的位置,该列表项监听会触发回调。

原因分析:其实和前一个的原因是一样的,HeaderView以及同行的其他隐藏View都是GirdView的item,所以点击都会响应列表项点击监听

解决方案:在onItemClickListener的回调函数onItemCLick(AdapterView view,int position,int id)中加上判断:
if (position < position - id) return;
position是算上headerView以及隐藏View后所有item的真实位置,id是我们所理解的不包含HeaderView的item的序号,所以position - id就是一个常数,等于HeaderView的个数乘以GridView的列数,也就是HeaderView和隐藏View的总个数,当position小于该值时,说明我们点击的是HeaderView或是隐藏View,不处理直接返回

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值