**view绘制**html
ViewGroup做为 父控件,可包含多个View控件,造成控件树java
上层控件负责下层子控件的测量与绘制,并传递交互事件canvas
```onMeasure()-MeasureSpec类```架构
1)测量模式:EXACTLY(精确值)ide
AT_MOST (最大值)布局
UNSPECIFIED (不指定,在自定义view中使用)this
自定义则必须重写onMeasure()方法spa
```~ ... onMeasure(~ ,~ ){ setMeasuredDimension( measureWidth(widthMS),measureHeight(~); } //参数是MeasureSpec的测量宽度、自定义的宽度方法 ~ ..int measureWidth(int measureSpec){ int result=0; int specMode=MS.getMode(mS); int SpecSize=MS.getSize(mS); if(sM==MS.EXACTLY){ result=specSize; } else{ result=200; //当不是EXACTLY模式,则须要给默认值if(specMode==MS.AT_MOST){result=Math.min(result,specSize); //如果AT_MOST模式,则要取出个人指定的大小与SpecSize中最小的} } return result; }
重写onDraw()方法,在Canvas对象上绘制所需对象(在其余地方一般须要建立Canvas canvas=new Canvas(bitmap) ; )设计
管理子View(显示大小)code
**· 当VG为wrap_content,须要对子View遍历,得到全部子View大小,从而决定本身的大小**
**·在其余模式,则经过具体的指定值来设置自身的大小**
1)VG在测量时经过遍历全部子View,从而调用子View的Measure方法来得到每个子View的测量结果
2)子View测量后,View的Layout方法设定其放置位置
3)VG执行layout过程时,遍历调用子View的Layout方法,指定其具体显示的位置,决定其布局位置(在自定义VG时,重写onLayout()方法控制子View显示位置,若须要支持wrap_content,必须重写onMeasure() )
指定VG背景颜色,必须调用onDraw()方法,调用dispatchDraw()绘制子View
比较重要的回调方法(根据实际须要)
onFinishInflate( ):从XML加载组件后回调
onSizeChanged():组件大小改变时回调
onMeasure():回调该方法进行测量 onLayout():回调肯定显示的位置
onTouchEvent():监听到触摸时间时回调
**实现自定义控件方法**
1)对现有控件拓展
2)经过组合实现新控件
3)重写View实现全新控件
//初始化画笔 Paint mPaint=new Paint(); mPaint.setColor(getResources().getColor(~ .blue)); mPaint.setStyle(Paint.Style.FILL); ~...onDraw( ){ //在回调法雷方法前,实现本身的逻辑,对TextView来讲,就是在绘制文本内容前 super.onDraw(); //在 ...后,则在 ... 后 }
(1)定义属性
//在res-values下建立attrs.xml的属性定义文件 <resource> <declare-styleablename="Topbar"> <attr name ="title" format="string" /> <attrname="leftBackground"format="color|reference"/> </> </>……
(2)建立控件继承VG`
//获取自定义属性 TypedArray ta=context.obtainStyledAttributes(attrs,.styleable.Topbar); mLeftTextColor=ta.getColor(R.~~.Topbar_leftTextColor, 0); ta.recycle( ); //获取完 要释放
//动态添加控件--addView ,添加到定义的Topbar中,设置属性值 mLeftButton=new Button(context); mTitleView=new TextView(~); …… mLeftButton.setTextColor(mLeftTextColor); …… //为组件元素设置相应的布局元素 mLeftParams=new LayoutParams(L~P~.WRAP_CONTENT,L~P~.M~P~); mLeftParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT,TRUE); //添加到VG addView(mLeftButton ,mLeftParams);
public interface topbarClickListener{ void leftClick(); void rightClick(); }
public class Topbar extends RelativeLayout { //设置自定义控件的父类布局的参数 private LayoutParams titleParams_lp; private LayoutParams leftParams_lp; private LayoutParams rightParams_lp; //自定义的属性 private String title_txt; private int title_color; private float titleTextSize; private String left_txt; private int leftText_color; private Drawable leftBackground; private String right_txt; private int rightText_color; private Drawable rightBackground; //自定义的控件 private Button left_btn,right_btn; //左右按钮 private TextView title_tv; //标题 private topbarClickListener listener; //自定义的接口实例对象 //自定义接口 public interface topbarClickListener{ public void leftClick(); public void rightClick(); //抽象点击方法 } //自定义的点击方法---将回调回来的匿名内部类参数给系统的ClickListener() public void setOnTopbarClickListener(topbarClickListener listener){//传来一个参数--接口的对象 this.listener=listener; } public Topbar(Context context, AttributeSet attrs) { super(context, attrs); TypedArray ta=context.obtainStyledAttributes(attrs,R.styleable.Topbar); //将自定义的属性从中获取出来 title_txt=ta.getString(R.styleable.Topbar_title); title_color=ta.getColor(R.styleable.Topbar_titleColor,0); titleTextSize=ta.getDimension(R.styleable.Topbar_titleTextSize,0); left_txt=ta.getString(R.styleable.Topbar_leftText); leftText_color=ta.getColor(R.styleable.Topbar_leftTextColor,0); leftBackground=ta.getDrawable(R.styleable.Topbar_leftBackground); right_txt=ta.getString(R.styleable.Topbar_rightText); rightText_color=ta.getColor(R.styleable.Topbar_rightTextColor,0); rightBackground=ta.getDrawable(R.styleable.Topbar_rightBackground); ta.recycle(); //回收 //实例化控件 title_tv=new TextView(context); left_btn=new Button(context); right_btn=new Button(context); //将控件与自定义的属性关联 title_tv.setText(title_txt); title_tv.setTextColor(title_color); title_tv.setTextSize(titleTextSize); title_tv.setGravity(Gravity.CENTER); //直接设定居中对齐 left_btn.setText(left_txt); left_btn.setTextColor(leftText_color); left_btn.setBackground(leftBackground); right_btn.setText(right_txt); right_btn.setTextColor(rightText_color); right_btn.setBackground(rightBackground); setBackgroundResource(R.color.colorWhite); /**自定义控件的父类布局参数*/ titleParams_lp=new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); //布局宽 高、 对齐方式 titleParams_lp.addRule(RelativeLayout.CENTER_IN_PARENT); //左边布局自适应,居左对齐 leftParams_lp=new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); leftParams_lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT); rightParams_lp=new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); rightParams_lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); /**将自定义的控件放进父布局中---也就是设定它们的布局位置 */ addView(title_tv,titleParams_lp); addView(left_btn,leftParams_lp); addView(right_btn,rightParams_lp); /**自定义的点击事件------利用回调机制----------------*/ left_btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { listener.leftClick(); //此时将传回来的点击事件(经过 匿名内部类参数)传递给left_btn的监听接口 } }); right_btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { listener.rightClick(); } }); } } public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Topbar topbar= (Topbar) findViewById(R.id.tb_title); topbar.setOnTopbarClickListener(new Topbar.topbarClickListener() { @Override public void leftClick() { Toast.makeText(MainActivity.this,"我是back",Toast.LENGTH_SHORT).show(); } @Override public void rightClick() { Toast.makeText(MainActivity.this,"我是go",Toast.LENGTH_SHORT).show(); } }); } }