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

来源:互联网 发布:南京软件行业优惠政策 编辑:程序博客网 时间:2024/06/10 15:58

简介

自定义控件步骤:           

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) {// 将资源文件转换为BitmapslideBitmap = BitmapFactory.decodeResource(getResources(),slideBackground);}/** * 设置switch的图片 *  * @param switchBackground */public void setSwitchBackgroundResource(int switchBackground) {// 将资源文件转换为BitmapswitchBitmap = 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;}/** * 设置当前控件在屏幕上的宽和高 */@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);// 设置当前View的大小 这个方法决定了当前View的大小setMeasuredDimension(switchBitmap.getWidth(), switchBitmap.getHeight());}/** * 绘制自己显示在屏幕上的样子 */@Overrideprotected 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:0if (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()

@Overridepublic 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值和中间线的大小  更改SwitchStateif( currentX >= centernX){//openif(sState != SwitchState.OPEN){sState = SwitchState.OPEN;}}else{//closeif(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;//如果leftif (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:0if (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值和中间线的大小  更改SwitchStateif( currentX >= centernX){//openif(sState != SwitchState.OPEN){sState = SwitchState.OPEN;if(listern != null){listern.onSwitchStateChenged(sState);}}}else{//closeif(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;@Overrideprotected 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() {@Overridepublic void onSwitchStateChenged(SwitchState state) {Toast.makeText(MainActivity.this,state == SwitchState.OPEN ? "开启" : "关闭", 0).show();}});}}



0 0
原创粉丝点击