`
chroya
  • 浏览: 661489 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Android自定义长按事件

阅读更多

    Android系统自带了长按事件,setOnLongClickListener即可监听。但是有时候,你不希望用系统的长按事件,比如当希望长按的时间更长一点的时候。这时候就需要自己来定义这个长按事件了。
    下面是去年我写代码的时候,自定义长按事件的方式:

package chroya.fun;

import android.content.Context;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

public class LongPressView1 extends View{
	private int mLastMotionX, mLastMotionY;
	//是否移动了
	private boolean isMoved;
	//是否释放了
	private boolean isReleased;
	//计数器,防止多次点击导致最后一次形成longpress的时间变短
	private int mCounter;
	//长按的runnable
	private Runnable mLongPressRunnable;
	//移动的阈值
	private static final int TOUCH_SLOP = 20;

	public LongPressView1(Context context) {
		super(context);
		mLongPressRunnable = new Runnable() {
			
			@Override
			public void run() {
				mCounter--;
				//计数器大于0,说明当前执行的Runnable不是最后一次down产生的。
				if(mCounter>0 || isReleased || isMoved) return;
				performLongClick();
			}
		};
	}

	public boolean dispatchTouchEvent(MotionEvent event) {
		int x = (int) event.getX();
		int y = (int) event.getY();
		
		switch(event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			mLastMotionX = x;
			mLastMotionY = y;
			mCounter++;
			isReleased = false;
			isMoved = false;
			postDelayed(mLongPressRunnable, ViewConfiguration.getLongPressTimeout());
			break;
		case MotionEvent.ACTION_MOVE:
			if(isMoved) break;
			if(Math.abs(mLastMotionX-x) > TOUCH_SLOP 
					|| Math.abs(mLastMotionY-y) > TOUCH_SLOP) {
				//移动超过阈值,则表示移动了
				isMoved = true;
			}
			break;
		case MotionEvent.ACTION_UP:
			//释放了
			isReleased = true;
			break;
		}
		return true;
	}
}

     代码里注释的比较清楚。主要思路是在down的时候,让一个Runnable一段时间后执行,如果时间到了,没有移动超过定义的阈值,也没有释放,则触发长按事件。在真实环境中,当长按触发之后,还需要将后来的move和up事件屏蔽掉。此处是示例,就略去了。

      下面讲讲第二种方式:

package chroya.fun;

import android.content.Context;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

public class LongPressView2 extends View{
	private int mLastMotionX, mLastMotionY;
	//是否移动了
	private boolean isMoved;
	//长按的runnable
	private Runnable mLongPressRunnable;
	//移动的阈值
	private static final int TOUCH_SLOP = 20;

	public LongPressView2(Context context) {
		super(context);
		mLongPressRunnable = new Runnable() {
			
			@Override
			public void run() {				
				performLongClick();
			}
		};
	}

	public boolean dispatchTouchEvent(MotionEvent event) {
		int x = (int) event.getX();
		int y = (int) event.getY();
		
		switch(event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			mLastMotionX = x;
			mLastMotionY = y;
			isMoved = false;
			postDelayed(mLongPressRunnable, ViewConfiguration.getLongPressTimeout());
			break;
		case MotionEvent.ACTION_MOVE:
			if(isMoved) break;
			if(Math.abs(mLastMotionX-x) > TOUCH_SLOP 
					|| Math.abs(mLastMotionY-y) > TOUCH_SLOP) {
				//移动超过阈值,则表示移动了
				isMoved = true;
				removeCallbacks(mLongPressRunnable);
			}
			break;
		case MotionEvent.ACTION_UP:
			//释放了
			removeCallbacks(mLongPressRunnable);
			break;
		}
		return true;
	}
}

     思路跟第一种差不多,不过,在移动超过阈值和释放之后,会将Runnable从事件队列中remove掉,长按事件也就不会再触发了。源码中实现长按的原理也基本如此。

 

      工程见附件。

分享到:
评论
28 楼 Badwaka 2015-12-02  
Badwaka 写道
大神你太厉害了!


这个思路很特别,直接控制longClick事件的分发
我之前一直想着自己来做判定,很麻烦很麻烦,想的脑子都爆炸了。。。

谢谢大神~~~~
27 楼 Badwaka 2015-12-02  
大神你太厉害了!
26 楼 lanroness 2014-05-21  
lanroness 写道
打开是黑屏啊

就在屏幕上按么?为什么不弄个按钮呢
25 楼 lanroness 2014-05-21  
打开是黑屏啊
24 楼 zhaoyazhong 2013-10-31  
最近在做MapView相关的东西,长按,移动,点击相互影响,文章太有用了。桑扣!
23 楼 chroya 2012-09-24  
sayyanfu 写道
chroya 写道
热血pk007 写道
chroya 写道
热血pk007 写道
这个运行之后怎么是黑屏?触屏没反应啊

你看代码啊,log里面会打出来的。

长按时间也没有加长啊,和内部自带的长按事件是相同的时间长短啊

是的,长按事件是用的系统的时间ViewConfiguration.getLongPressTimeout(),如果你需要加长,可以自己更改,把这个改成想要的时间。

ViewConfiguration.getLongPressTimeout()是个常量如何修改?

sayyanfu 写道
chroya 写道
热血pk007 写道
chroya 写道
热血pk007 写道
这个运行之后怎么是黑屏?触屏没反应啊

你看代码啊,log里面会打出来的。

长按时间也没有加长啊,和内部自带的长按事件是相同的时间长短啊

是的,长按事件是用的系统的时间ViewConfiguration.getLongPressTimeout(),如果你需要加长,可以自己更改,把这个改成想要的时间。

ViewConfiguration.getLongPressTimeout()是个常量如何修改?

我不是说改ViewConfiguration.getLongPressTimeout()它的值,而是说自己定义长按delay的时间
22 楼 sayyanfu 2012-09-10  
chroya 写道
热血pk007 写道
chroya 写道
热血pk007 写道
这个运行之后怎么是黑屏?触屏没反应啊

你看代码啊,log里面会打出来的。

长按时间也没有加长啊,和内部自带的长按事件是相同的时间长短啊

是的,长按事件是用的系统的时间ViewConfiguration.getLongPressTimeout(),如果你需要加长,可以自己更改,把这个改成想要的时间。

ViewConfiguration.getLongPressTimeout()是个常量如何修改?
21 楼 chroya 2012-07-11  
ysxmwyhh 写道
请问我怎么在自己的button上面使用这个长按事件

自己的Button实现文中所述的几个方法,然后直接setOnLongClickListener即可。
20 楼 ysxmwyhh 2012-07-04  
请问我怎么在自己的button上面使用这个长按事件
19 楼 chroya 2011-12-31  
Dr.hydra 写道
感谢楼主!非常感谢,最近在做一个东西,正好遇到一个长按滑动和普通滑动并存的问题,幸亏看到楼主的文章!楼主能留个联系方式不,以后想向您请教

加群:5838954
18 楼 Dr.hydra 2011-12-07  
感谢楼主!非常感谢,最近在做一个东西,正好遇到一个长按滑动和普通滑动并存的问题,幸亏看到楼主的文章!楼主能留个联系方式不,以后想向您请教
17 楼 u_xtian 2011-10-13  
很不错!但是我现在需要自定义AdapterView里面的OnItemLongClickListener,难搞啊
16 楼 王山而 2011-08-08  
mark 
15 楼 greenboy1 2011-05-16  
楼主的文章不错
14 楼 chroya 2011-02-22  
binggo2011 写道
chroya 写道
binggo2011 写道
在onTOuch里面监听action-move执行的次数也可以实现longclick,
不知道有没意义,性能怎么样?

  不明白,监听action-move执行次数有什么作用?多少次算是longclick?


/**
* 自定义图片左右手势和类LongClick触发事件
* @author Administrator
*
*/
public abstract class MyOnTouchListener implements OnTouchListener {

private static final int MOVE_MIN_DISTANCE = 100; //触发左移或右移的最小距离
private static final int LONG_CLICK_MIN_DISTANCE = 20; //触发LongClick的最大移动距离
private static final int LONG_CLICK_MIN_TIME = 35; //触发LongClick的最小ACTION_MOVE的次数
private float mX;
private int mNum = 0;

public abstract void setLeftEvent();

public abstract void setRightEvent();

public abstract void setLongClickEvent();

@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mX = event.getX();
return false;
case MotionEvent.ACTION_CANCEL:

return false;
case MotionEvent.ACTION_MOVE:
System.out.println("MOVE");
mNum++;
return false;
case MotionEvent.ACTION_OUTSIDE:

return false;
case MotionEvent.ACTION_UP:
float distance = event.getX() - mX;
if (Math.abs(distance) > MOVE_MIN_DISTANCE) {
if (distance > 0)
setRightEvent();
else
setLeftEvent();
} else if (Math.abs(distance) < LONG_CLICK_MIN_DISTANCE
&& mNum > LONG_CLICK_MIN_TIME) {
setLongClickEvent();
}
mNum = 0;
return true;
}
return false;
}
}

我哥介绍看你的博客的  说看了能变超人的... 呃.

根据次数判断长按,太不严谨了 
别被误导了
13 楼 binggo2011 2011-02-22  
chroya 写道
binggo2011 写道
在onTOuch里面监听action-move执行的次数也可以实现longclick,
不知道有没意义,性能怎么样?

  不明白,监听action-move执行次数有什么作用?多少次算是longclick?


/**
* 自定义图片左右手势和类LongClick触发事件
* @author Administrator
*
*/
public abstract class MyOnTouchListener implements OnTouchListener {

private static final int MOVE_MIN_DISTANCE = 100; //触发左移或右移的最小距离
private static final int LONG_CLICK_MIN_DISTANCE = 20; //触发LongClick的最大移动距离
private static final int LONG_CLICK_MIN_TIME = 35; //触发LongClick的最小ACTION_MOVE的次数
private float mX;
private int mNum = 0;

public abstract void setLeftEvent();

public abstract void setRightEvent();

public abstract void setLongClickEvent();

@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mX = event.getX();
return false;
case MotionEvent.ACTION_CANCEL:

return false;
case MotionEvent.ACTION_MOVE:
System.out.println("MOVE");
mNum++;
return false;
case MotionEvent.ACTION_OUTSIDE:

return false;
case MotionEvent.ACTION_UP:
float distance = event.getX() - mX;
if (Math.abs(distance) > MOVE_MIN_DISTANCE) {
if (distance > 0)
setRightEvent();
else
setLeftEvent();
} else if (Math.abs(distance) < LONG_CLICK_MIN_DISTANCE
&& mNum > LONG_CLICK_MIN_TIME) {
setLongClickEvent();
}
mNum = 0;
return true;
}
return false;
}
}

我哥介绍看你的博客的  说看了能变超人的... 呃.
12 楼 chroya 2011-02-21  
binggo2011 写道
在onTOuch里面监听action-move执行的次数也可以实现longclick,
不知道有没意义,性能怎么样?

  不明白,监听action-move执行次数有什么作用?多少次算是longclick?
11 楼 binggo2011 2011-02-21  
在onTOuch里面监听action-move执行的次数也可以实现longclick,
不知道有没意义,性能怎么样?
10 楼 alen456 2010-12-06  
长按键,我之前也做过了,但是感觉你的代码比我的少点,感谢你!
9 楼 chroya 2010-12-05  
热血pk007 写道
chroya 写道
热血pk007 写道
这个运行之后怎么是黑屏?触屏没反应啊

你看代码啊,log里面会打出来的。

长按时间也没有加长啊,和内部自带的长按事件是相同的时间长短啊

是的,长按事件是用的系统的时间ViewConfiguration.getLongPressTimeout(),如果你需要加长,可以自己更改,把这个改成想要的时间。

相关推荐

    android自定义长按事件

    在Android开发中,自定义长按事件是一项基本且重要的技能,尤其在设计交互式用户界面时。本知识点主要探讨如何在Android应用中实现自定义的长按事件,并结合实际的项目代码进行解析。 首先,我们需要了解Android中...

    android:自定义长按/长点击事件

    总结来说,自定义长按事件在Android开发中是常见的需求,通过`GestureDetector`可以方便地实现这一功能。在实际应用中,我们还可以结合其他手势,如滑动、双击等,为用户提供更为丰富的交互体验。对于`...

    Android自定义TextView链接点击和长按事件

    // 自定义长按事件的逻辑 return true; } }); ``` 四、自定义链接样式 除了点击和长按事件,我们还可以自定义链接的样式,例如颜色、下划线等。这可以通过设置`SpannableString`实现: ```java String text = ...

    Android自定义按钮实现长按功能

    通过这种方式,我们就成功地实现了Android自定义按钮的长按功能。这种方法允许我们在不改变原有按钮样式的情况下,轻松添加长按行为,为用户提供更多的交互可能性。同时,自定义按钮类也可以根据需求扩展其他功能,...

    WebView 自定义长按选择,实现收藏 / 分享选中文本

    总之,实现WebView自定义长按选择并提供收藏和分享选中文本的功能,涉及到WebView的事件监听、JavaScript与Java的交互、自定义菜单的创建以及Android的分享和存储机制。这需要开发者具备扎实的Android基础和一定的...

    Android长按屏幕事件

    在Android开发中,用户交互是应用的核心部分,而长按事件(Long Press Event)是其中一种常见的交互方式。本文将详细讲解如何在Android应用中实现长按屏幕事件,并通过一个名为"LongPressEventDemo"的示例项目进行...

    Android MenuItem 自定义长按事件的实现

    本篇文章将详细讲解如何在Android中实现MenuItem的自定义长按事件。 首先,实现MenuItem的长按事件主要涉及以下步骤: 1. **获取MenuItem的View**: 在Android中,MenuItem本身并不直接对应一个View,但它可以...

    ExpandableListView 点击和长按事件

    在`ExpandableListViewDemo`项目中,开发者通常会创建一个自定义的`ExpandableListAdapter`,在这个适配器中实现上述的点击和长按事件处理逻辑。同时,还需要在主活动中设置`ExpandableListView`并绑定适配器。 ...

    RecyclerView的长按事件和点击事件

    综上所述,通过自定义Adapter、设置监听器以及使用接口回调,我们可以在RecyclerView中实现点击和长按事件。这个过程不仅涉及到事件监听,还涉及到组件交互和业务逻辑处理,是Android开发中的常见实践。

    Android解决文本链接长按事件与短按事件冲突的demo

    在Android开发中,处理文本链接的交互是一个常见的需求。...本文将深入探讨如何在Android中解决这种冲突,实现长按事件和短按事件...这种方法既保留了链接的默认外观,又允许我们自定义长按事件,从而提供更好的用户体验。

    android listview长按,单击各种事件捕捉

    对于长按事件,我们需要使用`OnLongClickListener`。同样在`getView`中设置: ```java view.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { int ...

    Android ListView长按删除

    综上所述,实现Android ListView的长按删除功能,主要涉及以下几个步骤:设置适配器、添加长按监听器、处理长按事件、删除数据源中的项并更新适配器,以及可选地提供删除确认提示。通过这些步骤,你可以为你的...

    Android实现长按图片保存至相册功能

    首先,我们需要监听用户的长按事件。这通常通过在ImageView或自定义视图上添加OnLongClickListener来完成。当用户长按时,我们可以调用一个方法来处理图片的保存操作。以下是一个简单的例子: ```java imageView....

    安卓(Android) 监听按键长按事件

    尤其对于需要频繁操作物理按键的场景,如相机应用、播放器控制等,对按键长按事件的监听尤其关键。长按事件不仅可以提高用户体验,还能使应用具备更多的交互操作。 首先,要理解Android按键事件的处理流程。在...

    Android 自定义按钮点击事件和长按事件对比

    Android 自定义按钮点击事件和长按事件对比 Android 自定义按钮点击事件和长按事件对比是 Android 应用开发中经常遇到的问题。在 Android 中,我们可以通过设置OnClickListener 和 OnLongClickListener 来实现按钮...

    Android自定义GridView长按拖动排序

    以上就是实现Android自定义`GridView`长按拖动排序的详细步骤和技术要点。实际开发中,可能需要根据具体需求进行调整和优化,但这个基本框架应该足以指导你完成大部分工作。在`DragGridView`源代码中,你应该能找到...

    android listview长按子项动态添加自定义view

    在做项目中碰见一个在listview子项里面长按,会显示不定数量的控件出来,于是我通过添加自定义view来实现,当然也可以通过listview动态添加gridview来实现.功能说明,长按显示新添加上去的自定义view,点击中间的...

Global site tag (gtag.js) - Google Analytics