Android 自定义View
自定义View划分,分为三大类,第一种是自定义 View,第二种是自定义 ViewGroup,第三种是自定义组合控件。 其中自定义View又分为继承系统控件(比如TextView)和继承View两种。自定义ViewGroup也分为继承 ViewGroup 和继承系统特定的 ViewGroup(比如 RelativeLayout)
继承系统控件的自定义View
这种自定义View 在系统控件的基础上进行拓展,一般是添加新的功能或者修改显示的效果,一般情况 下在onDraw()方法中进行处理,例如自定义textview,继承系统的textview,在上面实现的划横线竖线
public class InvalTextView extends AppCompatTextView {
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
public InvalTextView(Context context) {
super(context);
initDraw();
}
public InvalTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initDraw();
}
public InvalTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initDraw();
}
private void initDraw() {
paint.setColor(Color.RED);
paint.setStrokeWidth(5.5f);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
//划横线
canvas.drawLine(0,height/2,width,height/2,paint);
//划竖线
canvas.drawLine(width/2,0,width/2,height,paint);
canvas.drawLine(0,height-2f,width,height-2f,paint);
}
<com.xiaobin.androidview.weigth.InvalTextView
android:id="@+id/invalTextView"
android:layout_width="120dp"
android:layout_height="80dp"
android:layout_gravity="center_vertical"
android:background="@android:color/holo_blue_bright"
android:layout_margin="10dp"
android:text="自定义textview"
android:textSize="12sp"
android:textColor="@android:color/black"
android:gravity="center"/>
示例图:
继承View 实现自定义控件
自定义view除了要实现onDraw,还要考虑到宽高以及外边距内边距的设置,对外提供自定义属性,在实现过程中还要考虑到wrap_content属性以及padding属性的设置
public class RectView extends View {
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private int color;
public RectView(Context context) {
super(context);
initDraw();
}
public RectView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
//使用attrs配置文件,为RectView自定义属性
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RectView);
//提取RectView的rect_color属性,设置,如果没设置 则默认Color.RED属性
color = typedArray.getColor(R.styleable.RectView_rect_color, Color.RED);
//获取资源后回收
typedArray.recycle();
initDraw();
}
public RectView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initDraw();
}
private void initDraw() {
paint.setColor(color);
paint.setStrokeWidth(2.0f);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//设置padding
int paddingLeft = getPaddingLeft();
int paddingRight = getPaddingRight();
int paddingTop = getPaddingTop();
int paddingBottom = getPaddingBottom();
//设置宽高
int width = getWidth()-paddingLeft-paddingRight;
int height = getHeight()-paddingTop-paddingBottom;
canvas.drawRect(0+paddingLeft,0+paddingTop,width+paddingRight,height+paddingBottom,paint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//设置默认宽高,设置wrap_content时生效,setMeasuredDimension单位是px
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST){
setMeasuredDimension(300,300);
}else if (widthSpecMode == MeasureSpec.AT_MOST){
setMeasuredDimension(300,heightSpecSize);
}else if (heightSpecMode == MeasureSpec.AT_MOST){
setMeasuredDimension(widthSpecSize,300);
}
}
}
<com.xiaobin.androidview.weigth.RectView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|right"
android:layout_margin="10dp"
android:padding="10dp"
android:background="@android:color/black"
app:rect_color="@android:color/holo_orange_dark"/>
默认设置padding,默认宽高,如果不设置指定宽高,就显示默认的,对外暴露控件设置背景色
示例图:
组合控件—自定义titleBar
自定义组合控件就是多个控件组合起来 成为一个新的控件–自定义titleBar。需要自定义控件属性,对外暴露,需要在在values目录下创建 attrs.xml,在其中声明属性
public class TitleBar extends RelativeLayout {
private ImageView iv_back;
private TextView tv_title;
private ImageView iv_right;
private RelativeLayout rl_titlebar_layout;
private int backgroundColor = Color.BLUE;
private int textColorColor = Color.WHITE;
private int underlineColor = Color.GRAY;
private String titleName = "";
private View underline_view;
public TitleBar(Context context) {
super(context);
initView(context);
}
public TitleBar(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.TitleBar);
backgroundColor = typedArray.getColor(R.styleable.TitleBar_title_bg,Color.BLUE);
textColorColor = typedArray.getColor(R.styleable.TitleBar_title_text_color,Color.WHITE);
titleName = typedArray.getString(R.styleable.TitleBar_title_text);
underlineColor = typedArray.getColor(R.styleable.TitleBar_underline_bg,Color.GRAY);
//释放资源
typedArray.recycle();
initView(context);
}
public TitleBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
private void initView(Context context) {
LayoutInflater.from(context).inflate(R.layout.view_titlebar,this,true);
iv_back = findViewById(R.id.iv_back);
tv_title = findViewById(R.id.tv_title);
iv_right = findViewById(R.id.iv_right);
rl_titlebar_layout = findViewById(R.id.rl_titlebar_layout);
underline_view = findViewById(R.id.underline_view);
rl_titlebar_layout.setBackgroundColor(backgroundColor);
tv_title.setTextColor(textColorColor);
tv_title.setText(titleName);
underline_view.setBackgroundColor(underlineColor);
}
public void setTitle(String titleName){
if (!TextUtils.isEmpty(titleName)){
tv_title.setText(titleName);
}
}
public void setLeftListener(OnClickListener onClickListener){
iv_back.setOnClickListener(onClickListener);
}
public void setRightListener(OnClickListener onClickListener){
iv_right.setOnClickListener(onClickListener);
}
}
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="RectView">
<attr name="rect_color" format="color"/>
</declare-styleable>
<declare-styleable name="TitleBar">
<attr name="title_text_color" format="color"/>
<attr name="title_bg" format="color"/>
<attr name="underline_bg" format="color"/>
<attr name="title_text" format="string"/>
</declare-styleable>
</resources>
布局文件:
<com.xiaobin.androidview.weigth.TitleBar
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="45dp"
app:title_text="自定义组合控件"
app:title_bg="@color/colorAccent"
app:title_text_color="@android:color/black"
app:underline_bg="@android:color/holo_red_light"/>
点击方法:
val title = findViewById<TitleBar>(R.id.title)
title.setLeftListener{
finish()
}
title.setRightListener{
Toast.makeText(this,"点击右侧按钮",Toast.LENGTH_LONG).show()
}
示例图:
自定义ViewGroup
继承viewgroup,实现一些类似于viewpager,FrameLayout的控件