在android中,我们经常会在java代码中,或者在xml界面布局代码中使用我们的自定义控件。开发者可以通过自定义自己的控件时继承Android系统提供的view组件,就可以像在使用Android系统提供的view组件时一样,用一些系统中控件的属性来很好地控制View组件中的外观行为。但其实,我们也可以通过自定义自己的控件的属性值,来扩展自定义的属性,继而获得更好的外观控件或者其他的功能。
比如,我们可以通过在应用中添加一个组件属性
duration来达到控制图片从不透明到透明的效果。接下来就让我们来看看效果吧。
第一步,我们可以在/res/values目录下属性资源文件attrs.xml,属性资源文件的根元素也是 < resources…/>元素,该元素有两个子元素
attr:定义一个属性
declare-styleable:定义一个styleable对象,每个styleable对象就 是一组attr属性的集合。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--定义一个属性-->
<attr name="duration"></attr>
<!--定义一个包含多个属性的styleabe对象-->
<declare-styleable name="MyImageView">
<attr name="duration"/>
</declare-styleable>
</resources>
现在就定义了一个名字叫MyImageView的属性组,里面含有一个叫duration的属性。而属性有什么效果,则就看自定义的控件里面是怎么使用它的了。
而上面也有一个等价的写法,就是
<declare-styleable name="MyImageView">
<attr name="duration" format="integer"/>
</declare-tyleable>
接下来就是定义自己的控件 MyImageView
public class MyImageView extends ImageView {
//图片透明度每次改变的大小
private int alphaDelta = 0;
//记录图片当前的透明度
private int curAlpha = 0;
//每隔多少毫秒透明度改变一次
private final int SPEED = 300;
public MyImageView(Context context,AttributeSet attrs) {
super(context,attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.AlphaImageView);
//获取duration参数
int duration = typedArray.getInt(R.styleable.AlphaImageView_duration,0);
//计算图片透明度每次改变的大小
alphaDelta = 255 * SPEED / duration;
}
@Override
protected void onDraw(Canvas canvas) {
this.setImageAlpha(curAlpha);
this.setImageAlpha(curAlpha);
super.onDraw(canvas);
final Timer timer = new Timer();
//按固定间隔发送消息,通知系统改变图片的透明度
timer.schedule(new TimerTask() {
@Override
public void run() {
Message msg = new Message();
msg.what = 0x123;
if (curAlpha >= 255) {
timer.cancel();
} else {
handler.sendMessage(msg);
}
}
},0,SPEED);
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
if (message.what == 0x123) {
//每次增加curAlpha的值
curAlpha += alphaDelta;
if (curAlpha > 255) {
curAlpha = 255;
}
MyImageView.this.setAlpha(curAlpha);
}
}
};
}
最后,我们就在main_activity.xml文件中引用我们自己定义的控件与属性了。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:mydef="http://schemas.android.com/apk/res/自己的包名"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<com.自己的包名.MyImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"
mydef:duration="30000"
/>
</RelativeLayout>
在android studio中,由于应用是采用gradle来构造的,所以也可以直接用这个来替代上面的,AS会自己寻找相应的适合的路径的。 xmlns:mydef=”http://schemas.android.com.apk/res-auto” 包名就是你是你代码放的路径,举例说明 如 com.example.jinhom.attrdef