一、问题分析

 

      在上一篇中,我们将头布局加到了ListView上。但是没有隐藏他。你可能会想,隐藏还不简单,直接给它设置为GONE属性不就可以了吗,在需要的时候再设定为可见。没错,这正是ListView实现分页加载时候的做法。但是实现分页加载时,只需要上拉一下,并没有和用户过多的互动。而实现下拉刷新时,一般的做法是,用户在下拉的时候,头布局会慢慢显示,以至于有一种被拉出来的感觉。而分页加载的做法确是只要发现用户下拉,就一下子全部显示出来了。所以这种做法显然不是我们想要的效果。

      那么,我们根据我们想要的效果,就不难想到,我们需要一个方法,一个可以随着用户往下拉的幅度,而让头布局也慢慢跟随显示出来的方法。在这里,采用的方法就是隐藏头布局高度的方法,即即时设置它的paddingTop。这样,刚开始直接设定paddiingTop为高度的负值,就是全部隐藏的效果,然后随着用户下拉,不断传入用户下拉的幅度作为改变paddingTop的依据,这样子头布局就会慢慢被拉出来了。

      思路有了,那么问题来了。第一,要获取头布局自身的高度。第二,要编写这个方法。代码里解释的很清晰了。我们直接看下面的代码吧。对于初学者,这是很大的技巧,应该认真学习。

 

二、实现头布局隐藏

 

      废话不多说,需要注意的东西在代码注释里写的很清楚了。再次编写MyListView类,如下:

 1 package com.fuly.load;
 2 
 3 import android.content.Context;
 4 import android.util.AttributeSet;
 5 import android.view.LayoutInflater;
 6 import android.view.View;
 7 import android.view.ViewGroup;
 8 import android.widget.ListView;
 9 
10 public class MyListView extends ListView{
11     
12     private View header;//头布局
13     
14     private int headerHeight;//头布局自身的高度
15 
16     //三个构造方法都要重写
17     public MyListView(Context context) {
18         super(context);
19         initView( context);
20         
21     }
22     public MyListView(Context context, AttributeSet attrs) {
23         super(context, attrs);
24         initView( context);
25         
26     }
27     public MyListView(Context context, AttributeSet attrs, int defStyle) {
28         super(context, attrs, defStyle);
29         initView( context);
30     
31     }
32     
33     public void initView(Context context){
34         
35         header = LayoutInflater.from(context).inflate(R.layout.header, null);
36         //这里需要注意,在获取高度时必须首先通知父布局header要占多大高和宽。
37         //因为此时父布局还不知道header的尺寸呢,否则你获取的高度只能为0.
38         notifyView(header);
39         headerHeight = header.getMeasuredHeight();//获取header的高度
40 
41         //不能使用header.getHeight。我也不明白为什么不能使用这个方法。
42         //希望有人帮忙解答
43 //        headerHeight = header.getHeight();
44         paddingTop(-headerHeight);
45         //将头布局加进去
46         this.addHeaderView(header);
47     }
48 
49     
50     
51     
52     /**
53      * 该方法为通知父布局,子布局view的宽度和高度
54      * @param view:子布局
55      */
56     private void notifyView(View view){
57         
58         ViewGroup.LayoutParams p = view.getLayoutParams();
59         
60         if(p == null){
61             p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
62             
63         }
64         
65         //spec表示当前子view左右边距,padding表示子view的左右内边距
66         //childDimension:子view的宽度
67         int width = ViewGroup.getChildMeasureSpec(0, 0, p.width);
68         
69         int height;
70         int tempHeight = p.height;
71         if(tempHeight>0){
72             //子布局高度不为空,需要填充这个布局
73             height = MeasureSpec.makeMeasureSpec(tempHeight, MeasureSpec.EXACTLY);
74         }else{
75             //高度为0,则不需要填充
76             height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
77         }
78         
79         //然后告诉父布局,子布局的高度和宽度
80         view.measure(width, height);    
81     }
82     
83     
84     //该方法设定header的paddingTop
85     private void paddingTop(int pt){
86         header.setPadding(header.getPaddingLeft(), pt, header.getPaddingRight(), header.getPaddingBottom());
87         header.invalidate();
88     }
89     
90     
91     
92     
93 }

      我再强调一遍吧。在获得header自身高度的时候,由于渲染header为view的时候并没有通知父布局它有多大。因此在获取之前,需要通知父布局它要占的宽和高。否则取到的高度永远是0.

 

 

 

      好了,运行程序,发现头布局被隐藏了。一个难啃的难题解决了。下一篇文章中,我们就开始实现下拉刷新吧。

posted on 2015-10-10 15:31  fuly  阅读(1583)  评论(0编辑  收藏  举报