监听Touch事件自定义属性实现Selector

先看效果图,点击事件触发时背景变化,一般都是通过selector标签实现的。但是当我们经常要使用到的时候,我们想直接在布局文件中设置两个背景资源,点击时候一个,默认情况下一个,这样就很直观的在布局文件中看出来,而不需要建立大量的selector来实现。

这样的效果当然可以使用android:background设置一个Selector背景,但是这里不是。这里仅仅是自定义一个button。

<com.example.view.ButtonSelect
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginTop="20dp"
android:text="@string/hello_world"
android:background="@android:color/holo_green_light" />

其中的自定义控件是怎么改变背景的呢:

public class ButtonSelect extends Button {

	public ButtonSelect(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	@SuppressLint("ClickableViewAccessibility")
	private void init(Context context) {

		setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				if (event.getAction() == MotionEvent.ACTION_DOWN) {
					setBackgroundResource(android.R.color.holo_red_light);
				} else if (event.getAction() == MotionEvent.ACTION_CANCEL
						|| event.getAction() == MotionEvent.ACTION_UP || !isPressed()) {
					setBackgroundResource(android.R.color.holo_green_light);
				}
				return false;
			}
		});
	}

}

可以看出,这里是监听了OnTouchListener事件,通过点击状态改变背景。通常情况下,手指离开了按键范围之后,需要取消事件,所以这里加入了isPressed()判断。当已经离开按键范围,就还原背景,否则只要手指不抬起来,按下的背景状态一直持续。触摸离开按键范围就还原背景也是普通的Button的基本情况。

接下来我们实现在布局文件中直接设置按键按下的背景。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

	<com.example.view.ButtonSelectRes
	    android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_marginTop="20dp"
        android:background="@drawable/bg_off"
        android:text="@string/hello_world"
        android:textColor="@android:color/black"
        app:clickOnBackground="#FFF44000" />

</LinearLayout>

这里使用了自定义属性app:clickOnBackground,设置按下之后的背景变化成什么样子。

首先第一属性,在res/values/styles.xml中建立标签:<declare-styleable name="SelectBackground">;

<resources>

    <!--
        Base application theme, dependent on API level. This theme is replaced
        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
    -->
    <style name="AppBaseTheme" parent="android:Theme.Light">
        <!--
            Theme customizations available in newer API levels can go in
            res/values-vXX/styles.xml, while customizations related to
            backward-compatibility can go here.
        -->
    </style>

    <!-- Application theme. -->
    <style name="AppTheme" parent="AppBaseTheme">
        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
    </style>

    <declare-styleable name="SelectBackground">
        <attr name="clickOnBackground" format="reference|color" />
    </declare-styleable>

</resources>

这里使用了的控件自定义属性可以参考http://blog.csdn.net/dreamintheworld/article/details/45224807

设置了declare-styleable标签的style之后,就可以在布局文件中使用所定义的clickOnBackground属性。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

	<com.example.view.ButtonSelectRes
	    android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_marginTop="20dp"
        android:background="@drawable/bg_off"
        android:text="@string/hello_world"
        android:textColor="@android:color/black"
        app:clickOnBackground="#FFF44000" />

</LinearLayout>

这里直接使用app:clickOnBackground="#FFF44000" 。是因为在文件开始的地方已经定义了app的命名空间

xmlns:app="http://schemas.android.com/apk/res-auto"

在sdk17以后都可以直接使用res-auto了。方便了不少,不用填写包名等信息,统一使用一个字段;

这里的bg_off是一张图片。

自定义控件代码:

public class ButtonSelectRes extends Button {

	private Drawable clickOffbg;
	private Drawable clickOnbg;

	public ButtonSelectRes(Context context, AttributeSet attrs) {
		super(context, attrs);

		init(context, attrs);
	}

	@SuppressLint("ClickableViewAccessibility")
	private void init(Context context, AttributeSet attrs) {
		initAttributeSet(context, attrs);

		setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				if (event.getAction() == MotionEvent.ACTION_DOWN) {
					setBackground(clickOnbg);
				} else if (event.getAction() == MotionEvent.ACTION_CANCEL
						|| event.getAction() == MotionEvent.ACTION_UP || !isPressed()) {
					setBackground(clickOffbg);
				}
				return false;
			}
		});
	}

	private void initAttributeSet(Context context, AttributeSet attrs) {
		if (attrs == null) {
			return;
		}
		int[] styles = R.styleable.SelectBackground;

		TypedArray typedArray = context.obtainStyledAttributes(attrs, styles);
		try {
			int clickOnColor =  typedArray.getColor(R.styleable.SelectBackground_clickOnBackground,
					android.R.color.holo_red_light);
			clickOnbg = new ColorDrawable(clickOnColor);
		} catch (Exception e) {
			clickOnbg = typedArray.getDrawable(R.styleable.SelectBackground_clickOnBackground);
		}

		typedArray.recycle();
	}

	@Override
	protected void onFinishInflate() {
		super.onFinishInflate();
		clickOffbg = getBackground();
	}

}

