安卓自定义view总结1

来源:互联网 发布:广东高考难度 知乎 编辑:程序博客网 时间:2024/06/03 18:02

一直以来用了很多自定义view都没有好好总结,今天就总结总结:


第一个例子:验证码

思路:重写view:

1. values下创建文件attr.xml :这里主要放自定义view(控件)需要的:属性名,属性代表的值;

2.写一个自定义view继承view类:

     2.1:重载构造函数的三种: public CustomTitleView(Context context);

                                                 public CustomTitleView(Context context, AttributeSet attrs);

                                                 public CustomTitleView(Context context, AttributeSet attrs, int defStyle);       

                                                   在这些构造函数中:按需取得attr.xml文件下第一步定义的属性,和属性值;

                                     一般要用到的类和函数:

                                  TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomTitleView, defStyle, 0); //从attr.xml中获取declare-styleable下的节点

                               int n = a.getIndexCount();       //获取节点的总个数

                              int attr = a.getIndex(i);               //获取位置为i的节点的attr

                            String str= a.getString(attr);        //获取attr设置的字符串的值

                            int color=a.getColor(attr, Color.YELLOW);  //获取attr中设置的颜色,第二个参数是默认颜色,防止未设置时出现错误(可以随意设置颜色)

                         int a a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(//设定默认字体大小,并返回
                                          TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));

                               获取后,务必进行:a.recycle();  //释放资源

       当然也可以为自定义的view设置监听事件:

例如:

this.setOnClickListener(new OnClickListener()
  {

   @Override
   public void onClick(View v)
   {
    mTitleText = randomText();
    postInvalidate();                             //重绘
   }

  });


                        


     2.2:重写protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec):按需求对控件进行测量,并设置宽高


一个测量的例子:

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

  int width = 0;
  int height = 0;

  /**
   * 设置宽度
   */
  int specMode = MeasureSpec.getMode(widthMeasureSpec);   //获取宽设置的模式
  int specSize = MeasureSpec.getSize(widthMeasureSpec);    //获取宽尺寸
  switch (specMode)
  {
  case MeasureSpec.EXACTLY:// 明确指定了
   width = getPaddingLeft() + getPaddingRight() + specSize;  //宽为外边距加尺寸
   break;
  case MeasureSpec.AT_MOST:// 一般为WARP_CONTENT
   width = getPaddingLeft() + getPaddingRight() + mBound.width();
   break;
  }

  /**
   * 设置高度
   */
  specMode = MeasureSpec.getMode(heightMeasureSpec);
  specSize = MeasureSpec.getSize(heightMeasureSpec);
  switch (specMode)
  {
  case MeasureSpec.EXACTLY:// 明确指定了
   height = getPaddingTop() + getPaddingBottom() + specSize;
   break;
  case MeasureSpec.AT_MOST:// 一般为WARP_CONTENT
   height = getPaddingTop() + getPaddingBottom() + mBound.height();
   break;
  }

  setMeasuredDimension(width, height);  //设置宽高

 }


     2.3:重写onDraw(Canvas canvas):进行绘制

重绘的话,无非就是画笔,画布,矩阵,其他类型的矩阵之类的:

mPaint = new Paint();          //画笔
  mPaint.setTextSize(mTitleTextSize);       //设置画笔写字的大小
  // mPaint.setColor(mTitleTextColor);
  mBound = new Rect();       //矩阵
  mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);//获取文字占据的区域


重写onDraw(Canvas canvas)例子

@Override
 protected void onDraw(Canvas canvas)
 {
  //mPaint.setColor(Color.YELLOW);
  //canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);

  mPaint.setColor(mTitleTextColor);  
  canvas.drawText(mTitleText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);
 }


完整的例子: 例子来自鸿洋大神的

材料:一个设置属性的attr.xml

          一张包含了自定义的布局:activity_main.xml

        一个继承了view类的自定义类:CustomTitleView

       一个Activity:MainActivity


attr.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <attr name="titleText" format="string" />                   <!--定义属性为字符串-->
    <attr name="titleTextColor" format="color" />                 <!-- 定义属性为颜色 -->
    <attr name="titleTextSize" format="dimension" />             <!-- 定义属性为字体大小 -->

    <declare-styleable name="CustomTitleView">            <!-- 声明属性 -->
        <attr name="titleText" />
        <attr name="titleTextColor" />
        <attr name="titleTextSize" />
    </declare-styleable>

</resources>


<!-- format还可以指定其他的类型比如;

reference   表示引用,参考某一资源ID

string   表示字符串

color   表示颜色值

dimension   表示尺寸值

boolean   表示布尔值

integer   表示整型值

float   表示浮点值

fraction   表示百分数

enum   表示枚举值

flag   表示位运算 -->


