自定义View的构造函数:
public class TestView extends View {
public TestView(Context context) {
super(context);
}
public TestView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
}
自定义属性:
1.在
values/attrs.xml
文件中定义自定义属性:
<resources>
<declare-styleable name="test">
<attr name="name" format="string" />
<attr name="count" format="integer" />
<attr name="xxx" format="color" />
<attr name="xxx" format="reference" /> //资源ID,如xxx="@drawable/xxx"
<attr name="xxx" format="boolean" />
<attr name="xxx" format="dimension" />
<attr name="xxx" format="float" />
<attr name="xxx" format="fraction" /> //百分数,如xxx="100%"
<attr name="xxx" format="color" />
<attr name="xxx" format="reference|color" /> //混合属性
<attr name="orientation"> //枚举,orientation="vertical">
<enum name="horizontal" value="0" />
<enum name="vertical" value="1" />
</attr>
</declare-styleable>
</resources>
2.自定义View中获取这些属性:
public class MyTextView extends View {
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.test);
String name = ta.getString(R.styleable.test_name);
int count = ta.getInteger(R.styleable.test_count, -1);
ta.recycle();
}
}
自定义控件的一般形式:
1.继承View重写onDraw创建不规则View:
一些Paint的常用设置:
注意paint的设置最好不要写在onDraw方法里
Paint paint = new Paint();
paint.setColor(0xFFFFFFFF);
paint.setAntiAlias(true);
paint.setDither(true);
paint.setStyle(Paint.Style.FILL);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
Paint.setTextSize(50);
path用来画不规则图形:
Path path = new Path();
path.moveTo(100, 100);
path.lineTo(100, 100);
path.quadTo(100, 200, 200, 200);
path.cubicTo(200, 100, 200, 200, 100, 200);
path.close();
渐变:
Shader shader = new LinearGradient(x1, y1, x2, y2,
new int[]{Color.RED,Color.BLACK,Color.GREEN},
new float[]{0 , 0.5f, 1.0f}
Shader.TileMode.REPEAT);
paint.setShader(shader);
canvas:
canvas才是最后绘制的主体,它可以:绘制图形,变换,存档
canvas.drawLine(x1, y1, x2, y2, paint);
canvas.drawRect(x1, y1, x2, y2, paint);
canvas.drawCircle(ox, oy, r, paint);
canvas.drawOval(new RectF(x1, y1, x2, y2), paint);
canvas.drawPath(path, paint);
canvas.drawText("hello world", 100, 100, mPaint);
canvas.drawRoundRect(new RectF(x1, y1, x2, y2), 30, 20, mPaint);
canvas.drawColor(Color.GRAY);
canvas.translate(100, 100);
canvas.scale(0.5f, 0.5f);
canvas.rotate(45,200,200)
canvas.skew(0, 1);
canvas.save();
canvas.restore();
2.继承某种ViewGroup
用来继承某个布局中包含多个控件的情况,类似于<Merge>标签的功能,只是通过自定义控件的方式控件组增加一些逻辑
public class SimpleEditor extends FrameLayout {
private EditText editor;
private Context context;
public SimpleEditor(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
private void init() {
inflate(context, R.layout.layout_simple_editor, this);
editor = (EditText) findViewById(R.id.root_view);
}
}
3.继承某种系统控件,扩展其功能
例如给TextView加条下划线:
public class LineTextView extends TextView {
private Paint mPaint;
public LineTextView(Context context) {
super(context);
init();
}
public LineTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setColor(Color.BLACK);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
mPaint.setColor(Color.BLUE);
canvas.drawLine(0,height,width,height,mPaint);
}
}