运行之后是这样的:

到此我们就可以直接的使用

android:background="@drawable/bg_off"

app:clickOnBackground="#FFF44000"

非常直观的可以看到点击前后的效果,也避免了过多的drawable文件。

至于是监听了onTouch事件,是因为如果监听点击事件是不容易修改背景的,也会导致在页面中的设置了点击事件被覆盖掉而不响应的问题。

博文来自CSDN:http://blog.csdn.net/dreamintheworld/article/details/45224337

时间: 2024-08-28 23:41:16

监听Touch事件自定义属性实现Selector的相关文章

Netty源码分析第3章(客户端接入流程)----&gt;第5节: 监听读事件

Netty源码分析第三章: 客户端接入流程 第五节: 监听读事件 我们回到AbstractUnsafe的register0()方法: private void register0(ChannelPromise promise) { try { //省略代码 //做实际的注册 doRegister(); neverRegistered = false; registered = true; //触发事件 pipeline.invokeHandlerAddedIfNeeded(); safeSetS

JS 事件绑定、事件监听、事件委托详细介绍

事件绑定 要想让 JavaScript 对用户的操作作出响应,首先要对 DOM 元素绑定事件处理函数.所谓事件处理函数,就是处理用户操作的函数,不同的操作对应不同的名称. 在JavaScript中,有三种常用的绑定事件的方法: 在DOM元素中直接绑定: 在JavaScript代码中绑定: 绑定事件监听函数. 在DOM中直接绑定事件 我们可以在DOM元素上绑定onclick.onmouseover.onmouseout.onmousedown.onmouseup.ondblclick.onkeyd

ionic 监听路由事件 验证登录

.run(['$rootScope', '$location' , '$state', '$http','$ionicPopup', function($rootScope, $location, $state,$http,$ionicPopup){ var loginname=['tab.member','loan','repayment','iftab.exe']; $http.jsonp(apiurl+"/home/appapi/isLogin?callback=JSON_CALLBACK

原 JS监听回车事件

原 JS监听回车事件 发表于2年前(2014-06-04 10:16)   阅读(6101) | 评论(0) 11人收藏此文章, 我要收藏 赞0 1月16日厦门 OSC 源创会火热报名中,奖品多多哦   JS监听某个输入框 ? 1 2 3 4 5 6 7 //回车事件绑定     $('#search_input').bind('keyup', function(event) {         if (event.keyCode == "13") {             //回车

vue监听滚动事件,实现滚动监听

在vue中实现滚动监听和原生js无太大差异,下面是一个简单的demo,可在控制台查看结果 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script type="text/javascript" src="https://unpkg

JS 中的事件绑定、事件监听、事件委托

事件绑定 要想让 JavaScript 对用户的操作作出响应,首先要对 DOM 元素绑定事件处理函数.所谓事件处理函数,就是处理用户操作的函数,不同的操作对应不同的名称. 在JavaScript中,有三种常用的绑定事件的方法: 在DOM元素中直接绑定: 在JavaScript代码中绑定: 绑定事件监听函数. 在DOM中直接绑定事件 我们可以在DOM元素上绑定onclick.onmouseover.onmouseout.onmousedown.onmouseup.ondblclick.onkeyd

Qt实现小功能之列表无限加载(创意很不错:监听滚动条事件,到底部的时候再new QListWidgetItem)

概念介绍 无限加载与瀑布流的结合在Web前端开发中的效果非常新颖,对于网页内容具备较好的表现形式.无限加载并没有一次性将内容全部加载进来,而是通过监听滚动条事件来刷新内容的.当用户往下拖动滚动条或使用鼠标滚轮的时候,页面会自动加载剩余的内容.如下: 简约而不简单,正是这种别出心裁,突破常规的设计才能得到用户的青睐…… 实现思路 在前端开发可以使用一些jQuery插件实现这种效果,后台只需要准备好数据就行了.在Qt中如何给列表组件(QListWidget,QTreeWidget, QTableWi

javascript事件监听与事件委托

事件监听与事件委托 在js中,常用到element.addEventListener()来进行事件的监听.但是当页面中存在大量需要绑定事件的元素时,这种方式可能会带来性能影响.此时,我们可以用事件委托的方式来进行事件的监听. 每个事件都经历三个阶段 捕获 到达目标 冒泡 事件委托需要用到事件的冒泡,冒泡就是事件发生时,上层会一层一层的接收这个事件. 如下页面结构: <body> <div id="div1"> <div id="div2"

Linux文本模式下监听鼠标事件

Linux文本模式下监听鼠标事件,这里是通过gpm这个来实现的,代码如下: 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <gpm.h> 5 6 void main(int argc,char **argv) 7 { 8 fd_set readset; 9 Gpm_Event event; 10 Gpm_Connect conn; 11 12 conn.