关于安卓view中draw()方法的调用问题
2016-09-10 16:10
330 查看
首先来简单叙述一下安卓view的大致工作过程:
第一步:当activity启动的时候,触发初始化view过程的是由Window对象的DecorView调用View(具体怎样从xml中读取是用LayoutInflater.from(context).inflate)对象的 public final void measure(int widthMeasureSpec, int heightMeasureSpec)方法开始的,这个方法是final类型的,也就是所有的子类都不能继承该方法,保证android初始化view的原理不变。具体参数类值,后面会介绍。
第二步:View的measure方法 onMeasure(widthMeasureSpec, heightMeasureSpec),该方法进行实质性的view大小计算。注意:view的大小是有父view和自己的大小决定的,而不是单一决定的。这也就是为什么ViewGroup的子类会重新该方法,比如LinearLayout等。因为他们要计算自己和子view的大小。View基类有自己的实现,只是设置大小。其实根据源码来看,measure的过程本质上就是把Match_parent和wrap_content转换为实际大小
第三步:当measure结束时,回到DecorView,计算大小计算好了,那么就开始布局了,开始调用view的 public final void layout(int l, int t, int r, int b),该还是也是final类型的,目的和measure方法一样。layout方法内部会调用onlayout(int l, int t, int r, int b )方法,二ViewGroup将此方法abstract的了,所以我们继承ViewGroup的时候,需要重新该方法。该方法的本质是通过measure计算好的大小,计算出view在屏幕上的坐标点
第四步:measure过了,layout过了,那么就要开始绘制到屏幕上了,所以开始调用view的 public void draw(Canvas canvas)方法,此时方法不是final了,原因是程序员可以自己画,内部会调用ondraw,我们经常需要重写的方法。
好了,知道了大致工作原理,我们来谈谈draw()调用的一个细节问题:
我在下面的代码中用layout()方法来自定义view的位置及大小时,发现调用了layout()方法后,该view的draw()方法也被调用了,代码和图片如下:
这是mainactivity:
package com.ljcCustomViewDemo.customview;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
CustomView customview;
TextView textview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textview=(TextView) findViewById(R.id.textview);
customview=(CustomView) findViewById(R.id.customview1);
//通过点击事件,调整customview的大小
customview.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
customview.layout(0, 0, 120, 100);
}
});
}
到这里发现,我调用了layout()方法,接着draw()方法也调用了,这是为什么呢?经过笔者的研究,是因为控件尺寸和位置发生了变化。layout()方法中,若尺寸或位置发生变化,则setFrame()方法就会返回false,这时Decorview,就会调用draw()方法。
下面,我把layout()方法,中的参数改为和view初始值一样的参数(0,0,100,100),则不会调用draw()方法
customview.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
customview.layout(0, 0, 120, 100);
}
});
}
第一步:当activity启动的时候,触发初始化view过程的是由Window对象的DecorView调用View(具体怎样从xml中读取是用LayoutInflater.from(context).inflate)对象的 public final void measure(int widthMeasureSpec, int heightMeasureSpec)方法开始的,这个方法是final类型的,也就是所有的子类都不能继承该方法,保证android初始化view的原理不变。具体参数类值,后面会介绍。
第二步:View的measure方法 onMeasure(widthMeasureSpec, heightMeasureSpec),该方法进行实质性的view大小计算。注意:view的大小是有父view和自己的大小决定的,而不是单一决定的。这也就是为什么ViewGroup的子类会重新该方法,比如LinearLayout等。因为他们要计算自己和子view的大小。View基类有自己的实现,只是设置大小。其实根据源码来看,measure的过程本质上就是把Match_parent和wrap_content转换为实际大小
第三步:当measure结束时,回到DecorView,计算大小计算好了,那么就开始布局了,开始调用view的 public final void layout(int l, int t, int r, int b),该还是也是final类型的,目的和measure方法一样。layout方法内部会调用onlayout(int l, int t, int r, int b )方法,二ViewGroup将此方法abstract的了,所以我们继承ViewGroup的时候,需要重新该方法。该方法的本质是通过measure计算好的大小,计算出view在屏幕上的坐标点
第四步:measure过了,layout过了,那么就要开始绘制到屏幕上了,所以开始调用view的 public void draw(Canvas canvas)方法,此时方法不是final了,原因是程序员可以自己画,内部会调用ondraw,我们经常需要重写的方法。
好了,知道了大致工作原理,我们来谈谈draw()调用的一个细节问题:
我在下面的代码中用layout()方法来自定义view的位置及大小时,发现调用了layout()方法后,该view的draw()方法也被调用了,代码和图片如下:
这是mainactivity:
package com.ljcCustomViewDemo.customview;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
CustomView customview;
TextView textview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textview=(TextView) findViewById(R.id.textview);
customview=(CustomView) findViewById(R.id.customview1);
//通过点击事件,调整customview的大小
customview.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
customview.layout(0, 0, 120, 100);
}
});
}
到这里发现,我调用了layout()方法,接着draw()方法也调用了,这是为什么呢?经过笔者的研究,是因为控件尺寸和位置发生了变化。layout()方法中,若尺寸或位置发生变化,则setFrame()方法就会返回false,这时Decorview,就会调用draw()方法。
下面,我把layout()方法,中的参数改为和view初始值一样的参数(0,0,100,100),则不会调用draw()方法
customview.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
customview.layout(0, 0, 120, 100);
}
});
}
相关文章推荐
- 安卓开发_关于WebView使用链接时调用浏览器显示的问题
- 关于混淆打包后,webview 无法调用js方法 的问题
- 关于WebView的addJavascriptInterface方法的安卓版本问题
- 关于WebView的addJavascriptInterface方法的安卓版本问题
- JAVA关于方法调用的代码写法与性能问题
- 关于子类继承父类后调用方法的问题
- video标签在安卓webview下无法自动播放问题的解决方法
- 安卓初学者关于在setContentView(..)出现source not found 的问题
- 关于Asp.net的FormView控件中,用FindControl方法找不到对应控件问题
- ios 关于 通过加载 xib 生成的view,调用 addsubviews,sub view的按钮 不相应点击事件的 问题
- 关于asp.net前台js调用后台方法的问题
- 关于对话框OnPaint 不调用基类CDialog::OnPaint方法CPU消耗很大达到70%以上问题
- 关于调用不到方法的问题
- 【CLR-sos调试】关于方法表继承调用问题的总结
- 关于在manageBean中调用业务方法的问题
- 关于多态性的动态绑定问题, 对象调用方法的执行过程.
- 关于 WebWork 中Action 的prepare方法被调用多次的问题
- 关于 WebWork 中Action 的prepare方法调用多次的问题
- 最近在ArcGIS Engine开发中关于调用gp工具过程出现COM 组件的调用返回了错误 HRESULT E_FAIL 错误的解决方法 和 学习oracle中遇到的一些问题总结
- 安卓开发_关于WebView加载页面空白问题