带你真正认识View

栏目: 编程语言 · XML · 发布时间: 7年前

内容简介:作为一个Android开发者,工作中肯定或多或少都会跟自定义View打交道,但是我们的第一反应就是这太难了,去网上找找,看看有没有现成的可以拿来直接用的。其实之所以我们觉得自定义View很难,根本原因还是我们对于View的基础掌握不牢。今天这篇文章,我就带大家一起重新学习一下View的基础。

作为一个Android开发者,工作中肯定或多或少都会跟自定义View打交道,但是我们的第一反应就是这太难了,去网上找找,看看有没有现成的可以拿来直接用的。

其实之所以我们觉得自定义View很难,根本原因还是我们对于View的基础掌握不牢。

今天这篇文章,我就带大家一起重新学习一下View的基础。

View的构造函数

1.View(Context)

Java 代码里面直接new的时候调用。

2. View(Context, AttributeSet)

.xml 里声明的时候调用, AttributeSet 是从 .xml 中解析出来的属性集合。

<ImageView  
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/icon" />
复制代码

上面 .xml 中的 layout_width , layout_height 以及 src 是从哪里来的?它们可不是凭空产生的;实际上是通过 <declare-styleable> 把这些属性明确的声明为系统需要处理的东西。比如,src就是在这里定义的:

<declare-styleable name="ImageView">  
    <!-- Sets a drawable as the content of this ImageView. -->
    <attr name="src" format="reference|color" />
</declare-styleable>
复制代码

每个 declare-styleable 产生一个 R.styleable.[name] ,外加每个属性的 R.styleable.[name]_[attribute] 。比如,上面的代码产生 R.styleable.ImageViewR.styleable.ImageView_src

这些资源是什么东西呢? R.styleable.[name] 是所有属性资源的数组,系统使用它来查找属性值。每个 R.styleable.[name]_[attribute] 只不过是这个数组的索引罢了,所以你可以一次性取出所有属性,然后按索引分别查询每个的值。

xml 中属性是以 AttributeSet 的形式通过构造方法传递给 View 的,但通常我们不直接使用 AttributeSet 。而是使用 Theme.obtainStyledAttributes() 。这是因为原始的属性通常需要引用和应用样式。比如,如果你在XML中定义了 style=@style/MyStyle ,这个方法先获取 MyStyle ,然后把它的属性混合进去。最终 obtainStyledAttributes() 返回一个 TypedArray ,你可以用它来获取属性值。这个过程简化之后就像这样:

public ImageView(Context context, AttributeSet attrs) {
    TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ImageView, 0, 0);
    Drawable src = ta.getDrawable(R.styleable.ImageView_src);
    setImageDrawable(src);
    ta.recycle();
}
复制代码

这里我们向 obtainStyledAttributes() 传递了两个参数。第一个参数是 AttributeSet attrs ,即xml中的属性;第二个参数是 R.styleable.ImageView 数组,它告诉这个方法我们想取哪个属性的值,这里表示要获取 ImageView 属性的值;第三和第四个参数是两个资源引用 defStyleAttrdefStyleRes ,将在第三和第四个构造方法中进行说明。 当获得了 TypedArray 之后,我们就可以获取单个属性了。我们需要使用 R.styleable.ImageView_src 来正确索引数组中的 src 属性。

3. View(Context, AttributeSet, defStyleAttr)

defStyleAttr 参数:默认的 Style ,指它在当前 ApplicationActivity 所用的 Theme 中的默认 Style ,为某个类型的 View 定义这个类的基础样式,如果我们不在构造方法传入指定我们自定义的样式则将使用 Android 系统默认的控件样式,指定时需要间接的通过 theme ,如下所示:

1、在Theme(styles.xml)中设置样式

<resources>  
    <style name="Theme">
      <item name="mStyle">@style/CustomStyle</item>
    </style>
    
    <!--具体样式-->
    <style name="CustomStyle" >
      <item name="android:background">@android:color/black</item>
    </style>
</resource>
复制代码

2、在构造方法中使用

TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.view, R.attr.mStyle, 0);
复制代码

4. View(Context, AttributeSet, defStyleAttr, defStyleRes)

defStyleRes 参数:它只是一个用于指定样式的 style 资源( @style/Widget.TextView )。比 defStyleAttr 简单,不需要间接的通过 theme 。在API 21添加的。因此除非你的 minSdkVersion21 ,否则不要使用它。

