**view绘制**
1、控件架构
ViewGroup作为 父控件,可包含多个View控件,形成控件树
上层控件负责下层子控件的测量与绘制,并传递交互事件
2、View的测量---绘制前提
```onMeasure()-MeasureSpec类```
1)测量模式:EXACTLY(精确值)
AT_MOST (最大值)
UNSPECIFIED (不指定,在自定义view中使用)
自定义则必须重写onMeasure()方法
```~ ... 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;
}
3、View的绘制
重写onDraw()方法,在Canvas对象上绘制所需对象(在其他地方通常需要创建Canvas canvas=new Canvas(bitmap) ; )
4、ViewGroup的测量
管理子View(显示大小)
**· 当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() )
5、VG绘制
指定VG背景颜色,必须调用onDraw()方法,调用dispatchDraw()绘制子View
6、自定义View
比较重要的回调方法(根据实际需要)
onFinishInflate( ):从XML加载组件后回调
onSizeChanged():组件大小改变时回调
onMeasure():回调该方法进行测量 onLayout():回调确定显示的位置
onTouchEvent():监听到触摸时间时回调
**实现自定义控件方法**
1)对现有控件拓展
2)通过组合实现新控件
3)重写View实现全新控件
*1、对现有控件进行拓展--可在onDraw()中实现*
//初始化画笔
Paint mPaint=new Paint();
mPaint.setColor(getResources().getColor(~ .blue));
mPaint.setStyle(Paint.Style.FILL);
~...onDraw( ){ //在回调法雷方法前,实现自己的逻辑,对TextView来说,就是在绘制文本内容前
super.onDraw(); //在 ...后,则在 ... 后 }
2、复合控件--组合
(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();
}
});
}
}