2.activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:custom="http://schemas.android.com/apk/res/com.example.customview01"                                <!--引入此句,设置自定义属性时便可以用custom:属性:属性值-,com.example.customview01是view类包名字-->
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.example.customview01.view.CustomTitleView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        custom:titleText="3712"
        android:padding="10dp"
        custom:titleTextColor="#ff0000"
        android:layout_centerInParent="true"
        custom:titleTextSize="40sp" />

</RelativeLayout>

3.CustomTitle.java

public class CustomTitleView extends View
{
 /**
  * 文本
  */
 private String mTitleText;
 /**
  * 文本的颜色
  */
 private int mTitleTextColor;
 /**
  * 文本的大小
  */
 private int mTitleTextSize;

 /**
  * 绘制时控制文本绘制的范围
  */
 private Rect mBound;
 private Paint mPaint;

 public CustomTitleView(Context context, AttributeSet attrs)
 {
  this(context, attrs, 0);
 }

 public CustomTitleView(Context context)
 {
  this(context, null);
 }

 /**
  * 获得我自定义的样式属性
  *
  * @param context
  * @param attrs
  * @param defStyle
  */
 public CustomTitleView(Context context, AttributeSet attrs, int defStyle)
 {
  super(context, attrs, defStyle);
  /**
   * 获得我们所定义的自定义样式属性
   */
  TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomTitleView, defStyle, 0); //从attr.xml中获取sttleable下的节点
  int n = a.getIndexCount();
  for (int i = 0; i < n; i++)
  {
   int attr = a.getIndex(i);        //获取该attr
   switch (attr)
   {
   case R.styleable.CustomTitleView_titleText:
    mTitleText = a.getString(attr);    //返回字符串属性
    break;
   case R.styleable.CustomTitleView_titleTextColor:
    // 默认颜色设置为黑色
    mTitleTextColor = a.getColor(attr, Color.YELLOW);  //设定默认颜色,并返回标签
    break;
   case R.styleable.CustomTitleView_titleTextSize:
    // 默认设置为16sp,TypeValue也可以把sp转化为px
    mTitleTextSize = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(//设定默认字体大小,并返回
      TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
    break;

   }

  }
  a.recycle();  //释放资源

  /**
   * 获得绘制文本的宽和高
   */
  mPaint = new Paint();          //画笔
  mPaint.setTextSize(mTitleTextSize);       //设置画笔写字的大小
  // mPaint.setColor(mTitleTextColor);
  mBound = new Rect();
  mPaint.getTextBounds(mTitleText, 0, mTitleText.length(), mBound);//获取文字占据的区域

  this.setOnClickListener(new OnClickListener()
  {

   @Override
   public void onClick(View v)
   {
    mTitleText = randomText();
    postInvalidate();
   }

  });

 }
 private String randomText()  //随机产生四位数字
 {
  Random random = new Random();
  Set<Integer> set = new HashSet<Integer>();
  while (set.size() < 4)
  {
   int randomInt = random.nextInt(10);
   set.add(randomInt);
  }
  StringBuffer sb = new StringBuffer();
  for (Integer i : set)
  {
   sb.append("" + i);
  }

  return sb.toString();
 }

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

  int width = 0;
  int height = 0;

  /**
   * 设置宽度
   */
  int specMode = MeasureSpec.getMode(widthMeasureSpec);   //获取宽设置的模式
  int specSize = MeasureSpec.getSize(widthMeasureSpec);    //获取宽尺寸
  switch (specMode)
  {
  case MeasureSpec.EXACTLY:// 明确指定了
   width = getPaddingLeft() + getPaddingRight() + specSize;  //宽为外边距加尺寸
   break;
  case MeasureSpec.AT_MOST:// 一般为WARP_CONTENT
   width = getPaddingLeft() + getPaddingRight() + mBound.width();
   break;
  }

  /**
   * 设置高度
   */
  specMode = MeasureSpec.getMode(heightMeasureSpec);
  specSize = MeasureSpec.getSize(heightMeasureSpec);
  switch (specMode)
  {
  case MeasureSpec.EXACTLY:// 明确指定了
   height = getPaddingTop() + getPaddingBottom() + specSize;
   break;
  case MeasureSpec.AT_MOST:// 一般为WARP_CONTENT
   height = getPaddingTop() + getPaddingBottom() + mBound.height();
   break;
  }

  setMeasuredDimension(width, height);  //设置宽高

 }

 @Override
 protected void onDraw(Canvas canvas)
 {
  mPaint.setColor(Color.YELLOW);
  canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint);

  mPaint.setColor(mTitleTextColor);  
  canvas.drawText(mTitleText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);
 }
}


4.MainActivity:

public class MainActivity extends Activity
{

 @Override
 protected void onCreate(Bundle savedInstanceState)
 {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
 }


}


例子完成,view第一篇











0 0
原创粉丝点击