(4.2.7.2)Android PullToRefresh 分析之二、UI结构

转载请标明出处: 
http://blog.csdn.net/xuehuayous/article/details/50352000
本文出自:【Kevin.zhou的博客】

前言:接着上一篇《Android PullToRefresh 分析之一、初识PullToRefresh》,这一篇主要分析UI结构,尽可能每一篇只说一点,然后将该点讲解清楚。


一、 问题思考

    

    我们首先把上一篇的一个图拿过来,来分析这三段,如果让我们封装一个刷新加载框架应该怎样写,首先提出几个问题:

    

  • 刷新加载的方向是怎样的,通常的是竖向,万一奇葩的需求提出横向呢?
  • "内容区域"应该显示什么?怎么设置才好扩展?
  • 怎么判断到顶部了,要触发刷新动作?
  • 怎么判断到底部了,要触发加载操作?


OK,来分析下这四个问题:

  • 对于问题一,非常简单,我们可以提供设置方向的配置;
  • 对于问题二,似乎比较棘手,其实也比较好扩展,我们提供一个容器,想放什么布局都可以;
  • 对于问题三、四不同的控件都有判断到顶部和尾部的方法。
这样,只有在基类中将配置的方法抽象出来让不同的实现去处理就好了。

二、UI源码分析

    通过上面问题的思考,就给下面的源码分析做好了铺垫,不要骂我唐僧(太啰嗦了),大牛请无视,只是为了让刚入门的朋友也能理清思路。还是以简单的 PullToRefreshScrollView来分析。
    来看下PullToRefreshScrollView都有哪些方法:
    

比较简单,只是覆盖了父类的四个方法,通过名称可以看出。
  • getPullToRefreshScrollDirection() 为获取刷新加载的方向,是横向还是竖向;
  • createRefreshableView() 为生成刷新加载View,这里生成的是 ScrollView;
  • isReadyForPullStart() 为判断是否促发了刷新操作;
  • isReadyForPullEnd() 为判断是否触发了加载操作;
是不是很眼熟,不错这就是我们提出的四个问题,也就是扩展一个控件只需要实现这四个方法就可以了。但是这几个方法是如何被调用的呢?我们来到它爸爸的类 PullToRefreshBase 瞅瞅。

    

    通过类的继承关系就可以看到继承自LinearLayout,再来看下构造函数:

[java]  view plain  copy
  print ?
  1. // ===========================================================  
  2. // Constructors  
  3. // ===========================================================  
  4.   
  5. public PullToRefreshBase(Context context) {  
  6.     super(context);  
  7.     init(context, null);  
  8. }  
  9.   
  10. public PullToRefreshBase(Context context, AttributeSet attrs) {  
  11.     super(context, attrs);  
  12.     init(context, attrs);  
  13. }  
  14.   
  15. public PullToRefreshBase(Context context, Mode mode) {  
  16.     super(context);  
  17.     mMode = mode;  
  18.     init(context, null);  
  19. }  
  20.   
  21. public PullToRefreshBase(Context context, Mode mode, AnimationStyle animStyle) {  
  22.     super(context);  
  23.     mMode = mode;  
  24.     mLoadingAnimationStyle = animStyle;  
  25.     init(context, null);  
  26. }  
    可以发现,这几个构造函数都不约而同的调用了一个方法, PullToRefreshBase# init(context, attrs);今天的主角就是它了,那它都进行了哪些初始操作呢:

[java]  view plain  copy
  print ?
  1. @SuppressWarnings("deprecation")  
  2. private void init(Context context, AttributeSet attrs) {  
  3.     // ①、获取刷新加载的方向  
  4.     switch (getPullToRefreshScrollDirection()) {  
  5.         case HORIZONTAL:  
  6.             setOrientation(LinearLayout.HORIZONTAL);  
  7.             break;  
  8.         case VERTICAL:  
  9.         default:  
  10.             setOrientation(LinearLayout.VERTICAL);  
  11.             break;  
  12.     }  
  13.     ......  
  14.     // ②、获取配置的刷新加载模式  
  15.     if (a.hasValue(R.styleable.PullToRefresh_ptrMode)) {  
  16.         mMode = Mode.mapIntToValue(a.getInteger(R.styleable.PullToRefresh_ptrMode, 0));  
  17.     }  
  18.     ......  
  19.   
  20.     // ③、初始化刷新加载View  
  21.     mRefreshableView = createRefreshableView(context, attrs);  
  22.     // ④、将刷新加载View添加到布局  
  23.     addRefreshableView(context, mRefreshableView);  
  24.   
  25.     // ⑤、初始"刷新头部"和"加载外部"布局  
  26.     mHeaderLayout = createLoadingLayout(context, Mode.PULL_FROM_START, a);  
  27.     mFooterLayout = createLoadingLayout(context, Mode.PULL_FROM_END, a);  
  28.   
  29.     ......  
  30.   
  31.     // ⑥、根据刷新加载模式更新控件  
  32.     updateUIForMode();  
  33. }  

    省略掉我们暂时不关心的代码,接下来主要分析标注的五段:
    ①、首先就是抽象的getPullToRefreshScrollDirection()来获取刷新加载的方向,该方法在子类中去实现,也是对应我们在思考中提出的问题一;
    ②、获取配置的刷新加载模式,有其中Mode为一个内部的枚举,有DISABLED、PULL_FROM_START、PULL_FROM_END、BOTH、MANUAL_REFRESH_ONLY即不允许刷新加载、从头部刷新、从尾部加载、刷新加载都支持、只允许手动刷新加载,对应的在布局中的配置为
