一、属性动画
1.Animator
3.0之后的api,如果要在3.0之前使用需要导入NineOldAndroids。
2.ObjectAnimator
改变对象(Object)的属性,需要目标对象中对属性有get/set的方法。
如:
//可以帮助视图修改显示宽度,以及显示高度的类型
class ViewTool {
View v;
ViewTool(View v) {
this.v = v;
}
public void setWidth(int width) {
v.getLayoutParams().width = width;
//刷新视图
v.requestLayout();
}
public int getWidth() {
return v.getLayoutParams().width;
}
}
要对ViewTool这个对象改变width
ViewToolvt = new ViewTool(view);
ObjectAnimator.ofInt(vt,"width",vt.getWidth(),500).setDuration(3000).start();
3.ValueAnimator
改变数值的对象,需要设置改变范围、设置改变监听
privatevoid playAnimatorByValue(final int oldWidth) {
//创建ValueAnimator
ValueAnimator anim = ValueAnimator.ofInt(1, 100);
//添加变化监听
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
private IntEvaluator mEvaluator = new IntEvaluator();
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int current = (Integer)valueAnimator.getAnimatedValue();
Log.e("m_tag","==>" + current);
//取当前的宽度
// //基于当前变化的值算出要加的量
// int wantAdd = 380 * current/ 100;
// int w = oldWidth+ wantAdd;
// //改变显示的宽度
// mBtn.getLayoutParams().width = w;
float fraction = current /100f;
int w =mEvaluator.evaluate(fraction, oldWidth, 500);
mBtn.getLayoutParams().width =w;
mBtn.requestLayout();
}
});
anim.setDuration(3000).start();
}
二、自定义View
(一) View的显示流程
1、onMeasure,计算实际宽高
2、onLayout,容器布置显示位置和大小
3、onDraw,显示效果
(二)自定义属性
可以再values下创建属性资源文件,如attrs.xml,然后在resource标签中添加属性的定义。
<!--声明一系列属性集(属性数组)的标签 -->
<declare-styleable name="MyTextView">
<attr name="bigText" format="string"/>
<attr name="bigTextSize" format="dimension"/>
<attr name="bigTextColor"format="color"/>
<attr name="smallText" format="string"/>
<attr name="smallTextSize"format="dimension"/>
<attr name="smallTextColor" format="color"/>
</declare-styleable>
format表示属性的类型string是字符串 dimension表示尺寸 color表示颜色。
(三)应用自定义属性
需要在使用自定属性的布局中添加属性的命名空间(前缀)
如:
<LinearLayout
...
xmlns:abc="http://schemas.android.com/apk/res-auto"
...>
<com.xyy.viewdemo.MyTextView
...
abc:bigText="@string/app_name"
abc:bigTextSize="30sp"
abc:bigTextColor="@color/colorAccent"
abc:smallText="你好"
abc:smallTextColor="#ff0000ff"
abc:smallTextSize="20sp"/>
</LinearLayout>
(四)解析自定义属性
需要在自定义View的构造中获取属性值
/**一般在xml布局中使用自定义标签(包名.类名)申明,会调用的构造方法
*@param context 视图依赖的环境(如Activity)
*@param attrs 属性域
*/
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs); //该父类构造的调用均可以解析基本属性:宽高背景边距
//将AttributeSet转为TypeArray
TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.MyTextView);
//按照属性下标解析属性值
bigTitle = ta.getString(R.styleable.MyTextView_bigText);
bigTitleSize = ta.getDimensionPixelSize(R.styleable.MyTextView_bigTextSize,20);
bigTitleColor = ta.getColor(R.styleable.MyTextView_bigTextColor,Color.BLACK);
smallTitle = ta.getString(R.styleable.MyTextView_smallText);
smallTitleSize =ta.getDimensionPixelSize(R.styleable.MyTextView_smallTextSize, 16);
smallTitleColor = ta.getColor(R.styleable.MyTextView_smallTextColor,Color.RED);
//这里解析完毕一定要回收掉TypedArray
ta.recycle();
init();
}
(五)自定义宽高
需要重写onMeasure方法通过setMeasuredDimension设置实际宽高。
//视图需要测量宽高时触发(计算自身的宽高告诉父容器)
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//获取高方向的模式
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
//获取参考的高度
int height = MeasureSpec.getSize(heightMeasureSpec);
//如果模式为wrap_content方式,则计算精确的高度设置到MeasuredDimension
if (heightMode == MeasureSpec.AT_MOST) {
computeHeight();
height = bigHeight + smallHeight + 15;
}
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec), height);
}
(六)画出效果
//该视图显示的效果
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setTextSize(bigTitleSize);
mPaint.setColor(bigTitleColor);
//画文本
Paint.FontMetrics fm = mPaint.getFontMetrics();
int bigHeight = (int) (fm.bottom - fm.top);
canvas.drawText(bigTitle,5,bigHeight,mPaint);
mPaint.setTextSize(smallTitleSize);
mPaint.setColor(smallTitleColor);
fm = mPaint.getFontMetrics();
int smallHeight = (int) (fm.bottom - fm.top);
canvas.drawText(smallTitle,15,smallHeight+bigHeight+5,mPaint);
}