重点:
三步:测量排版。。。。。
回调函数
###创建自定义按钮传递背景和按钮给自定义控件
1.创建自定义按钮
cn.itcast.togglebutton.MyToggleButton.java
public class MyToggleButton extends View {
public MyToggleButton(Context context) {
//super(context);
this(context,null);
}
public MyToggleButton(Context context, AttributeSet attrs) {
//super(context, attrs);
this(context,attrs,0);
}
public MyToggleButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
}
2.布局文件中使用
activity_main.xml
<!-- 位置是中间的位置 -->
<cn.itcast.togglebutton.MyToggleButton
android:id="@+id/mytogglebutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
></cn.itcast.togglebutton.MyToggleButton>
3.将背景和按钮传递给自定义按钮显示
3.1.自定义控件创建接受图片的方法
cn.itcast.togglebutton.MyToggleButton.java
/**
* 接受传递过来的背景和按钮图片
*/
public void setBackgroundAndIcon(int backgroundid,int iconid){
//根据id获取图片
background = BitmapFactory.decodeResource(getResources(), backgroundid);
icon = BitmapFactory.decodeResource(getResources(), iconid);
}
3.2.在Activity中调用方法传递图片
cn.itcast.togglebutton.MainActivity.java
/**
*
* @Description:初始化控件
*/
private void initView() {
myToggleButton = (MyToggleButton) findViewById(R.id.mytogglebutton);
myToggleButton.setBackgroundAndIcon(R.drawable.slide_background, R.drawable.slide_icon);
}
###显示控件操作 (重点)
cn.itcast.togglebutton.MyToggleButton.java
//2.显示操作
//Android系统中控件绘制显示的流程:1.测量控件的宽高;2.排版(设置控件的显示位置);3.绘制显示控件
//第一步完成,才会执行第二步,第二步完成,才会执行第三步,第三步完成,才能看到控件,才能控件的属性
//如果activity的oncreate方法没有执行完,看不到控件,无法获取控件的宽高,结论:在oncreate方法中是无法获取控件的宽高的
//1.测量控件的宽高
//widthMeasureSpec : 控件的宽
//heightMeasureSpec : 控件的高
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
//super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//根据背景图片的宽高绘制控件的宽高
setMeasuredDimension(background.getWidth(), background.getHeight());
}
//2.排版(设置控件的显示位置)
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
// TODO Auto-generated method stub
super.onLayout(changed, left, top, right, bottom);
}
//3.绘制显示控件
@Override
protected void onDraw(Canvas canvas) {
//绘制背景
//left : 在x轴的哪个位置绘制
//top : 在y轴的哪个位置绘制,以自定义控件的圆心坐标的来算
//null:因为使用的是图片,形状,颜色都已经有了,不需要画笔来画了
canvas.drawBitmap(background, 0, 0, null);
//绘制按钮
canvas.drawBitmap(icon, 0, 0, null);
super.onDraw(canvas);
}
###滑动的所有操作
cn.itcast.togglebutton.MyToggleButton.java的OnTouchEvent事件
1.滑动操作
/**
* 自定义控件的触摸事件
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//移动的位置 = 按住的坐标的x - 按钮图片的宽度/2
lefticon = (int) (event.getX() - icon.getWidth()/2);
break;
case MotionEvent.ACTION_MOVE:
//移动的位置 = 按住的坐标的x - 按钮图片的宽度/2
lefticon = (int) (event.getX() - icon.getWidth()/2);
break;
case MotionEvent.ACTION_UP:
break;
}
//获取到移动的新的位置之后,让按钮在新的位置重新绘制就行了
//onDraw(canvas);//不能直接调用onDraw
invalidate();//间接调用ondraw
//返回true执行事件,false:拦截事件
return true;
}
// 3.绘制显示控件
@Override
protected void onDraw(Canvas canvas) {
......
// 绘制按钮
canvas.drawBitmap(icon, lefticon, 0, null);
super.onDraw(canvas);
}
2.滑动范围
// 3.绘制显示控件
@Override
protected void onDraw(Canvas canvas) {
......
//控制滑动的范围
if (lefticon < 0) {
lefticon = 0;
}else if(lefticon > maxLeft){
lefticon = maxLeft;
}
// 绘制按钮
canvas.drawBitmap(icon, lefticon, 0, null);
super.onDraw(canvas);
}
3.自动滑动的操作
在onTouchEvent的up事件中
case MotionEvent.ACTION_UP:
//自动滑动的操作
//判断按住的坐标和背景宽度的一半比较
if (event.getX() < background.getWidth()/2) {
lefticon=0;
}else{
lefticon = maxLeft;
}
break;
###回调函数 (重点)
cn.itcast.togglebutton.MyToggleButton.java
1.在自定义控件中创建回调函数
//监听按钮的开关状态了
//回调监听了,监听器
//3.创建保存监听器实现对象的变量
private OnToggleOnLisenter onToggleOnLisenter;
//2.创建获取监听的实现对象的方法
public void setOnToggleOnListener(OnToggleOnLisenter onToggleOnLisenter){
this.onToggleOnLisenter = onToggleOnLisenter;
}
//1.创建监听器
public interface OnToggleOnLisenter{
//监听控件是否开关的操作
public void onToggleOn(boolean isToggle);
}
2.调用操作
在Activity中
myToggleButton.setOnToggleOnListener(new OnToggleOnLisenter() {
@Override
public void onToggleOn(boolean isToggle) {
}
});
###回调监听的使用 (重点)
1.在自定义控件的ondraw方法中将开关状态,保存到回调接口的方法中
cn.itcast.togglebutton.MyToggleButton的onDraw
// 3.绘制显示控件
@Override
protected void onDraw(Canvas canvas) {
..........
//绘制完成,将开关状态保存到接口的方法中,方便activity使用
//1.必须抬起手指
//2.获取开关状态,设置给接口方法
boolean istoggle = lefticon > 0;
if (isHandUp) {
//2.获取开关状态,设置给接口方法
if (onToggleOnLisenter != null) {
onToggleOnLisenter.onToggleOn(istoggle);
}
//将是否抬起手指的操作设置为false,为下一次抬起手指做准备
isHandUp = false;
}
// 绘制按钮
canvas.drawBitmap(icon, lefticon, 0, null);
super.onDraw(canvas);
}
2.在Activity中的使用传递的参数
cn.itcast.togglebutton.MainActivity的initview方法中
private void initView() {
......
myToggleButton.setOnToggleOnListener(new OnToggleOnLisenter() {
@Override
public void onToggleOn(boolean isToggle) {
Toast.makeText(getApplicationContext(), isToggle ? "开启" : "关闭", 0).show();
}
});
}
###手动开启关闭按钮的操作
1.在自定义控件中创建手动开启关闭的方法
cn.itcast.togglebutton.MyToggleButton.java
/**
*
* @Description:手动开启关闭按钮
* @param
*
isOpen:开关的状态
*/
public void setSate(boolean isOpen){
//为了使用回调弹出toast
isHandUp = true;
if (isOpen) {
lefticon = maxLeft;
}else{
lefticon = 0;
}
//重新绘制控件
invalidate();
}
2.在MainActivity中调用
cn.itcast.togglebutton.MainActivity的initview方法中
private void initView() {
......
myToggleButton.setSate(true);
}
###自定义属性
1.创建自定义属性
res -> values-> attrs.xml
<resources>
<declare-styleable name="MyToggleButton">
<!-- 背景 -->
<attr name="backgroundid" format="reference" /> <!-- reference : 图片 -->
<!-- 按钮 -->
<attr name="iconid" format="reference" />
<!-- 开关状态 -->
<attr name="istoggle" format="boolean" />
</declare-styleable>
</resources>
2.在布局文件中使用自定义属性
xmlns:itcast="http://schemas.android.com/apk/res/cn.itcast.togglebutton"
<!-- 位置是中间的位置 -->
<cn.itcast.togglebutton.MyToggleButton
android:id="@+id/mytogglebutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
itcast:backgroundid="@drawable/slide_background2"
itcast:iconid="@drawable/slide_icon2"
itcast:istoggle="false"
></cn.itcast.togglebutton.MyToggleButton>
3.在定义控件中获取属性的值,并设置
public MyToggleButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
//获取控件的自定义属性的值,设置给自定义控件
int backgroundId = attrs.getAttributeResourceValue(NAMESPACE, "backgroundid", -1);
int iconid = attrs.getAttributeResourceValue(NAMESPACE, "iconid", -1);
boolean b = attrs.getAttributeBooleanValue(NAMESPACE, "istoggle", true);
//设置属性的值给自定义控件
if (backgroundId != -1 && iconid != -1) {
setBackgroundAndIcon(backgroundId, iconid);
}
//设置开关状态
setSate(b);
}