Android 自定义View实现单击和双击事件的方法
自定义View,
1.自定义一个Runnable线程TouchEventCountThread, 用来统计500ms内的点击次数
2.在MyView中的onTouchEvent中调用上面的线程
3.自定义一个Handler,在TouchEventHandler中处理统计到的点击事件,单击,双击,三击,都可以处理
核心代码如下:
publicclassMyViewextendsView{
......
//统计500ms内的点击次数
TouchEventCountThreadmInTouchEventCount=newTouchEventCountThread();
//根据TouchEventCountThread统计到的点击次数,perform单击还是双击事件
TouchEventHandlermTouchEventHandler=newTouchEventHandler();
@Override
publicbooleanonTouchEvent(MotionEventevent){
switch(event.getAction()){
caseMotionEvent.ACTION_DOWN:
if(0==mInTouchEventCount.touchCount)//第一次按下时,开始统计
postDelayed(mInTouchEventCount,500);
break;
caseMotionEvent.ACTION_UP:
//一次点击事件要有按下和抬起,有抬起必有按下,所以只需要在ACTION_UP中处理
mInTouchEventCount.touchCount++;
//如果是长按操作,则Handler的消息,不能将touchCount置0,需要特殊处理
if(mInTouchEventCount.isLongClick){
mInTouchEventCount.touchCount=0;
mInTouchEventCount.isLongClick=false;
}
break;
caseMotionEvent.ACTION_MOVE:
break;
caseMotionEvent.ACTION_CANCEL:
break;
default:
break;
}
returnsuper.onTouchEvent(event);
}
publicclassTouchEventCountThreadimplementsRunnable{
publicinttouchCount=0;
publicbooleanisLongClick=false;
@Override
publicvoidrun(){
Messagemsg=newMessage();
if(0==touchCount){//longclick
isLongClick=true;
}else{
msg.arg1=touchCount;
mTouchEventHandler.sendMessage(msg);
touchCount=0;
}
}
}
publicclassTouchEventHandlerextendsHandler{
@Override
publicvoidhandleMessage(Messagemsg){
Toast.makeText(mContext,"touch"+msg.arg1+"time.",Toast.LENGTH_SHORT).show();
}
}
......
}
包装以后如下,这样就能在别的地方调用了:
publicinterfaceOnDoubleClickListener{
voidonDoubleClick(Viewv);
}
privateOnDoubleClickListenermOnDoubleClickListener;
publicvoidsetOnDoubleClickListener(MyView.OnDoubleClickListenerl){
mOnDoubleClickListener=l;
}
publicbooleanperformDoubleClick(){
booleanresult=false;
if(mOnDoubleClickListener!=null){
mOnDoubleClickListener.onDoubleClick(this);
result=true;
}
returnresult;
}
publicclassTouchEventHandlerextendsHandler{
@Override
publicvoidhandleMessage(Messagemsg){
if(2==msg.arg1)
performDoubleClick();
}
}
在Activity中使用:
myView1.setOnDoubleClickListener(newMyView.OnDoubleClickListener(){
@Override
publicvoidonDoubleClick(Viewv){
Toast.makeText(mContext,"doubleclick",Toast.LENGTH_SHORT).show();
}
});
全部代码
MyView.java
packagecom.carloz.test.myapplication.view;
importandroid.content.Context;
importandroid.content.res.TypedArray;
importandroid.graphics.Bitmap;
importandroid.graphics.BitmapFactory;
importandroid.graphics.Canvas;
importandroid.graphics.Paint;
importandroid.os.Handler;
importandroid.os.Message;
importandroid.util.AttributeSet;
importandroid.view.MotionEvent;
importandroid.view.View;
importandroid.widget.Toast;
importcom.carloz.test.myapplication.R;
/**
*Createdbyrooton15-11-9.
*/
publicclassMyViewextendsView{
privatePaintmPaint=newPaint();
privatebooleanmNotDestroy=true;
privateintmCount=0;
privateMyThreadmyThread;
Bitmapbitmap;
//attrs
privateStringmText;
privatebooleanmStartChange;
ContextmContext;
publicMyView(Contextcontext){
super(context);
init();
}
publicMyView(Contextcontext,AttributeSetattrs){
super(context,attrs);
TypedArrayta=context.obtainStyledAttributes(attrs,R.styleable.MyView);
mText=ta.getString(R.styleable.MyView_text);
mStartChange=ta.getBoolean(R.styleable.MyView_startChange,false);
//Log.d("ASDF","mText="+mText+",mStartChange="+mStartChange);
ta.recycle();
init();
}
@Override
protectedvoidonFinishInflate(){
super.onFinishInflate();
}
@Override
protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
}
@Override
protectedvoidonLayout(booleanchanged,intleft,inttop,intright,intbottom){
super.onLayout(changed,left,top,right,bottom);
}
@Override
protectedvoidonDraw(Canvascanvas){
super.onDraw(canvas);
mPaint.setTextSize(50);
canvas.drawText(mText+mCount++,20f,100f,mPaint);
canvas.save();
canvas.rotate(60,getWidth()/2,getHeight()/2);
canvas.drawBitmap(bitmap,20f,50f,mPaint);
canvas.restore();
if(null==myThread){
myThread=newMyThread();
myThread.start();
}
}
@Override
publicbooleandispatchTouchEvent(MotionEventev){
returnsuper.dispatchTouchEvent(ev);
}
@Override
protectedvoidonAttachedToWindow(){
super.onAttachedToWindow();
mNotDestroy=true;
}
@Override
protectedvoidonDetachedFromWindow(){
mNotDestroy=false;
super.onDetachedFromWindow();
}
//统计500ms内的点击次数
TouchEventCountThreadmInTouchEventCount=newTouchEventCountThread();
//根据TouchEventCountThread统计到的点击次数,perform单击还是双击事件
TouchEventHandlermTouchEventHandler=newTouchEventHandler();
@Override
publicbooleanonTouchEvent(MotionEventevent){
switch(event.getAction()){
caseMotionEvent.ACTION_DOWN:
if(0==mInTouchEventCount.touchCount)//第一次按下时,开始统计
postDelayed(mInTouchEventCount,500);
break;
caseMotionEvent.ACTION_UP:
//一次点击事件要有按下和抬起,有抬起必有按下,所以只需要在ACTION_UP中处理
mInTouchEventCount.touchCount++;
//如果是长按操作,则Handler的消息,不能将touchCount置0,需要特殊处理
if(mInTouchEventCount.isLongClick){
mInTouchEventCount.touchCount=0;
mInTouchEventCount.isLongClick=false;
}
break;
caseMotionEvent.ACTION_MOVE:
break;
caseMotionEvent.ACTION_CANCEL:
break;
default:
break;
}
returnsuper.onTouchEvent(event);
}
publicclassTouchEventCountThreadimplementsRunnable{
publicinttouchCount=0;
publicbooleanisLongClick=false;
@Override
publicvoidrun(){
Messagemsg=newMessage();
if(0==touchCount){//longclick
isLongClick=true;
}else{
msg.arg1=touchCount;
mTouchEventHandler.sendMessage(msg);
touchCount=0;
}
}
}
publicclassTouchEventHandlerextendsHandler{
@Override
publicvoidhandleMessage(Messagemsg){
Toast.makeText(mContext,"touch"+msg.arg1+"time.",Toast.LENGTH_SHORT).show();
}
}
classMyThreadextendsThread{
@Override
publicvoidrun(){
super.run();
while(mNotDestroy){
if(mStartChange){
postInvalidate();
try{
Thread.sleep(500);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
}
}
publicvoidinit(){
mContext=getContext();
bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
}
publicvoidsetText(StringmText){
this.mText=mText;
}
publicvoidsetStartChange(booleanmStartChange){
this.mStartChange=mStartChange;
}
publicbooleangetStartChange(){
returnthis.mStartChange;
}
}
attrs.xml
<?xmlversion="1.0"encoding="utf-8"?> <resources> <declare-styleablename="MyView"> <attrname="text"format="string"/> <attrname="startChange"format="boolean"/> </declare-styleable> </resources>
postDelayed方法最终是靠Handler的postDelayed方法实现原理如下
publicfinalbooleanpostDelayed(Runnabler,longdelayMillis)
{
returnsendMessageDelayed(getPostMessage(r),delayMillis);
}
publicfinalbooleansendMessageDelayed(Messagemsg,longdelayMillis)
{
if(delayMillis<0){
delayMillis=0;
}
returnsendMessageAtTime(msg,SystemClock.uptimeMillis()+delayMillis);
}
publicbooleansendMessageAtTime(Messagemsg,longuptimeMillis){
MessageQueuequeue=mQueue;
if(queue==null){
RuntimeExceptione=newRuntimeException(
this+"sendMessageAtTime()calledwithnomQueue");
Log.w("Looper",e.getMessage(),e);
returnfalse;
}
returnenqueueMessage(queue,msg,uptimeMillis);//然后在MessageQueue中会比较时间顺序
}
以上就是小编为大家带来的Android自定义View实现单击和双击事件的方法的全部内容了,希望对大家有所帮助,多多支持毛票票~