您的位置:首页 > 移动开发 > Android开发

Android学习(43) -- 自定义控件(7) 滑动开关

2016-04-25 11:57 567 查看

简介

自定义控件步骤:

1. 写类继承View

2. 重写onDraw, 进行绘制

3. 重新onMeasure,修改尺寸 要使用 setMeasuredDimension设置当前自定义View的大小

4. 在xml布局文件中配置

可能需要重写的方法:

测量:onMeasure 设置自己显示在屏幕上的宽高 在重写这个方法时,必须调用setMeasuredDimension(int, int)来存储测量得到的宽度和高度值

布局:onLayout 设置自己显示在屏幕上的位置(只有在自定义ViewGroup中才用到) 需要调用各自的layout(int, int, int, int)方法

绘制:onDraw 控制显示在屏幕上的样子(自定义viewgroup时不需要这个)

View和ViewGroup的区别

1.他们都需要进行测量操作

2.ViewGroup主要是控制子view如何摆放,所以必须实现onLayout

View没有子view,所以不需要onLayout方法,但是必须实现onDraw

自定义控件实际操作:

1、创建类继承View

2、重写两个构造器

3、重写

onMeasure并调用setMeasuredDimension方法设置控件的宽和高

onDraw 绘制自己显示在屏幕上的样子

4、定义操作控件的方法

a、设置开关块的图片

b、设置开关背景的图片

c、设置更改开关状态的方法

5、定义onTouchEvent事件

6、定义接口对外开关状态

效果



定义View

1、创建类继承View

2、重写两个构造器

3、重写

onMeasure并调用setMeasuredDimension方法设置控件的宽和高

onDraw 绘制自己显示在屏幕上的样子

4、定义操作控件的方法

a、设置开关块的图片

b、设置开关背景的图片

c、设置更改开关状态的方法