[html]  view plain  copy
  print ?
  1. <!-- Mode of Pull-to-Refresh that should be used -->  
  2. <attr name="ptrMode">  
  3.     <flag name="disabled" value="0x0" />  
  4.     <flag name="pullFromStart" value="0x1" />  
  5.     <flag name="pullFromEnd" value="0x2" />  
  6.     <flag name="both" value="0x3" />  
  7.     <flag name="manualOnly" value="0x4" />  
  8. </attr>  
    ③、createRefreshableView()生成刷新加载View,该方法也是抽象的由子类去实现;
    ④、在生成刷新加载View后调用了addRefreshableView(),通过名称为加载到View结构上,
[java]  view plain  copy
  print ?
  1. private void addRefreshableView(Context context, T refreshableView) {  
  2.     mRefreshableViewWrapper = new FrameLayout(context);  
  3.     mRefreshableViewWrapper.addView(refreshableView, ViewGroup.LayoutParams.MATCH_PARENT,  
  4.             ViewGroup.LayoutParams.MATCH_PARENT);  
  5.   
  6.     addViewInternal(mRefreshableViewWrapper, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,  
  7.             LayoutParams.MATCH_PARENT));  
  8. }  
    把刷新加载View添加到FrameLayout上,然后将该FrameLayout 加载到自身LinearLayout上,可见这个名叫mRefreshableViewWrapper 的FrameLayout就是刷新加载View的父View。前面已经提到过,就是对应的我们在思考中提出的问题二;
    ⑤、初始"刷新头部"和"加载外部"布局,在初始化头部和尾部的时候都是调用的 createLoadingLayout()方法,只是传入的参数不同;
[java]  view plain  copy
 print ?
  1. protected LoadingLayout createLoadingLayout(Context context, Mode mode, TypedArray attrs) {  
  2.     LoadingLayout layout = mLoadingAnimationStyle.createLoadingLayout(context, mode,  
  3.             getPullToRefreshScrollDirection(), attrs);  
  4.     layout.setVisibility(View.INVISIBLE);  
  5.     return layout;  
  6. }  
    发现是调用的 LoadingAnimationStyle类的createLoadingLayout()方法,接着跟进去:
[java]  view plain  copy
 print ?
  1. LoadingLayout createLoadingLayout(Context context, Mode mode, Orientation scrollDirection, TypedArray attrs) {  
  2.     switch (this) {  
  3.         case ROTATE:  
  4.         default:  
  5.             return new RotateLoadingLayout(context, mode, scrollDirection, attrs);  
  6.         case FLIP:  
  7.             return new FlipLoadingLayout(context, mode, scrollDirection, attrs);  
  8.     }  
  9. }  
是根据刷新加载样式不同来生成布局,可以看到默认提供了两种样式,一个是这样的 ,另一个是这样的
    ⑥、 最后调用了 updateUIForMode(),即根据刷新加载的模式来更新UI:
