最近自己编写下拉刷新的时候,发现了一个问题,就是有一个需求是这样的:要求页面中是一个Tab切换界面,一个界面有底部操作栏,不可下拉刷新,另一个界面没有底部操作栏,但可以下拉刷新。

按照平常的做法,我在xml文件中使用了RelativeLayout,声明下拉刷新组件的layout_above为底部操作栏,然后在测试的时候发现一个奇怪的现象:如果一开始设置底部操作栏可见,在另一个运行下拉刷新的界面在下拉的时候就会出现和底部操作栏同样位置,同样大小,但颜色采用系统默认的布局,如果设置为不可见,则不会出现这个问题。

<BottomView
android:id="@+id/bottom"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"/>
<RefreshListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/bottom" />

经过调试,底部操作栏的确是在下拉刷新的时候被设为不可见,所以这个迷之物体并不是底部操作栏。

查了一些资料,虽然并没有找到和我一样的问题,但最大的可能就是在RelativeLayout中,如果layout_above对应的组件被gone掉,有可能产生布局错乱的问题。

既然这样,就换一种写法:声明底部操作栏的layout_bellow为下拉刷新组件。可惜,同样的问题还是会产生。

好吧,既然有可能是因为组件的相对关系产生问题,那么思考是否能够动态的添加对应关系。

Android依然可以提供这种方案,可以通过view.getLayoutParams来获取组件的LayoutParams,然后通过addRule和removeRule方法来动态的添加和删除相对关系。但可惜的是,removeRule和addRule这两个方法并不是成套出售的,removeRule需要更高的API才能支持。

想想,为了考虑兼容性问题,还是放弃这种做法。

结合现象,可能的问题就是下拉刷新需要一个下拉区域,而这个区域在View刚被绘制的时候就已经确定好,如果后面的对应关系被打乱了,可能系统也会产生默认的布局来明确这个区域。

更好的解决方法就出来了:将底部操作栏也作为下拉刷新的区域,也就是和下拉刷新组件一起作为一个布局。

问题是解决了,但我觉得不是很舒服:我的 下拉刷新组件是通用的,只要不启动下拉刷新这个功能,它完全就是一个ListView,并且还可以自由的配置没有数据时候的界面。现在因为一个需求,就加入一个特化的底部操作栏,即使可以控制它的可见性一定程度上还是可以保证它是可用的,但如果我要替换底部操作栏呢?

所以我开始把底部操作栏也可以封装进来。

一开始想到的解决方法就是利用面向对象的继承关系,声明一个基类组件,但实际上,Android的xml文件并不能识别组件的继承关系,不能让子类组件用在基类组件声明的地方。

既然继承行不通,就利用组合。

声明一个类,持有自定义布局底部操作栏的引用,就可以对它进行控制。

public class ContactBottomOperation {
private BaseBottomOperation bottomOperation; ...
}

但要想做到自由替换布局,就必须传入layout的id,然后由该类对布局的渲染进行控制。

 public BaseBottomOperation initBottom(int id) {
bottomOperation.setVisibility(View.VISIBLE);
bottomOperation.init(id);
return bottomOperation;
}
public class BaseBottomOperation{
... public void init(int id) {
LayoutInflater.from(context).inflate(id, this);
}
}

问题是解决了,但还是发现一个不舒服的地方:点击事件呢?

因为我只是持有布局的引用,所以我不能让该类实现onItemClickListener,无法监听点击事件,而自定义的底部操作栏也只有在渲染的时候才知道自己的控件到底是啥。

其实,这个问题根本就不是问题,我完全可以在控制类中获取到底部操作栏的控件,然后设置相应的事件,但无法使用ButterKnife这样的工具来简化代码。

rlSave = (RelativeLayout)bottom.findViewById(R.id.rl_save);
rlSave.setOnItemClickListener(new OnItemClickListener(){
@Override
public void onClick(...){
save();
}
}
}

想到ButterKnife原本就是利用反射的原理,于是我也开始思考反射能否解决我的困扰。

这样就可以解决问题了,我只要传入需要监听的View和调用的方法,就可以完成View和事件的绑定。

bottomOperation.setItemClick(rlFav, this, "favorite");
public void setItemClick(View view, final Object object, final String methodName) {
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Class classObj = object.getClass();
try {
Method method = classObj.getMethod(methodName, null);
method.invoke(object, null);
} catch (NoSuchMethodException e) {
LogUtil.e(e.toString());
} catch (InvocationTargetException e) {
LogUtil.e(e.toString());
} catch (IllegalAccessException e) {
LogUtil.e(e.toString());
}
}
});

实际编码中总会遇到各种奇葩的问题,但问题并不是解决了就完事了,往往问题的解决才是真正的开始。

