自定义ListView 加head 下拉刷新



 /* 问题:
         初始的时候head布局是不显示的 如果直接隐藏下拉的动画效果是出不来的
       (显示的时候会出现下拉动画显示而 如果直接隐藏再显示 会直接显示出来没有效果的呢)
          解决思路:吧顶部布局的上边距设置为布局View的高度的负值 看到的也是隐藏的效果*/


package com.example.administrator.listviewrefreshfunc;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;

/**
 * Created by Administrator on 2017/11/29.
 */

public class RefreshListView extends ListView {

    private View mView;
    private int headHeight;

    public RefreshListView(Context context) {
        super(context);
        initHeadView(context);
    }

    public RefreshListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initHeadView(context);
    }

    public RefreshListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initHeadView(context);
    }

    /*
    初始化ListView的顶部控件
    */
    public void initHeadView(Context context) {
        mView = View.inflate(context, R.layout.lvlist_head_layout, null);
        MeasureView(mView);
        /* 测量方法不执行时
        此方法获得控件的高度  此时是娶不到高度的 因为没有提前通知父布局 我到底占多大地方*/
        headHeight = mView.getMeasuredHeight();
        Log.i("", "测量高度 "+ headHeight);
        TopPadding(- headHeight);
        this.addHeaderView(mView);
        /* 问题:
         初始的时候head布局是不显示的 如果直接隐藏下拉的动画效果是出不来的
       (显示的时候会出现下拉动画显示而 如果直接隐藏再显示 会直接显示出来没有效果的呢)
          解决思路:吧顶部布局的上边距设置为布局View的高度的负值 看到的也是隐藏的效果*/
    }

    /* mView设置布局上边距
    *
    * */
    public void TopPadding(int topPadding) {
     mView.setPadding(mView.getPaddingLeft(),topPadding,mView.getRight(),mView.getBottom());
     mView.invalidate();
    }
    public void MeasureView(View view){
        ViewGroup.LayoutParams p = view.getLayoutParams();
        if (p==null){
            p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
        }

        /* 通知父布局占用的宽高
        *
        * */
        /* space :mview的左右边距 padding 内边距 布局的宽度*/
        int width = ViewGroup.getChildMeasureSpec(0,0,p.width);
        int height ;
        int tempHeight = p.height;
        if (tempHeight>0){
            //高度不为0 填充
            height=MeasureSpec.makeMeasureSpec(tempHeight,MeasureSpec.EXACTLY);
        }else{
            height=MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED );
        }
        view.measure(width,height);
    }
}

1 view的 setPadding();方法的延伸理解

View的getWidth和getPaddingLeft()指的是什么意思

是查看的得到宽度和得到左边距
可以理解为,实际的绘图区域在距离他左边 paddingleft 远的位置开始算,比如一个view 他的左上坐标是0,0,正常你放个viewchild上去,如果不指定坐标,就是放在了0,0点,如果设置了paddingleft是20,那么viewchild就会放在20,0的位置,左边就会出现20像素单位的空区域
(结合上面的隐藏布局view理解)

2 View的invalidate()方法

3 给控件指明父布局  及在父布局的占位
  ViewGroup.LayoutParams p = view.getLayoutParams();
        if (p==null){
            //指定宽高 宽铺满屏幕 高度包裹内容 需要测量才知道确切的值
            p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);

        }
由于宽度固定 可测出宽:
 int width = ViewGroup.getChildMeasureSpec(0,0,p.width);

view.measure(k,g);通知view的宽高




measureSpec:

MeasureSpec的简单说明
原创 2015年03月21日 14:24:38 标签:android /measure /spec 12135
   注:Spec为specification的缩写,以为规格或者说明书的意思(英语不好,专门 用英语翻译软件翻译了一下)。所以顾名思义该类的所以就是定义View的测量规格或者测量规则。这个类是View里面的嵌套内部类,提供了三个对外公开的static变量UNSPECIFIED,EXACTLY,AT_MOST,,这三个变量统称为specMode,对于一个View来说它的宽和高各有属于自己的specMode,至于其具体作用后面会有说说明。MeasureSpec提供了三个方法
    1)makeMeasureSpec(int size,int mode):size参数由程序员自己设定,mode必须是specMode的三个值中的一个
    2)getMode(int measureSpec):见名知意,方法返回specMode的三个值中的一个,注意方法参数measureSpec,这个参数的值是怎么得来的呢?正是由makeMeasureSpec方法计算出来的
   3)getSize(int measureSpec):获取View的大小,方法参数的值同样是由makeMeasureSpec计算的出来的。
     注意:看android源码的时候有一个小技巧:凡是参数的名字中带有spec后缀的参数,该值都是由makeMeasureSpec来计算出来的,这也是代码中良好命名习惯带来的好处之一。
    android的绘制流程中,第一个流程是Measure测量流程,而MeasureSpec在测量的过程中起到了至关重要的作用,不论是自定义View还是android自带的View,只要重写了onMearsure方法都能发现MeasureSpec的影子。测量过程中View类提供了measure方法,在该方法中调用了onMeasure方法,先看看这两份方法的签名 measure(int widthMeasureSpec, int heightMeasureSpec)、onMeasure(int widthMeasureSpec, int heightMeasureSpec),onMeasure方法中的参数是由measure方法直接传过去的;但是measure方法的参数是由谁来传过来的呢?还是那句话,看看方法名的后缀都有spec,这肯定和MeasureSpec方法有关了,确定得说他们的值就是有makeMeasureSpec方法来决定的。事实上正是如此:在measure的时候measure方法是由ViewRoot的performTraversals来调用的,在该方法中调用了getRootMeasureSpec方法,详见这位大神的博客。
  上面一直强调参数命名参数后缀为spec的方法跟MeasureSpec的关系密切,下面就顺着这个思路沿着View的继承机构挑几个类来查看分析MeasureSpec具体作用的体现。View类就有onMeasure和Measure方法,上面已经做了简单的说明,下面具体看看ViewGroup的方法,在viewGroup里面是没有重写onMeasure方法的,换句话说方法参数带有spec后缀的只有measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec),measureChildren(int widthMeasureSpec, int heightMeasureSpec)和measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed,int parentHeightMeasureSpec, int heightUsed)。在这里挑measureChild方法来进行说明:
[java] view plain copy
protected void measureChild(View child, int parentWidthMeasureSpec,  
            int parentHeightMeasureSpec) {  
        final LayoutParams lp = child.getLayoutParams();  
  
        final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,  
                mPaddingLeft + mPaddingRight, lp.width);  
        final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,  
                mPaddingTop + mPaddingBottom, lp.height);  
        //执行child的measure流程  
        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);  
 }            
对于以上代码要注意点就是方法参数parentWidthMeasureSpec和parentHeightMeasureSpec说明是父View的Spec,并且在代码里调用了getChildMeasureSpec方法。下面就看看getChildMeasureSpec的方法具体都干了些什么好事。
   方法参数说明:padding:当前父view的内边距
        childDimension: 子视图想要绘制的准确大小,其值可以是LayoutParams对象的width或者height变量。也就ch是xml文件中layout_height或者layout_width的值,可以是
         match_parent和wrap_content,也可以是具体的值
         spec:可以是父View经过makeMeasureSpec计算的值,也可以传递用户自己通过makeMeasureSpec计算的值(如果在你自己的代码中调用getChildMeasureSpec的话)
