Android自定义view

一说起自定义view,似乎好高大上的样子,其实只是小马过河。

自定义view的入门相当的简单,让我想起了我的第一个程序,Hello World;

然后是自定义view的进阶,在我感觉就像我们常玩的积木,自需要根据一定的规律通过提供的方法、接口等把我们需要的东西组装在一起(当然,首先自己需要先了解要实现view的逻辑,否则该干嘛干嘛去吧,再者,需要知道实现view中功能的方法、接口,这些就需要自己平时的积累了)

自定义view入门

  • 自定义属性(xml中设置view的属性)
  • 获取设置的属性(获取xml中设置的属性)
  • 重写onMeasure方法(设置view的宽高)
  • 重写onDraw方法(绘制view的内容)

自定义属性
详细自定义属性

https://blog.csdn.net/qq1302526289/article/details/80747645

在res/values文件夹下创建attrs.xml文件

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--自定义控件文字内容-->
    <attr name="customViewText" format="string"/>
    <!--自定义控件文字内容颜色-->
    <attr name="customViewcolor" format="color|reference"/>
    <!--自定义控件文字内容大小-->
    <attr name="customViewSize" format="dimension"/>
    <declare-styleable name="CustomView">
        <attr name="customViewText"/>
        <attr name="customViewcolor"/>
        <attr name="customViewSize"/>
    </declare-styleable>
</resources>

在界面中使用定义的属性

<LinearLayout android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    xmlns:android="http://schemas.android.com/apk/res/android">
    
    <bin.com.customviewone.CustomView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        custom:customViewText="CustomView"
        custom:customViewcolor="@color/colorPrimary"
        custom:customViewSize="12sp" />
        
</LinearLayout>

获取设置的属性
创建CustomView类,继承View,在构造方法中获取自定义属性

public class CustomView extends View {

    String text;
    int color;
    int size;

    private Paint mPaint;
    
    public CustomView(Context context) {
        this(context, null);
    }

    public CustomView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomView, defStyleAttr, 0);
        int count = typedArray.getIndexCount();
        for(int i = 0; i < count; i++){
            int attr = typedArray.getIndex(i);
            switch (attr)
            {
                case R.styleable.CustomView_customViewText:
                    text = typedArray.getString(attr);
                    break;
                case R.styleable.CustomView_customViewcolor:
                    color = typedArray.getColor(attr, Color.BLACK);
                    break;
                case R.styleable.CustomView_customViewSize:
                    size = typedArray.getDimensionPixelSize(attr, 20);
                    break;
            }
        }
        //释放资源
        typedArray.recycle();
        mPaint = new Paint();
        mPaint.setTextSize(size);
    }
}

重写onMeasure方法

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

widthMeasureSpec、heightMeasureSpec并不是控件的真实宽、高,它是由宽、高的模式(例如:wrap_content、match_parent代表设置不同的模式)和具体的宽、高2部分组成。
获取宽的模式:int specMode = MeasureSpec. getMode(widthMeasureSpec);
模式具体的值
MeasureSpec. UNSPECIFIED:(可以随意设置大小,可以超过父布局)
MeasureSpec. AT_MOST:(可以随意设置大小,不能超过父布局)(当宽、高设置wrap_content时)
MeasureSpec. EXACTLY:(表示设置具体的值)(当宽、高设置具体值或者match_parent时)
获取真实的宽度: int specSize = MeasureSpec. getSize(widthMeasureSpec);
当宽、高的模式为MeasureSpec. AT_MOST和MeasureSpec. EXACTLY时,则不需要重新设置宽、高;如果是MeasureSpec. UNSPECIFIED时,则需要计算view的宽、高,然后通过setMeasuredDimension()方法设置宽、高。

 @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
  {
      int specWidthMode = MeasureSpec. getMode(widthMeasureSpec);
      int specWidthSize = MeasureSpec. getSize(widthMeasureSpec);
      int specHeightMode = MeasureSpec. getMode(heightMeasureSpec);
      int specHeightSize = MeasureSpec. getSize(heightMeasureSpec);
      switch (specWidthMode){
          case MeasureSpec.UNSPECIFIED:
	          //不确定什么时候会执行这个
              break;
          case MeasureSpec.AT_MOST:
	          //当宽、高设置wrap_content时)
	          //计算view的宽度,赋值给specWidthSize
	          break;
          case MeasureSpec.EXACTLY:
	          //(当宽、高设置具体值或者match_parent时)
              //specWidthSize不变
              break;
      }
      switch (specHeightMode){
          case MeasureSpec.UNSPECIFIED:
              break;
          case MeasureSpec.AT_MOST:
	          //计算view的高度,赋值给specHeightSize
	          break;
          case MeasureSpec.EXACTLY:
              //specHeightSize不变
              break;
      }
      //设置view的宽、高
      setMeasuredDimension(specWidthSize, specHeightSize);
  }

重写onDraw()方法

@Override
protected void onDraw(Canvas canvas)
{
	//mPaint在构造方法中初始化,相当于画笔;canvas相当于画布;getHeight 获取view的高
    mPaint.setColor(color);
    canvas.drawText(text, 20, getHeight(), mPaint);
}

主要在这个方法中绘制需要展示的东西,具体怎么绘制布局,可以自己了解;上面只是在界面中写字。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值