关于自定义view属性设置

来源:互联网 发布:做农村淘宝合伙人优势 编辑:程序博客网 时间:2024/05/19 18:37

       以前很少注意到的一些问题,在看过一些大神的文章以后有了一些新的认识。真正觉得自己接触到的android只是冰山一角,大神们确实在这些方面已经超越了我太多太多了。所以虚心学习才能百尺竿头,废话不多说。

       本文主要讲解的是自定义控件当中的有关自定义属性的问题,以前的做法是:

        1.在res/value目录下创建一个xml文件,在resource节点下,声明declare-styleable标签,在标签里面声明item标签,每个item需要声明name跟format属性  每个item就是一个自定义属性。

        2.定义完属性就需要在xml里面使用。首先在布局文件的最外层定义命名空间,然后在自定义view里面使用自定义属性。

        3.在自定义view中获取xml文件里面使用的自定义属性  TypedArray array = context.obtainStyledAttributes();第一个参数是xml布局传递过来的属性,第二个参数是自定义的的属性文件,这个函数的作用在笔者看来是为了将xml里面设置的属性跟自定义属性匹配存储到array里面。

        4.获取自定义属性的value值,并用于操作。array.getInt();array.getString()等等诸如此类。



    然而今天看了大神的文章,又学到了一些东西:

    1.构造方法方面的问题,以前从来没有注意过这个问题:众所周知自定义view需要重新父类的构造方法,有一个参数、两个参数、三个参数、四个参数的。一个参数的使用场景主要是用在new 自定义view的时候,两个参数的使用场景主要是布局里面使用自定义view的时候。其余两种构造方法都很少用到。

     先来说明一个问题:我在自定义一个button的时候,重写了构造方法,但是在使用的时候,出现的并不是button的样式。看完大神的文章,我才知道了这个错误出现在什么地方,原来是我在自定义view的时候,构造方法里面没有使用默认的样式导致的。都知道构造方法的作用是:初始化一些相关内容以及获取自定义属性。之前我都是这么写的。

    

 public MyCustomImageView(Context context) {        this(context, null);    }    public MyCustomImageView(Context context, AttributeSet attrs) {        this(context, attrs, 0);//在此处写入要使用的默认样式文件    }    public MyCustomImageView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        this.mContext = context;        //解析xml中自定义控件的属性,并将xml里面的属性与自定义属性进行绑定        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyCustomImageView);

    原来构造器的写法是有两种方式的:

    第一种方式:

 public MyCustomImageView(Context context) {        super(context);        init();    }    public MyCustomImageView(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    public MyCustomImageView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }

第二种方式:
 public MyCustomImageView(Context context) {        this(context, null);    }    public MyCustomImageView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public MyCustomImageView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);


之所以会出现上述所说的自定义出来的view没有父类控件的默认样式的问题,是因为第二种方式更容易把theme里面的默认样式覆盖掉,这个场景下使用第一种方式更安全。如果需要设置defStyleAttr,使用第二种方式会比较好。


2.获取自定义属性的两种方式:

获取自定义的属性都需要将xml里面设置的属性跟自定义属性文件进行匹配。

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyCustomImageView);

这样xml里面的属性值就跟自定义属性文件里面的属性绑定在一起并存储在typedarray里面。

获取方式一:

String name = typedArray.getString();参数为属性id

int i = typedArray.getInt();第一个参数为属性id,第二个参数为默认值

获取方式二:

int count = typedArray.getIndexCount();//获取typedArray里面所有数据的数量        for (int i = 0; i < count; i++) {            //            Log.i("当前的属性是:", typedArray.getIndex(i) + "");            //要获得自定义属性,根据自定义属性获得xml中自定义属性设置的内容            int attr = typedArray.getIndex(i);//获取指定位置的index            switch (attr) {                case R.styleable.MyCustomImageView_src:                    //获取xml里面设置的内容                    int imageId = typedArray.getResourceId(R.styleable.MyCustomImageView_src, 0);//                    int resoourId = typedArray.getInt(R.styleable.MyCustomImageView_src, R.mipmap.ic_launcher); 这样获得的是全路径                    imageView.setBackgroundResource(imageId > 0 ? imageId : R.mipmap.ic_launcher);                    break;                case R.styleable.MyCustomImageView_text:                    //获取xml里面的内容设置到textview                    String text = typedArray.getString(R.styleable.MyCustomImageView_text);                    int resourceid = typedArray.getResourceId(R.styleable.MyCustomImageView_text, 0);                    textView.setText(resourceid > 0 ? typedArray.getResources().getText(resourceid) : typedArray.getString(R.styleable.MyCustomImageView_text));                    break;            }
//在xml文件里面如果使用的是引用,可以使用getResourceId();,如果使用的直接是文字或者数字,可以直接使用 typedArray.getString();或者typedArray.getInt()


3.defStyleRes 这个的作用是指定一个默认的style资源的。如果没有在布局文件里面指定自定义属性,就会自动加载该文件下的属性。
  
   defStyleAttr 是一个attr,它引用了一个style文件,并在当前theme下进行设置。指定一个默认的属性样式。可用于切换不同theme,view进行切换不同样式的场景。
大致如下:
1.首先定义一个attr文件:
 
<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="MyCustomImageView">        <attr name="text" format="string"></attr>        <attr name="src" format="integer"></attr>        <attr name="attrViewStyleRef" format="reference"></attr>//它的作用就是为了在不同theme下切换不同属性内容的    </declare-styleable></resources>


2.然后在theme下进行配置
<resources>    <!-- Base application theme. -->    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">        <!-- Customize your theme here. -->        <item name="colorPrimary">@color/colorPrimary</item>        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>        <item name="colorAccent">@color/colorAccent</item>        <item name="attrViewStyleRef">@style/ref</item>//对应自定义属性当中的属性    </style>    <style name="ref">//不同theme下设置不同的内容style        <item name="text">加油</item>        <item name="src">1</item>    </style>

3.在自定义view的构造函数中进行设置
TypedArray typedArray =context.obtainStyledAttributes(attrs,R.styleable.MyCustomImageView,R.attr.attrViewStyleRef,0);






                  

1 0
原创粉丝点击