public class MySwitch extends View {

private SwitchState sState; // 开关状态
private Bitmap slideBitmap;
private Bitmap switchBitmap;

/**
* 如果自定义的View只是在布局文件中使用,只需要重写这个构造方法
*
* @param context
* @param attrs
*/
public MySwitch(Context context, AttributeSet attrs) {
super(context, attrs);

}

/**
* 如果自定义的View是在Java代码中动态的new出来,需要重写这个构造方法
*
* @param context
*/
public MySwitch(Context context) {
super(context);
}

/**
* 设置活动块的图片
*/
public void setSlideBackgroudResource(int slideBackground) {
// 将资源文件转换为Bitmap
slideBitmap = BitmapFactory.decodeResource(getResources(),
slideBackground);
}

/**
* 设置switch的图片
*
* @param switchBackground
*/
public void setSwitchBackgroundResource(int switchBackground) {
// 将资源文件转换为Bitmap
switchBitmap = BitmapFactory.decodeResource(getResources(),
switchBackground);
}

/**
* Switch开关状态的枚举
*
* @author Denny
* @date 2016-4-25
*/
public enum SwitchState {
OPEN, CLOSE
}

/**
* 设置Switch开关状态
*
* @param open
*/
public void setSwitchState(SwitchState open) {
sState = open;
}

/**
* 设置当前控件在屏幕上的宽和高
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

// 设置当前View的大小 这个方法决定了当前View的大小
setMeasuredDimension(switchBitmap.getWidth(), switchBitmap.getHeight());
}

/**
* 绘制自己显示在屏幕上的样子
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 1.在某一个位置 绘制背景图片
// left:图片的左边的x坐标
// top:图片的顶部的y坐标
canvas.drawBitmap(switchBitmap, 0, 0, null);

// 2.绘制滑动块图片

//当抬起的时候 绘制滑动块的位置
// 根据SwitchState 确定滑动块的位置
// 如果滑动块在左边的话 left:0 top:0
// 如果滑动块在右边:left : 背景的宽 - 滑动块的宽 top:0
if (sState == SwitchState.OPEN) {
canvas.drawBitmap(slideBitmap, switchBitmap.getWidth()
- slideBitmap.getWidth(), 0, null);
} else if (sState == SwitchState.CLOSE) {
canvas.drawBitmap(slideBitmap, 0, 0, null);
}

}
}


5、定义onTouchEvent事件

1、Android中有两套坐标:



2、开关要有两种操作

a、根据滑动块 滑动 操作

b、根据滑动块 状态 操作

2.1定义成员

定义一个变量用于判断是根据滑动还是 根据状态进行 操作

private boolean isSliding = false;

定义一个变量 用于获取滑动位置的x点
private int currentX; // 当前触摸点的x坐标

2.2当onTouchEvent事件中处理 滑动块滑动 操作

a、在ACTION_DOWN中 isSliding 设置为 true; 表示要滑动
b、 当ACTION_UP事件中 判断 判断当前x值和中间线的大小 更改SwitchState :
如果大于等于 SwitchState 则设置为OPEN ,否则设置为CLOSE

不要忘记,调用invalidate()方法,请求重新draw()

@Override
public boolean onTouchEvent(MotionEvent event) {

// 获取当前的x点
currentX = (int) event.getX();

switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isSliding = true;
break;
case MotionEvent.ACTION_MOVE:

break;
case MotionEvent.ACTION_UP:
isSliding = false;
//获取中间线
int centernX = switchBitmap.getWidth() / 2;
//判断当前x值和中间线的大小  更改SwitchState
if( currentX >= centernX){
//open
if(sState != SwitchState.OPEN){
sState = SwitchState.OPEN;
}
}else{
//close
if(sState != SwitchState.CLOSE){
sState = SwitchState.CLOSE;
}
}

break;
}

// 调用invalidate()方法,请求重新draw()
invalidate();
return true;
}


2.3在onDraw中根据 isSliding来 根据 滑动还是 状态 来绘制
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 1.在某一个位置 绘制背景图片
// left:图片的左边的x坐标
// top:图片的顶部的y坐标
canvas.drawBitmap(switchBitmap, 0, 0, null);

// 2.绘制滑动块图片
//如果是滑动的话 则根据currentX来进行操作
if(isSliding ){

//当鼠标移动到slideBitmap一半的时候才会有响应
int left = currentX - slideBitmap.getWidth() / 2;
//如果left
if (left < 0) {
left = 0;
}
int maxX = switchBitmap.getWidth() - slideBitmap.getWidth();
if (left > (maxX)) {
left = maxX;
}
canvas.drawBitmap(slideBitmap, left, 0, null);
}else{
//当抬起的时候 绘制滑动块的位置
// 根据SwitchState 确定滑动块的位置
// 如果滑动块在左边的话 left:0 top:0
// 如果滑动块在右边:left : 背景的宽 - 滑动块的宽 top:0
if (sState == SwitchState.OPEN) {
canvas.drawBitmap(slideBitmap, switchBitmap.getWidth()
- slideBitmap.getWidth(), 0, null);
} else if (sState == SwitchState.CLOSE) {
canvas.drawBitmap(slideBitmap, 0, 0, null);
}
}

}




6、定义接口对外开关状态

a、定义接口对外开关状态的方法
b、定义根据接口来更改状态的方法

public interface OnSwitchStateChangedListern{
void onSwitchStateChenged(SwitchState state);
}

private OnSwitchStateChangedListern  listern;

public void setOnSwitchStateChangedListern(OnSwitchStateChangedListern listern) {
this.listern = listern;
}


c、将监听 添加到 滑动时候

public boolean onTouchEvent(MotionEvent event) {

// 获取当前的x点
currentX = (int) event.getX();

switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isSliding = true;
break;
case MotionEvent.ACTION_MOVE:

break;
case MotionEvent.ACTION_UP:
isSliding = false;
//获取中间线
int centernX = switchBitmap.getWidth() / 2;
//判断当前x值和中间线的大小  更改SwitchState
if( currentX >= centernX){
//open
if(sState != SwitchState.OPEN){
sState = SwitchState.OPEN;
if(listern != null){
listern.onSwitchStateChenged(sState);
}
}
}else{
//close
if(sState != SwitchState.CLOSE){
sState = SwitchState.CLOSE;
if(listern != null){
listern.onSwitchStateChenged(sState);
}
}
}

break;
}

// 调用invalidate()方法,请求重新draw()
invalidate();
return true;
}


使用

布局文件

<RelativeLayout 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"
tools:context=".MainActivity" >

<com.example.togbutton.view.MySwitch
android:id="@+id/ms_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />

</RelativeLayout>


Java代码

public class MainActivity extends Activity {

private MySwitch mySwitch;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mySwitch = (MySwitch) findViewById(R.id.ms_btn);

// 设置滑动块的背景图片
mySwitch.setSlideBackgroudResource(R.drawable.slide_button);
// 设置Switch背景图片
mySwitch.setSwitchBackgroundResource(R.drawable.switch_background);
// 设置更改Switch的开关状态
mySwitch.setSwitchState(SwitchState.OPEN);
// 设置Switch的开关状态监听器
mySwitch.setOnSwitchStateChangedListern(new OnSwitchStateChangedListern() {

@Override
public void onSwitchStateChenged(SwitchState state) {
Toast.makeText(MainActivity.this,
state == SwitchState.OPEN ? "开启" : "关闭", 0).show();
}
});
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: