控件属性

前言:在开发过程中我们会经常遇到修改控件属性以及窗口属性的问题,现在就来分析下这些属性;

1.先从一个xml布局开始:

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

这是一个很简单的布局,我们来逐步分析:

xmlns:android="http://schemas.android.com/apk/res/android"

xmlns的全名是xml namespace,有点像C++中的namespace,它的作用是引入"android"这个概念,以便于后面的android:layout_width可以正常使用,如果没有声明"android"这个概念,android:layout_width是个错误的写法;

"http://schemas.android.com/apk/res/android"中最后面的一个字段"android",指的是包名,这个"android"是在manifest.xml中被声明的;

所以上面xml布局中代码的含义就是:

声明android引用,并给android引用赋予一个地址,接下来就可以使用android中的内容了;

 

再来举个项目中的例子:

<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.gome"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <com.gome.internal.menu.FloatActionMenuView
        android:id="@+id/floatMenu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal|bottom"
        android:layout_marginBottom="10dp"
        app:maxItems="3"
        app:menu="@menu/panel_edit_menu" />
</FrameLayout>

可以看到: xmlns:app="http://schemas.android.com/apk/res/com.gome";

这就表示了,app指向了com.gome这个包名,看看这个com.gome是在哪定义的?

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.gome" 
    coreApp="true"
    android:sharedUserId="android.uid.system"
    android:sharedUserLabel="@null">
</manifest>

com.gome是应用程序包名;

既然已经声明了app,接下来就可以使用它的内容了:

app:maxItems="3"

app:menu="@menu/panel_edit_menu"

注意:Manifest.xml中的"com.gome"与布局xml不在同一个进程里面,即"com.gome"是另一个应用,如果"com.gome"在布局xml的进程里面,还可以这样定义app:

xmlns:app="http://schemas.android.com/apk/res/res-auto";

表示在该程序包名的目录下自动查找路径;

 

2.上面介绍了怎么样使用app,但是没有解释app:maxItems="3"是怎么来的?接下来就详解下自定义属性:

我们以一个TextView为例:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:text="@string/msg_scroll_sreenshot_stop_hint"
    android:textColor="#ffffffff"
    android:textSize="13sp" />

可以看到TextView中有text,textColor,textSize这三个属性,而且,这三个属性的所对应的值的类型也是不同的,textColor对应的是"#ffffffff",textSize对应的是"13sp",这是怎么回事?

TextView其实就是一个标签,既然是标签,那就肯定有定义标签的地方,TextView标签的定义在frameworks\base\core\res\res\values\attrs.xml中的;

<declare-styleable name="TextView">
    <attr name="bufferType">
        <enum name="normal" value="0" />
        <enum name="editable" value="2" />
    </attr>

    <attr name="hint" format="string" />
    <attr name="textSize" />
    <attr name="textScaleX" format="float" />
    <attr name="cursorVisible" format="boolean" />
    <attr name="lines" format="integer" />
    <attr name="height" format="dimension" />
        <flag name="integer" value="0x01" />
        <flag name="signed" value="0x03" />
        <flag name="decimal" value="0x05" />
    </attr>
    <attr name="drawableTop" format="reference|color" />
    <attr name="drawableTint" format="color" />
    ............
</declare-styleable>

TextView中的attr代表着TextView标签中的属性,属性后面的format指的是该属性可以被赋予哪些类型的值,不同的属性可以被赋予的值的类型也就不同,接下来详细分析下这些属性:

①<attr name="hint" format="string" />

表示值的类型是字符串类型;

如:<TextView android:text = "我是文本"/>

②<attr name="textScaleX" format="float" />

表示值的类型是float类型;

如:<TextView android:textScaleX = "1.0"/>

③<attr name="cursorVisible" format="boolean" />

表示值的类型是boolean类型;

如:<TextView android:cursorVisible= "false"/>

④<attr name="drawableTop" format="reference|color" />

表示值的类型既可以是引用类型也可以是color类型;

如:<TextView android:drawableTop= "@drawable/图片ID"/>

<TextView android:drawableTop= "#ffff0000"/>

⑤<attr name="height" format="dimension" />

表示值的类型是尺寸类型;

如:<TextView android:layout_height= "42dp"/>

⑥<attr name="bufferType">

    <enum name="normal" value="0" />

    <enum name="editable" value="2" />

</attr>

表示值的类型是枚举类型;

如:<TextView android:bufferType= "normal"/>

⑦<attr name="height" format="dimension" />

    <flag name="integer" value="0x01" />

    <flag name="signed" value="0x03" />

    <flag name="decimal" value="0x05" />

 </attr>

表示值的类型是位或运算类型;

如:<TextView android:height= "integer|signed"/>

 

看完了这些,大家知道textview属性的赋值含义了吧;

