• Android应用之——自己定义控件ToggleButton


    我们经常会看到非常多优秀的app上面都有一些非常美丽的控件,用户体验非常好。比方togglebutton就是一个非常好的样例,IOS系统以下那个精致的togglebutton现在在android以下也能够实现了,并且还能够自己定义它的颜色文字背景图,做出各种美丽的开关按键出来。

    这里就用到了android里面一个比較经常使用的技术——自己定义控件。


    先来看下我们实现的自己定义的togglebutton效果图:

        


    自己定义控件的步骤:

    1、首先,定义一个类继承View 或者View的子类,这个取决于要定义的控件的类型。本例中,继承自View。


    2、继承了View后 就须要重写构造函数,有三个方法,各自是

    	public MyView(Context context) {
    		super(context);
    		// TODO Auto-generated constructor stub
    	}
    
    	public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
    		super(context, attrs, defStyleAttr);
    		// TODO Auto-generated constructor stub
    	}
    
    	public MyView(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		// TODO Auto-generated constructor stub
    这三个方法。依据不同的情况来使用,假设自己定义的控件须要设置xml属性那么就要用到第三个构造函数。假设须要设置xml属性而且定义样式,那么就须要实现第二个构造函数,使用其第三个參数defStyleAttr,假设没有以上两点要求,那么直接重写第一个构造函数就可以。


    这这个demo中,我们实现第一个构造函数就可以

    	public ToggleButton(Context context, AttributeSet attrs) {
    		super(context, attrs);
    
    		initBitmap();//初始化bitmap
    	}
    
    重写构造函数后,接下来就要依据不同控件的要求来选择是否重写onDraw和onMeasure方法了。

    假设自己定义控件的大小是须要自己定义的,比方本例中的togglebutton,那么首先须要重写onMeasure方法,測算出自己定义控件的宽和高。

    非常明显,我们这个togglebutton的宽和高是非常easy得出来的,高度就是这个控件背景图的宽和高

          

    所以onMeasure方法重写例如以下,得到自己定义控件的宽和高

    	/**
    	 * 初始化开关图片
    	 */
    	private void initBitmap() {
    		background = BitmapFactory.decodeResource(getResources(),
    				R.drawable.switch_background);
    		slideBackground = BitmapFactory.decodeResource(getResources(),
    				R.drawable.slide_button_background);
    	}

    	/**
    	 * 设置当前控件的宽和高
    	 */
    	@Override
    	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
    		// 设置开关的宽和高
    		setMeasuredDimension(background.getWidth(), background.getHeight());
    	}
    

    得到宽和高后,就须要绘制这个控件了。利用View的onDraw方法

    重写onDraw方法,我们能够得到一个參数canvas
     

    void onDraw(Canvas canvas)
    有了这个canvas对象,就能够非常方面的绘制出控件的样子

    先绘制控件的背景,由于togglebutton。事实上就是一个button在一个背景图上面来回滑动产生不同的效果。所以我们先绘制它的背景。

    canvas.drawBitmap(background, 0, 0, null);
    绘制完背景后,就要绘制小滑块了。小滑块有两种状态,一种是在滑动,还有一种是精巧状态,这两种状态我们须要分别进行处理。

    当小滑块在滑动的时候,背景图是不会变的,并且它滑动到某个时刻的样子也非常明白。滑动了多少距离就绘制它在某距离的状态。可是有一种情况须要进行处理,那就是滑块滑出边界的情况,假设是从左边滑出边界,那么就应该将它离左边的距离置为0,也就是不让它继续滑动,同理右边也要进行对应的处理。

    滑动过程代码例如以下:

    if(isSliding) {		// 正在滑动中
    			int left = currentX - slideBackground.getWidth() / 2;
    			
    			if(left < 0) {		// 当前超出了左边界, 赋值为0
    				left = 0;
    			} else if(left > (background.getWidth() - slideBackground.getWidth())) {
    				// 当前超出了右边界, 赋值为: 背景的宽度 - 滑动块的宽度
    				left = background.getWidth() - slideBackground.getWidth();
    			}
    			
    			canvas.drawBitmap(slideBackground, left, 0, null);
    		}
    精巧状态的话,非常easy,依据不同的状态将滑块放置到控件的左边和右边就可以

    if(currentState) {
    				// 绘制开的状态
    				canvas.drawBitmap(slideBackground, 0, 0, null);
    			} else {
    				// 绘制关的状态
    				int left = background.getWidth() - slideBackground.getWidth();
    				canvas.drawBitmap(slideBackground, left, 0, null);
    			}

    上面,我们就完毕了自己定义一个togglebutton的界面上的操作了,可是togglebutton的作用是用来控制开关的。所以还要对它的一些事件进行处理。

    滑动事件的处理。捕获用户的操作。为它设置一个自己定义的状态改变监听器

    /**
    	 * 捕获用户操作的事件
    	 */
    	@Override
    	public boolean onTouchEvent(MotionEvent event) {
    		switch (event.getAction()) {
    		case MotionEvent.ACTION_DOWN:
    			currentX = (int) event.getX();
    			isSliding = true;
    			break;
    		case MotionEvent.ACTION_MOVE:
    			currentX = (int) event.getX();
    			break;
    		case MotionEvent.ACTION_UP:
    			isSliding = false;
    			currentX = (int) event.getX();
    
    			int center = background.getWidth() / 2;
    
    			// 当前最新的状态
    			boolean state = currentX < center;
    			// 假设两个状态不一样而且监听事件不为null
    			if (currentState != state && mOnToggleStateChangeListener != null) {
    				// 调用用户的回调事件
    				mOnToggleStateChangeListener.onToggleStateChange(state);
    			}
    			currentState = state;
    			break;
    		default:
    			break;
    		}
    		invalidate(); // 此方法被调用会使onDraw方法重绘
    		return true;
    	}
    


    这里自己定义了一个状态改变监听器。用来监听togglebutton的状态改变,然后回调方法,进行对应的处理。

    public interface OnToggleStateChangeListener {
    
    	void onToggleStateChange(boolean state);
    
    }



    最后。为这个控件提供三个方法,设置状态为开或关的方法。另一个设置监听事件的方法

    /**
    	 * 设置开关的状态
    	 * 
    	 * @param state
    	 */
    	public void setToggleState(boolean state) {
    		currentState = state;
    	}
    
    	public boolean getToogleState() {
    		return currentState;
    	}
    
    	public void setOnToggleStateChangeListener(
    			OnToggleStateChangeListener listener) {
    		mOnToggleStateChangeListener = listener;
    	}


    到这里,整个自定义togglebutton的过程就算完了。接下来我们就能够在程序中使用自定义的控件了。

    在xml文件里,用全路径名使用自己定义控件,然后在java代码中就能够获取到这个自己定义控件的对象 和相关的方法了

    <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" >
    
        <com.yang.togglebutton.ToggleButton
            android:id="@+id/togglebutton"
            android:layout_width="wrap_content"
            android:layout_height="30dip"
            android:layout_centerInParent="true" />
    
        <com.yang.togglebutton.ToggleButtonVIPS
            android:id="@+id/toggle2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/togglebutton"
            android:layout_centerHorizontal="true" />
    
    </RelativeLayout>


    总结一下事实上就是几个步骤:

    1、继承View或者它的子类,依据不同的情况重写不同的构造函数(必须)

    2、重写onMeasure方法,測量控件的大小(非必须)

    3、重写onDraw方法,绘制控件(非必须)
    4、为控件设置一些自己定义方法和监听器(非必须)

    5、在xml中使用。或者直接在java代码中使用


    转载请注明出处http://blog.csdn.net/csr_yang/article/details/37341221




    Demo下载




  • 相关阅读:
    冒泡排序
    跑马(行转列,列转行)
    选择排序
    day06-迭代器
    day05-装饰器作业
    day07-生成器
    day08-内置函数和匿名函数
    day09-正侧表达式
    144-SpringBoot的编码问题?
    143-SprinBoot如何使用Servlet?
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/7063137.html
Copyright © 2020-2023  润新知