自定义View的使用场景:
- 1.显示特定风格
- 2.处理特有的用户交互
- 3.优化布局
- 4.封装
自定义View涉及内容
1.自定义属性的声明和获取(XML)
使用步骤:
- 1.xml代码中:
在res/values/attrs.xml中声明
name=”abc” format=”color”
在layout xml中使用
命名空间
xmlns:my=”http://schemas.android.com/apk/res/com.ixgsoft.space”- 2.Java代码中:
在构造方法中调用以下代码获取
TypedArray t =
getContext().obtainStyledAttributes(attrs,R.styleable.NewMyElement);
String textValue = t.getString(R.styleable.NewMyElement_textValue);
float textSize = t.getDimension(R.styleable.NewMyElement_textSize, 36);
int textColor = t.getColor(R.styleable.NewMyElement_textColor, 0xff0000
00);
2.测量onMeasure
- 目的:测量自身(和给子view大小一个参考-ViewGroup)
决定元素:模式(EXACTLY、ATMOST、UNSPECIFIED)和值
MeasureSpec测量辅助类
setMeasuredDimension设置自身view的尺寸
measureChild(child, parentWidthMeasureSpec, parentHeightMeasureSpec)给子
view一个尺寸大小的参考
requestLayout()请求重新测量会触发多次
3.绘制
- View onDraw(Canvas)
绘制内容区域
重绘invalidate(),和postInvalidate();
SurfaceView(双缓冲视图)
Canvas lockCanvas();
unlockCanvasAndPost(Canvas canvas)
canvas.save():把当前的绘制的图像保存起来,让后续的操作相当于是在一个新的图层上的操作。
canvas.restore(); 把当前画布返回(调整)到上一个save()状态之前
canvas.translate(dx, dy); //把当前画布的原点移到(dx,dy),后面的操作都以(dx,dy)作为参照点,默认原点为(0,0)
canvas.scale(x,y);扩大。x为水平方向的放大倍数,y为竖直方向的放大倍数
canvas.rotate(angel):旋转.angle指旋转的角度,顺时针旋转。
canvas.transform():切变。所谓切变,其实就是把图像的顶部或底部推到一边。
canvas.saveLayer(bounds, paint, saveFlags);- 认识一下canvas
Canvas类简单理解就是表示一块画布,可以在上面画我们想画的东西
Canvas中的方法很多,Canvas可以绘制的对象有:
弧线(arcs) canvas.
填充颜色(argb和color)
Bitmap
圆(circle和oval)
点(point)
线(line)
矩形(Rect)
图片(Picture)
圆角矩形 (RoundRect)
文本(text)
顶点(Vertices)
路径(path)
4.布局onLayout(ViewGroup才有)
- 1.决定子View的显示位置
2.requestLayout()请求重新测量
操作:child.layout(l,t,r,b)
5.事件定制
- onTouchEvent当前控件是否消化此事件
onInterceptTouchEvent(ViewGroup才有)事件转发过程中,当前(父)控件是否拦截子控件事
件
6.其他
- ViewConfiguation获取视图的一些常量(如mTouchSlop)
GestureDetector手势探测器,ScaleGestureDetector、SimpleOnGestureListener
ViewGragHelper快速实现拖拽
自定义荧光字体示例:
1.首先建立一个类,并继承TextView 重写3个方法:
- public FlickeringTextView(Context context) {
this(context, null);
}
public FlickeringTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public FlickeringTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//先获取系统属性,文字颜色
TypedArray a = context.obtainStyledAttributes(attrs, ATTRS);
textColor = a.getColor(0, textColor);
a.recycle();
//再获取自定义属性,闪烁颜色
a = context.obtainStyledAttributes(attrs, R.styleable.FlickeringTextView);
flickeringColor = a.getColor(R.styleable.FlickeringTextView_flickeringColor, flickeringColor);
//一定要回收,放置内存泄漏
a.recycle();
}
2.重写 onDraw方法
- @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mGradientMatrix != null) {
mTranslate += mViewWidth / 5;
if (mTranslate > mViewWidth * 2) {
mTranslate = -mViewWidth;
}
mGradientMatrix.setTranslate(mTranslate, 0);
mLinearGradient.setLocalMatrix(mGradientMatrix);
postInvalidateDelayed(100);
}
}
3.重写onSizeChanged:
这个是系统回调方法,是系统调用的,它的方法名已经告诉我们了,这个方法会在这个view的大小发生改变是被系统调用,我们要记住的就是view大小变化,这个方法就被执行就可以了,剩下的就是重写这个方法,在里面实现我们自己需求的业务逻辑,
- @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (mViewWidth == 0) {
mViewWidth = getMeasuredWidth();
if (mViewWidth > 0) {
mPaint = getPaint();
mLinearGradient = new LinearGradient(
0,//渐变起初点坐标x位置
0,//渐变起初点坐标y位置
mViewWidth,//渐变终点
0,//渐变终点
new int[]{textColor, flickeringColor, textColor},//参与渐变效果的颜色集合
null,//每个颜色处于的渐变相对位置
Shader.TileMode.CLAMP//平铺方式
);
mPaint.setShader(mLinearGradient);
mGradientMatrix = new Matrix();
}
}
4.xml中引用:
- xiangcuntiandi.myflytext.FlickeringTextView
android:visibility=”visible”
android:id=”@+id/start”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_centerInParent=”true”
android:gravity=”center”
android:text=”开始录制\nStart”
android:textColor=”#3F51B5”
android:textSize=”30sp”
app:flickeringColor=”#FF4081”
源代码:点击链接源代码