[java] view plain copy
public static int getChildMeasureSpec(int spec, int padding, int childDimension) {  
      //1.获取specMode,注意此时是父类的spec mode  
int specMode = MeasureSpec.getMode(spec);  
//获取view的size  
      int specSize = MeasureSpec.getSize(spec);  
  
//设置父view的size  
      int size = Math.max(0, specSize - padding);  
  
//因为spec有size和mode共同构成,所以定义了如下两个变量,经过处理后供makeMeasureSpec使用  
      int resultSize = 0;  
      int resultMode = 0;  
  
//解析specMode并做相应的处理  
      switch (specMode) {  
      // Parent has imposed an exact size on us  
//当父View的spec mode为 EXACTLY 时,父View强加给子View一个确切的大小  
      case MeasureSpec.EXACTLY:  
   //当用户设置了宽度值,比如xml文件里面设置了dimen值,直接用之  
          if (childDimension >= 0) {  
              resultSize = childDimension;  
        //在子view自己设置了size的情况下,比如xml文件里面layout_width或者layout_height设置了具体的dimen值  
              resultMode = MeasureSpec.EXACTLY;  
          } else if (childDimension == LayoutParams.MATCH_PARENT) {//如果子View layout_width或者layout_height为mactch_parent  
              // Child wants to be our size. So be it.  
        //子view的大小与父view的大小一样  
              resultSize = size;  
        //此时赋值为EXACTLY  
              resultMode = MeasureSpec.EXACTLY;  
          } else if (childDimension == LayoutParams.WRAP_CONTENT) {//如果子View layout_width或者layout_height为wrap_content  
              // Child wants to determine its own size. It can't be  
              // bigger than us.  
        //子view的大小由自己来决定,但是不能超过父View的大小  
              resultSize = size;  
        //此时赋值为At_MOST  
              resultMode = MeasureSpec.AT_MOST;  
          }  
          break;  
  
      // Parent has imposed a maximum size on us  
//当父View的spec mode为 AT_MOST 时,父View强加给一个最大的size给子view  
      case MeasureSpec.AT_MOST:  
      //当用户设置了宽度值,比如xml文件里面设置了dimen值,直接用之  
          if (childDimension >= 0) {  
              // Child wants a specific size... so be it                  
              resultSize = childDimension;  
        //在子view自己设置了size的情况下,比如xml文件里面layout_width或者layout_height设置了具体的dimen值  
              resultMode = MeasureSpec.EXACTLY;  
          } else if (childDimension == LayoutParams.MATCH_PARENT) {//如果子View layout_width或者layout_height为mactch_parent  
              // Child wants to be our size, but our size is not fixed.  
              // Constrain child to not be bigger than us.  
        //此时父view的大小和子view的大小一样  
              resultSize = size;  
        //此时mode 为AT_MOST  
              resultMode = MeasureSpec.AT_MOST;  
          } else if (childDimension == LayoutParams.WRAP_CONTENT) {//如果子View layout_width或者layout_height为wrap_content  
              // Child wants to determine its own size. It can't be  
              // bigger than us.  
        //子view的大小由自己来决定,但是不能超过父View的大小  
              resultSize = size;  
        //此时mode 为AT_MOST  
              resultMode = MeasureSpec.AT_MOST;  
          }  
          break;  
  
      // Parent asked to see how big we want to be  
//在父View的specMode为UNSPECIFIED,让子view决定自己有多大  
      case MeasureSpec.UNSPECIFIED:  
     //当用户设置了宽度值,比如xml文件里面设置了dimen值,直接用之  
          if (childDimension >= 0) {  
              // Child wants a specific size... let him have it  
              resultSize = childDimension;  
        //在子view自己设置了size的情况下,比如xml文件里面layout_width或者layout_height设置了具体的dimen值  
              resultMode = MeasureSpec.EXACTLY;  
          } else if (childDimension == LayoutParams.MATCH_PARENT) {  
              // Child wants to be our size... find out how big it should  
              // be  
              resultSize = 0;  
              resultMode = MeasureSpec.UNSPECIFIED;  
          } else if (childDimension == LayoutParams.WRAP_CONTENT) {  
              // Child wants to determine its own size.... find out how  
              // big it should be  
              resultSize = 0;  
              resultMode = MeasureSpec.UNSPECIFIED;  
          }  
          break;  
      }  
  
//最后调用makeMeasureSpec方法来提供子view的spec  
      return MeasureSpec.makeMeasureSpec(resultSize, resultMode);  
  }  
通过分析这个方法可以得出如下结论:从这个方法里可以看出父view的measureSpec在某种程度上决定了子view的measureSpec
1)不论父View 的specMode是EXACTLY、UNSPECIFIED、AT_MOST的哪一种,如果子view在xml文件里面把layout_width或者layout_height这是了具体
  的dimen值、或者在代码里调用相应的方法为view的宽度或者高度设置了具体的值,那么此时widthSpec的mode 或者heightSpec的mode就是EXACLTY,size就等于layout_width或者
  layout_height的值。此时子view的specMode值不受父View的specMode的影响。
2)当父View的specMode为EXACTLY的时候:父View强加给子View一个确切的大小,有如下两种情况
    2.1)子View的layout_width或者layout_height设置为MATCH_PARENT的时候,子View的specMode为EXACTLY
    2.2)子View的layout_width或者layout_height设置为WRAP_CONTENT的时候,子View的specMode为AT_MOST
    2.3)不论子view为match_parent或者wrap_content,resultSize都等于父类的size.
3)当父view的specMode为AT_MOST的时候:父View强加给一个最大的size给子view,最大的size也就是父view的size
    3.1)此时不论子view的为match_parent或者wrap_content,子view的specMode都为AT_MOST
    3.2)resultSize的大小被设置为父view的大小
4)当父view的specMode为UNSPECIFIED的时候:
    4.1) 此时不论子view的为match_parent或者wrap_content,子view的specMode都为UNSPECIFIED
    4.3)此时reusltSize = 0
5)从对UNSPECIFIED分析可以知道,在1)情况之外的情况下,要是想让子view自己决定自己的宽度或者高度的大小,MeasureSpec.makeMeasureSpec(0,UNSPECIFIED)这么调用来获取宽度和高度
的spec
6)根据方法的参数以及方法的实现可以知道,视图的大小是由父视图和子视图共同决定的,前提是子视图没有设置具体的dimen值




©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容