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

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

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

    

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY3NyX3lhbmc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

自己定义控件的步骤:

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下载

Android应用之——自己定义控件ToggleButton的更多相关文章

  1. Android经常使用自己定义控件(二)

           经常使用的Android自己定义控件分享 http://www.see-source.com//androidwidget/list.html?type=&p=1

  2. Android圆形图片--自己定义控件

    Android圆形图片控件效果图例如以下: 代码例如以下: RoundImageView.java package com.dxd.roundimageview; import android.con ...

  3. Android经常使用自己定义控件

    http://www.see-source.com/androidwidget/list.html

  4. Androd自己定义控件(三)飞翔的小火箭

    在前面的自己定义控件概述中已经跟大家分享了Android开发其中自己定义控件的种类. 今天跟大家分享一个非主流的组合控件. 我们在开发其中,难免须要在不同的场合中反复使用一些控件的组合.而Java的最 ...

  5. Android自定义控件1--自定义控件介绍

    Android控件基本介绍 Android本身提供了很多控件比如我们常用的有文本控件TextView和EditText:按钮控件Button和ImageButton状态开关按钮ToggleButton ...

  6. Android自己定义控件系列二:自己定义开关button(一)

    这一次我们将会实现一个完整纯粹的自己定义控件,而不是像之前的组合控件一样.拿系统的控件来实现.计划分为三部分:自己定义控件的基本部分,自己定义控件的触摸事件的处理和自己定义控件的自己定义属性: 以下就 ...

  7. Android自己定义控件之应用程序首页轮播图

    如今基本上大多数的Android应用程序的首页都有轮播图.就是像下图这种(此图为转载的一篇博文中的图.拿来直接用了): 像这种组件我相信大多数的应用程序都会使用到,本文就是自己定义一个这种组件,能够动 ...

  8. Android自己定义控件(状态提示图表)

    [工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处.尊重分享成果] 1 背景 前面分析那么多系统源代码了.也该暂停下来歇息一下,趁昨晚闲着看见一个有意思的需求就操 ...

  9. 【Android】自己定义控件——仿天猫Indicator

    今天来说说类似天猫的Banner中的小圆点是怎么做的(图中绿圈部分) 在学习自己定义控件之前,我用的是很二的方法,直接在布局中放入多个ImageView,然后代码中依据Pager切换来改变图片.这样的 ...

随机推荐

  1. 10-XML

    今日知识 1. xml * 概念 * 语法 * 解析 xml概念 1. 概念:Extensible Markup Language 可扩展标记语言 * 可扩展:标签都是自定义的. <user&g ...

  2. mysqls,为node.js而编写的sql语句生成插件 (crud for mysql).

    It is written in JavaScript,crud for mysql.You can also use transactions very easily. mysqls 一款专为nod ...

  3. Android 自定义控件之圆形扩散View(DiffuseView)

    实现效果 使用 属性方法 代码 源码下载 参考链接 实现效果 使用 XML中: <com.airsaid.diffuseview.widget.DiffuseView android:id=&q ...

  4. 百度map API

    1.做demo用的 http://developer.baidu.com/map/jsdemo.htm demo代码(外部使用的话需要提供密钥): <!DOCTYPE html> < ...

  5. sublime text 3 上安装xdebug

    安装完成之后启动xdebug,缺省设置下会显示warning等信息,很不方便. 可以参考 https://github.com/martomo/SublimeTextXdebug/blob/maste ...

  6. JVM上的下一个Java——Scala

    Scala是一种针对 JVM 将函数和面向对象技术组合在一起的编程语言.Scala编程语言近来抓住了很多开发者的眼球.它看起来像是一种纯粹的面向对象编程语言,而又无缝地结合了命令式和函数式的编程风格. ...

  7. 2 Selenium3.0+Python3.6环境搭建

    [说明] 再次搭建一次环境,是因为遇到怎么都打不开IE的问题了,环境信息为:Selenium3.0+Python3.6+win7+ie10 [搭建步骤] 1.下载Python3.6,并点击安装和配置环 ...

  8. 引用css样式的书写格式

    css的书写格式一共有三种 行内样式:意思是在行内中写样式 例如说<p style="color:red">用行内样式编写我的颜色</p> 只适用于< ...

  9. RxSwift學習教程之基礎篇

    前言 我們在 iOS 開發過程中,幾乎無時無刻都要面對異步事件的處理.例如,按鍵點擊.數據保存..音頻後臺播放.交互動畫展示.這些事件並不具備特定時序性,甚至它們可能同時發生. 雖然 Apple 提供 ...

  10. 行间事件传this的问题:

    在做1个简单功能的时候,行间事件这块发现了1个问题: <!doctype html> <html> <head> <meta charset="ut ...