Day15-View

View From

View 分类

单一视图 如 TextView
视图组 如 ViewGroup, LinearLayout

ViewGroup 继承自 View

View 构造函数

分为两大类

//如果是在 Java 代码里面 new 的
private CarsonView(Context context){
  super(context);
}


// 如果是在.xml里声明的
// 自定义属性由 attrs 传递
private CarsonView(Context context, Attribute attrs){
  super(context, attrs);
}

// 在第二种情况下,
// 当 view 包含 style 属性
private CarsonView(Context context, Attribute attrs, int defStyleAttr){
  super(context, attrs, defStyleAttr);
}

// API21后
// 在第二种情况下,
// 当 view 包含 style 属性时
private CarsonView(Context context, Attribute attrs, int defStyleAttr, int defStyleRes){
  super(context, attrs, defStyleAttr, defStyleRes);
}

attrs XML中的属性
defStyleAttr 应用到 View 的默认风格(定义在主题中)
defStyleRes 如果没有使用 defStyleAttr , 应用到View的默认风格

View 视图结构

无论是 measure, layout 还是 draw, 永远都是从根View开始测量/计算, 最终确定整个View的属性

View 坐标系

top, left, right, bottom 属性都是相对父容器的


View 获取位置

  • view.getLeft() 获取view左上角到父容器左侧的距离

  • MotionEvent中
    触摸点相对于其所在坐标系中的距离

    e.getX()
    e.getY()
    
  • 触摸点相对于屏幕的距离

    e.getRawX();
    e.getRawY();
    

Android 中角度和弧度

角度的增大方向为顺时针

自定义View From

1. Measure

1.1 方法

  1. measure()
    final 类型, 无法重写, 最终会调用 onMeasure()
    • onMeasure()
      自己重写
      • setMeasureDimension()
        存储测量后的宽高

        • setMeasuredDimensionRaw()
          设置 mMeasuredWidth 和 mMeasuredHeight
      • getDefaultSize()
        根据测量规格的模式, 给出测量值

1.2 测量过程

一个view的值由 自身的LayoutParams 和 父布局的 MeasureSpec 决定 (DecorView除外, 它没有父布局, 由自身的 LayoutParams 和 窗口尺寸决定)

2. Layout

2.1方法

  1. layout();
    确定 View 本身的位置
  2. onLayout;
    单一 View 空实现,
    ViewGroup 调用 onLayout 遍历子View 并调用子View layout()确定自身子View 的位置
    ViewGroup中 因为子view的确定位置与布局有关, 需重写

2.2 layout 过程

2.3 getWidth/getHeight 和 getMeasureWidth/getMeasureHeight 差别

  1. 定义
  • getWidth/getHeight view最终的宽高
  • getMeasureWidth/getMeasureHeight view的测量的宽高
  1. 代码

    // View的测量的宽 / 高:
    public final int getMeasuredWidth() {  
        return mMeasuredWidth & MEASURED_SIZE_MASK;  
        // measure 过程中返回的 mMeasuredWidth
    }  
    
    public final int getMeasuredHeight() {  
        return mMeasuredHeight & MEASURED_SIZE_MASK;  
        // measure 过程中返回的 mMeasuredHeight
    }  
    
    
    // View最终的宽 / 高
    public final int getWidth() {  
        return mRight - mLeft;  
    // View最终的宽 = 子View的右边界 - 子view的左边界。
    }  
    
    public final int getHeight() {  
        return mBottom - mTop;  
    // View最终的高 = 子View的下边界 - 子view的上边界。
    }
    
    
  2. 时机

  • getMeasureWidth/getMeasureHeight
    在 measure 的 setMeasureDimension()中setMeasureDimensionRaw 赋值, 在 onLayout 用它来获取宽高
  • getWidth/getHeight
    在 layout 的 layout()中赋值, 可以用于除 onLayout() 之外的地方获取宽高
  1. 结论
    在onLayout中用getMeasureWidth/Height(), 在其他地方用getWidth/Height()
    一般情况下两者的值是永远相等的, 与View是否超出屏幕无关,
    除非人为设置
    通过重写View的layout()强行设置,
    @Override
    public void layout( int l , int t, int r , int b){
    
    // 改变传入的顶点位置参数
     super.layout(l,t,r+100,b+100)
    // 如此一来,在任何情况下,getWidth() ( getHeight())获得的宽 / 高总是比getMeasuredWidth() (getMeasuredHeight())获取的宽 (高)大100px
    // View的最终宽 / 高总是比测量宽 / 高大100px
    }
    

3. draw

3.1 方法

  • draw()
    绘制自身
    1. drawBackground()
      绘制自身View的背景
    2. onDraw()
      绘制自身View的内容, 自定义View中必须且只需要重写onDraw
    3. dispatchDraw()
      单一View空实现
    4. onDrawScrollBar()
      绘制装饰
3.2 draw 过程

setContentView

Activity 在 android 中的根布局被分为 标题栏 + ContentView(外面包着 FrameLayout), 所以我们平时操作的都是 ContentView, 布局都是 setContentView, 而不是setView


因为外部有父布局FrameLayout, 所以属性 layout_width 和 layout_height 里的layout都是有的, 设置能起作用的
而如果我们通过纯代码方式创建布局, 如下:

LinearLayout mainLayout = (LinearLayout)findViewById(R.layout.main_layout);
LayoutInflater layoutInflater = LayoutInflater.from(this);
View buttonView = layoutInflater.inflate(R.layout.button_layout, null);
mainLayout.addView(buttonView);

再给button_layout添加 layout_width 和 layout_height 属性

<Button xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="300dp"  
       android:layout_height="80dp"  
       android:text="Button" >  
</Button>  

会发现无效, 因为button_layout没有父布局, 所以套一个布局就能让属性生效了

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent" >  

    <Button  
        android:layout_width="300dp"  
        android:layout_height="80dp"  
        android:text="Button" >  
    </Button>  

</RelativeLayout>  

参考
Android LayoutInflater原理分析,带你一步步深入了解View(一)
深入理解Android View的构造函数
自定义View Measure过程 - 最易懂的自定义View原理系列(2)
自定义View Layout过程 - 最易懂的自定义View原理系列(3)
自定义View Draw过程- 最易懂的自定义View原理系列(4)
Android开发之getMeasuredWidth和getWidth区别从源码分析

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

推荐阅读更多精彩内容