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实现单击和双击事件的方法的全部内容了,希望对大家有所帮助,多多支持毛票票~