安卓自定义view全解:初始化,onDraw函数,onMeasure函数,用户手势事件

安卓自定义View详解
本文详细介绍了安卓自定义View的实现方法,包括如何重写View基类中的关键函数如onDraw、onMeasure等来实现自定义绘图效果,并通过实例展示了如何响应用户交互事件。

全栈工程师开发手册 (作者:栾鹏)

安卓教程全解

安卓自定义view全解。

view类包含如下函数。可供重写。

onFinishInflate() 回调方法,当应用从XML加载该组件并用它构建界面之后调用的方法
onMeasure() 检测View组件及其子组件的大小
onLayout() 当该组件需要分配其子组件的位置、大小时
onSizeChange() 当该组件的大小被改变时
onDraw() 当组件将要绘制它的内容时
onKeyDown 当按下某个键盘时
onKeyUp 当松开某个键盘时
onTrackballEvent 当发生轨迹球事件时
onTouchEvent 当发生触屏事件时
onWindowFocusChanged(boolean) 当该组件得到、失去焦点时
onAtrrachedToWindow() 当把该组件放入到某个窗口时
onDetachedFromWindow() 当把该组件从某个窗口上分离时触发的方法
onWindowVisibilityChanged(int): 当包含该组件的窗口的可见性发生改变时触发的方法

安卓自定义view

在本文的示例中,我们使用view基类的基本函数进行了属性设置,在onDraw函数中使用Canvas进行绘图,在onMeasure函数中调整控件大小,并且重写了onKeyDown、onKeyUp、onTrackballEvent、onTouchEvent函数监听用户事件。

public class UI_View extends View {  
	
	  // 使用代码创建时必须的构造函数
	  public UI_View(Context context) {
	    super(context);
	    init();
	  }

	  //使用资源文件进行填充时必须的构造函数
	  public UI_View (Context context, AttributeSet attrs) {
	    super(context, attrs);
	    init();
	  }
	  
	  // 使用资源文件进行填充时必须的构造函数
	  public UI_View (Context context, AttributeSet ats, int defaultStyle) {
	    super(context,ats,defaultStyle);
	    init();
	  }
	  
	  //进行控件初始化
	  private void init(){
		  this.setBackgroundColor(Color.GREEN);   //设置背景颜色
		  this.setX(100);   //设置x
		  //...还有一大堆自己控制
	  }
	  
	  //绘制自定义控件
	  @Override
	  protected void onDraw(Canvas canvas) {
	    // 在上次对onMeasure方法调用的基础上获得控件的大小
	    int height = getMeasuredHeight();
	    int width = getMeasuredWidth();

	    //找出控件的中心
	    int px = width/2;
	    int py = height/2;

	    // 创建新的画刷,注意:由于效率的原因,这项工作应该在视图的构造函数中完成
	    Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
	    mTextPaint.setColor(Color.RED);    //设置文字颜色
	    mTextPaint.setTextSize(40);       //设置文字大小
	    mTextPaint.setStrokeWidth(3);     //设置线宽   
	    mTextPaint.setTextAlign(Align.LEFT);  //设置对齐方式
	    //定义字符串
	    String displayText = "Hello World!";

	    //计算文本字符串的宽度
	    float textWidth = mTextPaint.measureText(displayText);

	    //在控件的中心绘制文本字符串
	    canvas.drawText(displayText, px-textWidth/2, py, mTextPaint);
	    Log.v("自定义view", "绘制控件");
	  }
	  
	 
	  //onMeasure用来调整控件大小,默认为100*100
	  @Override
	  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
	    int measuredHeight = measureHeight(heightMeasureSpec);
	    int measuredWidth = measureWidth(widthMeasureSpec);
	    //必须调用setMeasuredDimension,否则在布局控件的时候会造成运行时异常
	    setMeasuredDimension(measuredHeight, measuredWidth);
	    Log.v("自定义view", "调整大小");
	  }

	  private int measureHeight(int measureSpec) {
	    int specMode = MeasureSpec.getMode(measureSpec);
	    int specSize = MeasureSpec.getSize(measureSpec);

	    //  如果不指定限制,就是默认大小
	    int result = 200;

	    if (specMode == MeasureSpec.AT_MOST) {
	      //计算控件在这个最大尺寸范围内的理想大小,如果控件填充了可用空间,则返回外边界
	      result = specSize;
	    } else if (specMode == MeasureSpec.EXACTLY) {
	      // 如果控件可以放置在这个边界内,则返回该值
	      result = specSize;
	    }
	    return result;
	  }

	  private int measureWidth(int measureSpec) {
	    int specMode = MeasureSpec.getMode(measureSpec);
	    int specSize = MeasureSpec.getSize(measureSpec);

	    //如果不指定限制,就是默认的大小
	    int result = 200;

	    if (specMode == MeasureSpec.AT_MOST) {
	      // 计算控件在这个最大的尺寸范围内的理想大小,如果控件填充了可用的空间,那么返回外边界
	      result = specSize;
	    } else if (specMode == MeasureSpec.EXACTLY) {
	      // 如果控件可以放置在这个边界内,则返回该值
	      result = specSize;
	    }
	    return result;
	  }
	  
	  //用户交互事件
	  @Override
	  public boolean onKeyDown(int keyCode, KeyEvent keyEvent) {
		  //如果事件得到处理,返回true
		  Log.v("自定义view", "按键按下");
		  return true;
	  }

	  @Override
	  public boolean onKeyUp(int keyCode, KeyEvent keyEvent) {
		  //如果事件得到处理,返回true
		  Log.v("自定义view", "按键弹起");
		  return true;
	  }

	  @Override
	  public boolean onTrackballEvent(MotionEvent event ) {
	    // 获得这个事件代表的动作类型
	    int actionPerformed = event.getAction();
	    Log.v("自定义view", event.toString());
	    // 如果事件得到处理,返回true
	    return true;
	  }

	  @Override
	  public boolean onTouchEvent(MotionEvent event) {
	    // 获得这个事件代表的动作类型
	    int actionPerformed = event.getAction();
	    Log.v("自定义view", event.toString());
	    // 如果事件得到处理,返回true
	    return true;
	  }

}

将我们自定义的view添加到窗口中有两种方式

1、在activity中将自定义view添加到窗口中

LinearLayout linearLayout = (LinearLayout)findViewById(R.id.activity1_linearlayout1);
UI_View myview = new UI_View(this);
linearLayout.addView(myview);

2、在xml布局文件中添加

在xml中添加也可以设置view的基本属性。不过在view显示时还是会调用onMeasure函数中设置的控件大小。

<?xml version="1.0" encoding="utf-8"?>
<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:id="@+id/activity1_linearlayout1"
    android:orientation="vertical">
    
    <com.lp.app.ui.UI_View 
        android:id="@+id/activity1_ui_view1"
        android:layout_width="match_parent"
        android:layout_height="100px"
        />
	
</LinearLayout>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

腾讯AI架构师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值