(一)概述
上节我们已经学习了完整的自定义View以及ViewGroup的详细流程和注意事项,今天我们学习——-继承自特定的View和ViewGroup
(二)继承自特定的View
继承我们最为熟悉的TextView ,我们不需要自己处理onMeasure()跟onLayot()方法,我们先来引用下徐大神的自定义TextView , 非常简约的自定义TextView ,我们一点点抽丝剥茧来看,把它改造成一个完美+标准的自定义TextView;
源码如下:
MyTextView.java
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.TextView;
public class MyTextView extends TextView {
private Paint mPaint1, mPaint2;
public MyTextView(Context context) {
super(context);
initView();
}
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public MyTextView(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
private void initView() {
mPaint1 = new Paint();
mPaint1.setColor(getResources().getColor(
android.R.color.holo_blue_light));
mPaint1.setStyle(Paint.Style.FILL);
mPaint2 = new Paint();
mPaint2.setColor(Color.YELLOW);
mPaint2.setStyle(Paint.Style.FILL);
}
@Override
protected void onDraw(Canvas canvas) {
// 绘制外层矩形
canvas.drawRect(
0,
0,
getMeasuredWidth(),
getMeasuredHeight(),
mPaint1);
// 绘制内层矩形
canvas.drawRect(
10,
10,
getMeasuredWidth() - 10,
getMeasuredHeight() - 10,
mPaint2);
canvas.save();
// 绘制文字前平移10像素
canvas.translate(10, 0);
// 父类完成的方法,即绘制文本
super.onDraw(canvas);
canvas.restore();
}
}
代码比较简单,简单说下:
初始化完成以后没执行onDraw()方法,这里TextView的OnDraw()方法的作用是绘制TextView的文本信息内容的,通过使用super来调用父类的OnDraw()方法,那么问题来了,我想给这个文本做一个矩形相框,怎么搞?必然是先把相框做好了,然后把文本弄上去,这就回答了,为什么要在super之前绘制矩形了!代码逻辑就是这样的;
activity_main.xml文件如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<com.mycoustomtextview.MyView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:text="因崔思婷~"
android:textSize="30sp"/>
</LinearLayout>
运行结果:
细心的小伙伴们,大概发现了对吧~没错,这货的宽高居然都是wrap_content ?按照我们之前说的,它没有从写OnMeasure()方法呀!显示效果应该是跟math_parent完全的一样的呀(即铺满屏幕),这是为什么呢?自然是去看看TextView的源码了:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
throw new RuntimeException("Stub!");
}
哇哈哈~它并没有进行“测量模式+测量大小”的套路,而是直接得到了测量值得,那么它是否支持padding 跟margin ?当然了!你可以试试~
好了,我们继续~这里允许我吐槽一下Android 的原生控件,比如SearchView ,我理想的SearchView是这样的:
可事实上它是长这样的:
怎么样是不是感觉丑哭了,o(╯□╰)o !!!
所以,我们需要在原生控件的基础上加入自己的自定义属性,那SearchView来说,我们增加了最右边的删除”X”,最左边的搜索图标,外围加入了一个矩形等自定义属性,看起来漂亮多了,别急,我后面会写一个加入TextView属性的自定义RelativeLayout;
(三)继承特定的ViewGroup
自定义ViewGroup跟继承特定ViewGroup方法步骤类似,只是自定义ViewGroup更加贴近底层,那么什么候会使用这个方法,当某种效果看起来像多个View组合而成的时候可以使用;(暂时还没有找到一个恰当的案例,找到了我一定给大家补上)