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的控件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值