Android下拉刷新底部操作栏的隐藏问题的更多相关文章

  1. 【原创】窥视懒人的秘密---android下拉刷新开启手势的新纪元

    小飒的成长史原创作品:窥视懒人的秘密---android下拉刷新开启手势的新纪元转载请注明出处 **************************************************** ...

  2. Android 下拉刷新上拉载入 多种应用场景 超级大放送(上)

    转载请标明原文地址:http://blog.csdn.net/yalinfendou/article/details/47707017 关于Android下拉刷新上拉载入,网上的Demo太多太多了,这 ...

  3. 打造通用的Android下拉刷新组件(适用于ListView、GridView等各类View)

    前言 近期在做项目时,使用了一个开源的下拉刷新ListView组件.极其的不稳定,bug还多.稳定的组件又写得太复杂了,jar包较大.在我的一篇博客中也讲述过下拉刷新的实现,即Android打造(Li ...

  4. [转]Android下拉刷新完全解析,教你如何一分钟实现下拉刷新功能

    版权声明:本文出自郭霖的博客,转载必须注明出处. 转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9255575 最近项目中需要用到L ...

  5. Android下拉刷新效果实现

    本文主要包括以下内容 自定义实现pulltorefreshView 使用google官方SwipeRefreshLayout 下拉刷新大致原理 判断当前是否在最上面而且是向下滑的,如果是的话,则加载数 ...

  6. Android 下拉刷新框架实现

    原文地址:http://blog.csdn.net/leehong2005/article/details/12567757 前段时间项目中用到了下拉刷新功能,之前在网上也找到过类似的demo,但这些 ...

  7. Android下拉刷新完全解析,教你如何一分钟实现下拉刷新功能 (转)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/9255575 最 近项目中需要用到ListView下拉刷新的功能,一开始想图省事,在 ...

  8. Android 下拉刷新上拉载入效果功能

    应用场景: 在App开发中,对于信息的获取与演示.不可能所有将其获取与演示,为了在用户使用中,给予用户以友好.方便的用户体验,以滑动.下拉的效果动态载入数据的要求就会出现. 为此.该效果功能就须要应用 ...

  9. Android下拉刷新上拉载入控件,对全部View通用!

    转载请声明出处http://blog.csdn.net/zhongkejingwang/article/details/38868463 前面写过一篇关于下拉刷新控件的博客下拉刷新控件终结者:Pull ...

随机推荐

  1. 【转】Xcode 6制作动态及静态Framework

    http://years.im/Home/Article/detail/id/52.html 创建iOS动态库 新建工程并选择默认Target为Cocoa Touch Framework, 如图: 做 ...

  2. 求n*m网格内矩形的数目

    一个n*m的网格,求这个网格中矩形的数目. 比如以下2*2网格,总共有9个矩形:4个1*1的矩形,4个1*2的矩形,1个2*2的矩形   算法1:动态规划,假设dp[i][j]表示以第 i 行第 j ...

  3. Lotus Domino中使用Xpage技术打造通讯录

    我们来完成一个类似通讯录的功能,我们可以添加人员,查看和修改,删除人员,我们假设我们的通讯录中只记录人员的名字和年龄字段.先看看完成后的效果吧 点击New可以到新增人员页面,如下图: 编辑按钮后进入编 ...

  4. QQ互联开发-01-开发者注册和网站应用申请

    首先需要申请网站应用 要想使用QQ互联,首先需要先注册一个开发者账号,使用QQ号码可以注册,注册后,就可以创建网站应用了: 通过下面地址:https://connect.qq.com/,我们去登录QQ ...

  5. ECSHOP始终显示全部分类方法

    商品分类树需要始终显示所有类别,默认的Ecshop的显示方式为在当前产品页面只显示当前的产品所在的同级及下级分类,这就导致当点开某个产品或者子分 类的时候全局的分类树就不见了. 其实修改的方法很简单. ...

  6. 太阳升起并下落的小动画-SWIFT

    一个小小的动画,太阳公公上山又下山.先上效果图. 用 lipecap 录的gif效果有点卡顿.好吧,说下如何实现的. 首先在一个大圆内先计算出内切九边形各个顶点的位置,接着连接相应的顶点变成一个九角星 ...

  7. sql server命令行

    http://www.cnblogs.com/bingcaihuang/archive/2011/01/31/1948222.html http://www.cnblogs.com/wontonJ/a ...

  8. C用函数指针模拟重载 C++重载

    C中为什么不支持重载,即同一作用域内不允许出现同名函数? 我们都知道重载是c++面向对象的特性.c语言中是不存在的.所谓重载简单来说就是一个函数名可以实现不同的功能,要么输入参数不同或者参数个数不同, ...

  9. Python--类-例子

    class Base: def __init__(self): self.data = [] def add(self, x): self.data.append(x) def addtwice(se ...

  10. android html 与webview属性从冲突

    在最近的项目开发中,使用webview加载html页面,这样可以节省大量页面开发的时间,同时也可加快项目进度. 我们需求是需要显示商品评论,页面设计如下: 调用android代码,对于webview的 ...