[java]  view plain  copy
 print ?
  1. protected void updateUIForMode() {  
  2.     // We need to use the correct LayoutParam values, based on scroll  
  3.     // direction  
  4.     final LinearLayout.LayoutParams lp = getLoadingLayoutLayoutParams();  
  5.   
  6.     ......  
  7.   
  8.     if (mMode.showHeaderLoadingLayout()) {  
  9.         addViewInternal(mHeaderLayout, 0, lp);  
  10.     }  
  11.   
  12.     ......  
  13.   
  14.     if (mMode.showFooterLoadingLayout()) {  
  15.         addViewInternal(mFooterLayout, lp);  
  16.     }  
  17.   
  18.     // Hide Loading Views  
  19.     refreshLoadingViewsSize();  
  20.   
  21.     ......  
  22. }  
    在这里把头部和尾部 加载到自身LinearLayout上,并隐藏头部和尾部。

    至此,怎么生成"刷新头部"、"加载尾部"及"内容区域"并将它们都加载到自身的LinearLayout上就清楚了。

三、结语


    在该篇中,我们只是搞清楚了一个问题,就是"刷新头部"、"内容部分"、"加载尾部"是如何初始化及加载到布局上,下篇《Android PullToRefresh 分析之三、手势响应》中将主要分析是如何响应手指滑动事件的。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
自动控制节水灌溉技术的高低代表着农业现代化的发展状况,灌溉系统自动化水平较低是制约我国高效农业发展的主要原因。本文就此问题研究了单片机控制的滴灌节水灌溉系统,该系统可对不同土壤的湿度进行监控,并按照作物对土壤湿度的要求进行适时、适量灌水,其核心是单片机和PC机构成的控制部分,主要对土壤湿度与灌水量之间的关系、灌溉控制技术及设备系统的硬件、软件编程各个部分进行了深入的研究。 单片机控制部分采用上下位机的形式。下位机硬件部分选用AT89C51单片机为核心,主要由土壤湿度传感器,信号处理电路,显示电路,输出控制电路,故障报警电路等组成,软件选用汇编语言编程。上位机选用586型以上PC机,通过MAX232芯片实现同下位机的电平转换功能,上下位机之间通过串行通信方式进行数据的双向传输,软件选用VB高级编程语言以建立友好的人机界面。系统主要具有以下功能:可在PC机提供的人机对话界面上设置作物要求的土壤湿度相关参数;单片机可将土壤湿度传感器检测到的土壤湿度模拟量转换成数字量,显示于LED显示器上,同时单片机可采用串行通信方式将此湿度值传输到PC机上;PC机通过其内设程序计算出所需的灌水量和灌水时间,且显示于界面上,并将有关的灌水信息反馈给单片机,若需灌水,则单片机系统启动鸣音报警,发出灌水信号,并经放大驱动设备,开启电磁阀进行倒计时定时灌水,若不需灌水,即PC机上显示的灌水量和灌水时间均为0,系统不进行灌水。
智慧农业是一种结合了现代信息技术,包括物联网、大数据、云计算等,对农业生产过程进行智能化管理和监控的新模式。它通过各种传感器和设备采集农业生产中的关键数据,如大气、土壤和水质参数,以及生物生长状态等,实现远程诊断和精准调控。智慧农业的核心价值在于提高农业生产效率,保障食品安全,实现资源的可持续利用,并为农业产业的转型升级提供支持。 智慧农业的实现依赖于多个子系统,包括但不限于设施蔬菜精细化种植管理系统、农业技术资料库、数据采集系统、防伪防串货系统、食品安全与质量追溯系统、应急追溯系统、灾情疫情防控系统、农业工作管理系统、远程诊断系统、监控中心、环境监测系统、智能环境控制系统等。这些系统共同构成了一个综合的信息管理和服务平台,使得农业生产者能够基于数据做出更加科学的决策。 数据采集是智慧农业的基础。通过手工录入、传感器自动采集、移动端录入、条码/RFID扫描录入、拍照录入以及GPS和遥感技术等多种方式,智慧农业系统能够全面收集农业生产过程中的各种数据。这些数据不仅包括环境参数,还涵盖了生长状态、加工保存、检验检疫等环节,为农业生产提供了全面的数据支持。 智慧农业的应用前景广阔,它不仅能够提升农业生产的管理水平,还能够通过各种应用系统,如库房管理、无公害监控、物资管理、成本控制等,为农业生产者提供全面的服务。此外,智慧农业还能够支持政府监管,通过发病报告、投入品报告、死亡报告等,加强农业产品的安全管理和质量控制。 面对智慧农业的建设和发展,存在一些挑战,如投资成本高、生产过程标准化难度大、数据采集和监测的技术难题等。为了克服这些挑战,需要政府、企业和相关机构的共同努力,通过政策支持、技术创新和教育培训等手段,推动智慧农业的健康发展。智慧农业的建设需要明确建设目的,选择合适的系统模块,并制定合理的设备布署方案,以实现农业生产的智能化、精准化和高效化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值