<TextView
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:text="@string/msg_scroll_sreenshot_stop_hint"
    android:textColor="#ffffffff"
    android:textSize="13sp" />

 

注意:

①我们看到在Textview的标签声明中,并没有layout_width属性,为啥在TextView中可以使用这些属性?

因为TxetView是继承自View这个类的,View类的所拥有的属性TextView全部拥有,layout_width属性被定义在View中,可以Textview可以直接使用;

②在TextView标签中,我们看到textSize属性并没有被指明要赋哪种类型的值:

<attr name="textSize" />;

format是限定当前定义的属性能接受什么值,如果不带format的就是在使用已有的属性;

 

3.根据上面的介绍,接下来我们自定义一个属性:

①首先在attrs文件中添加我们的自定义属性:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyTextView2">
        <attr name="myText" format="string"/>
        <attr name="myTextColor" format="color"/>
        <attr name="myTextSize" format="dimension"/>
    </declare-styleable>
</resources>

②在布局文件中使用该属性:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:myview="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.qianmo.activitydetail.MyTextView2
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#00ff00"
        myview:myText=" I Love You ......I Love You ......"
        myview:myTextColor="#ff3399"
        myview:myTextSize="25sp"/>
</LinearLayout>

③在构造方法中获取我们的自定义属性

public MyTextView2(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
       super(context, attrs, defStyleAttr);
       init(context, attrs, defStyleAttr);
   }
 
   /**
    * 初始化数据
    */
   private void init(Context context, AttributeSet attrs, int defStyleAttr) {
       //获取自定义属性的值
       TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyTextView2, defStyleAttr, 0);
       mText = a.getString(R.styleable.MyTextView2_myText);
       mTextColor = a.getColor(R.styleable.MyTextView2_myTextColor, Color.BLACK);
       mTextSize = a.getDimension(R.styleable.MyTextView2_myTextSize, 30f);
       a.recycle();
 
       //初始化Paint数据
       mPaint = new Paint();
       mPaint.setColor(mTextColor);
       mPaint.setTextSize(mTextSize);
 
       //获取绘制的宽高
       mBound = new Rect();
       mPaint.getTextBounds(mText, 0, mText.length(), mBound);
       Log.i(TAG, "mText :" + mText + ",mTextColor:" + mTextColor+ ",mTextSize:" + mTextSize);
   }

4.属性使用时的常见问题解析

①<style name="MusicTheme" parent="@com.gome:style/Theme.GOME.Light">

这个@com.gome:style/Theme.GOME.Light是啥意思?

这句代码和下面这句代码有点雷同:android:id="@android:id/tabhost";

"@"表示引用;

"android:id"表示是android包下面的id属性;

"tabhost"表示id的名字叫做tabhost;

所以,"@com.gome:style/Theme.GOME.Light"的意思就是:引用"com.gome"包下的名为"Theme.GOME.Light"的"style"属性;

 

②android:textAppearance="?android:attr/textAppearanceSmall"

这个怎么解释?开始分析:

"textAppearanceSmall",是"Theme"标签的属性:

<declare-styleable name="Theme">
    <attr name="textAppearanceSmall" format="reference" />
</declare-styleable>

所以"android:attr/textAppearanceSmall"可以简单理解为:android包下的Theme标签的textAppearanceSmall属性;

那"?"是意思呢?--> "?"表示系统是否给Theme标签的textAppearanceSmall属性设置了值,如果系统给它设置了值,那我们就引用这个textAppearanceSmall,如果没有,那就使用默认的值;

我们知道,不同的风格,就有不同的Theme,不同的Theme就有不同的textAppearanceSmall,比如:

<style name="Theme.Material">
    <item name="textAppearanceSmall">@style/TextAppearance.Material.Small</item>
</style>

<style name="Theme.Material.Light" parent="Theme.Light">
    <item name="textAppearanceSmall">@style/TextAppearance.Material.Small</item>
</style>

<style name="Theme.Holo">
    <item name="textAppearanceSmall">@style/TextAppearance.Holo.Small</item>
</style>

所以:"?android:attr/textAppearanceSmall"就是引用相应Theme风格下的textAppearanceSmall属性;

 

③"?"和"@"有什么区别?

这个问题是接着上面那两个问题的,何时用"@........",何时用"?.........";

@是引用的意思,@......表示引用一个确定的值,如引用一个drawable,引用一个style,drawable和style都是有明确的唯一的值,如:

<style name="Theme.Material">
    <item name="textAppearanceSmall">@style/TextAppearance.Material.Small</item>
</style>

Theme.Material有确定的唯一的值;

?也可以理解为引用,但它引用的是一个属性,这个属性被定义在Theme标签中,在theme.xml中会给不同Theme的该属性指定不同的值,这个从案例②中就可以看到;所以?......就是指定该Theme中的这个属性所对应的值;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

renshuguo123723

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值