它们是串联的,如果你调用了一个,所有的都会通过 super 被调用。串联还意味着你只需重写你需要的构造函数。一般来说,你只需实现前两个(一个用于代码,一个用于 XML inflation )。

View视图结构

对于多 View 的视图,结构是树形结构:最顶层是 ViewGroupViewGroup 下可能有多个 ViewGroupView ,如下图:

带你真正认识View

注意:无论是 measure 过程、 layout 过程还是 draw 过程,永远都是从 View 树的根节点开始测量或计算(即从树的顶端开始),一层一层、一个分支一个分支地进行(即树形递归),最终计算整个 View 树中各个 View ,最终确定整个 View 树的相关属性。

Android坐标系

Android的坐标系定义为:

x
y

具体如下图:

带你真正认识View

View位置(坐标)描述 )

  • View的位置由4个顶点决定的(如下图A、B、C、D)
  • 4个顶点的位置描述分别由4个值决定(View的位置是相对于父控件而言的):

Top :子View上边界到父view上边界的距离

Left :子View左边界到父view左边界的距离

Bottom :子View下边距到父View上边界的距离

Right :子View右边界到父view左边界的距离

带你真正认识View

View位置获取方式

View的位置是通过 view.getxxx() 函数进行获取(以Top为例):

// 获取Top位置
public final int getTop() { 
  return mTop; 
} 
// 其余如下:
getLeft();//获取子View左上角距父View左侧的距离 
getBottom(); //获取子View右下角距父View顶部的距离
getRight(); //获取子View右下角距父View左侧的距离
复制代码

MotionEventget...()getRaw...() 的区别

//get() :触摸点相对于其所在组件坐标系的坐标
event.getX();       
event.getY();
//getRaw() :触摸点相对于屏幕坐标系的坐标
event.getRawX();    
event.getRawY();
复制代码

具体如下图:

带你真正认识View

Android的角度(angle)与弧度(radian)

角度和弧度都是描述角的一种度量单位,区别如下图:

带你真正认识View

在默认的屏幕坐标系中角度增大方向为顺时针,与数学坐标系中角度增大方向刚好相反。

带你真正认识View

Android中颜色相关内容

Android支持的颜色模式:

带你真正认识View

以ARGB8888为例介绍颜色定义:

带你真正认识View

定义颜色的方式

  • 在java中定义颜色
//java中使用Color类定义颜色
int color = Color.GRAY; //灰色
//Color类中使用ARGB值表示颜色
int color = Color.argb(127, 255, 0, 0); //半透明红色
//使用十六进制定义颜色
int color = 0xaaff0000; //带有透明度的红色 
//Android中Color工具类 parseColor解析颜色字符串
int color = Color.parseColor("#FFFFFF")//白色
复制代码
  • 在xml文件中定义颜色 /res/values/color.xml
<?xml version="1.0" encoding="utf-8"?> 
<resources>
   //定义了红色(没有alpha(透明)通道) 
   <color name="red">#ff0000</color>
   //定义了蓝色(没有alpha(透明)通道) 
   <color name="green">#00ff00</color> 
</resources>
复制代码
  • xml 文件(不局限与布局 xml 文件,其它 xml 文件也可以用这种定义方式)中以 "#" 开头定义颜色,后面跟十六进制的值,有如下几种定义方式:
#f00 //低精度 - 不带透明通道红色 == #ff0000
#af00 //低精度 - 带透明通道红色 == #aaff0000
#ff0000 //高精度 - 不带透明通道红色 
#aaff0000 //高精度 - 带透明通道红色
复制代码

引用颜色的方式

  • 在java文件中引用 color.xml 中定义的颜色:
int color = getResources().getColor(R.color.mycolor);
复制代码
  • xml 文件( layoutstyle )中引用或者创建颜色:
<!--在style文件中引用-->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> 
   <item name="colorPrimary">@color/red</item>
</style> 
<!--在layout文件中引用在/res/values/color.xml中定义的颜色--> 
android:background="@color/red" 
<!--在layout文件中创建并使用颜色--> 
android:background="#ff0000"
复制代码

希望这边文章能对您有所帮助~~~~~~~~

原文链接


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Design systems

Design systems

Not all design systems are equally effective. Some can generate coherent user experiences, others produce confusing patchwork designs. Some inspire teams to contribute to them, others are neglected. S......一起来看看 《Design systems》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

MD5 加密
MD5 加密

MD5 加密工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具