关于android下面girdview item同时实现onclick和ontouch的一点心得.

源于一个bug.这个bug的是这样.下面是一个girdview当用户反复点击某一个自定义item的时候,比如说是1 ,会导致item 3响应.查了一下原因是由于

onclick实现的架构错误引起的,监听器源代码如下
		this.setOnTouchListener( new OnTouchListener() {
			
			@Override
			public boolean onTouch(
					View v ,
					MotionEvent event )
			{
				// TODO Auto-generated method stub
				if( event.getAction() == MotionEvent.ACTION_MOVE || event.getAction() == MotionEvent.ACTION_DOWN )
				{
					if( appinfo.getCurrentstate() == ApplicationInfo.APP_PAUSE || appinfo.getCurrentstate() == ApplicationInfo.APP_DOWNLOADING 
							|| appinfo.getCurrentstate() == ApplicationInfo.APP_DOWNLOAD_COMPLATE)
					{
						virtualOrRealAppBackgroud( false );
					}
					else
					{
						virtualOrRealAppBackgroud( true );
					}
				}
				else
				{
					if( appinfo.getCurrentstate() == ApplicationInfo.APP_PAUSE || appinfo.getCurrentstate() == ApplicationInfo.APP_DOWNLOADING 
							|| appinfo.getCurrentstate() == ApplicationInfo.APP_DOWNLOAD_COMPLATE)
					{
						virtualOrRealAppBackgroud( true );
					}
					else
					{
						virtualOrRealAppBackgroud( false );
					}
				}
				return false;
			}
		} );
		this.setOnClickListener( new OnClickListener() {
			
			@Override
			public void onClick(
					View v )
			{
				// TODO Auto-generated method stub
				//this is patch,because when downloading to pause will waste long time(almost 500ms).  
				if( appinfo.getCurrentstate() == ApplicationInfo.APP_DOWNLOADING )
				{
					virtualOrRealAppBackgroud( true );
					badgeViewHolder.badge.setBackgroundDrawable( getResources().getDrawable( R.drawable.operatestart ) );
					badgeViewHolder.badge.setBadgePosition( BadgeView.POSITION_CENTER );
					badgeViewHolder.badge.show();
				}
				ChoiceApplication.getInstance().mDynamicEntrce.processIcon( AppView.this.appinfo );
				baseAdapter.notifyDataSetChanged();
				Log.v( "MyOpt" , "setOnClickListener" );
			}
		} );
	}
刷新adapter的getview函数

@Override
		public View getView(
				int position ,
				View convertView ,
				ViewGroup parent )
		{
			if( title.getVisibility() == View.INVISIBLE )
			{
				title.setVisibility( View.VISIBLE );
			}
			ApplicationInfo appinfo = mAllAppsList.get( position );
			if( convertView == null )
			{
				convertView = new AppView( getContext() , appinfo , this );
			}
			else
			{
				( (AppView)convertView ).updateaAppView( appinfo );
			}
			return convertView;
		}
	}
错误的原因就在data(appinfo)成为了AppView的一个成员,而getview中利用了view缓存更新成员appinfo,这样导致当用户快速点击adapter调用getview速度没有更上.

比如说点击的item 1的view,但是有可能它是利用了item 2 view的缓存,恰好刷新的速度没有更上,item 2 view关联的 data还是 item 2的data,就导致了如上Bug.

如何修正?

girdview中自定义view的监听提取出来放在girdview的onitemlistener中去实现,这样就不会导致刷新频率跟不上监听事件.

gridView.setOnItemClickListener( new AdapterView.OnItemClickListener() {
				
				@Override
				public void onItemClick(
						AdapterView<?> parent ,
						View view ,
						int position ,
						long id )
				{
					// TODO Auto-generated method stub
					//this is patch,because when downloading to pause will waste long time(almost 500ms).
					if( mAllAppsList.get(position).getCurrentstate() == ApplicationInfo.APP_DOWNLOADING )
					{
						mAllAppsList.get(position).setCurrentstate(ApplicationInfo.APP_PAUSE);
						imageAdapter.notifyDataSetChanged();
						mAllAppsList.get(position).setCurrentstate(ApplicationInfo.APP_DOWNLOADING);
					}
					ChoiceApplication.getInstance().mDynamicEntrce.processIcon( mAllAppsList.get(position) );
				}
			} );
这里又有一个新的问题
每一个自定义view需要有按下的效果是通过setOnTouchListener()实现的,但是如果在girdview去设置了setOnItemClickListener,自定义view是触发到setOnTouchListener事件的, 这个原因我也不知道为什么?

那么只好把setOnTouchListener放置在girdview的setOnTouchListener,代码如下:

private boolean itempressflag = false;    //in order to each touch only touch one item
	private int itempressposition = -1;		  //record each touch position
	private void setListeners()
	{
		if( gridView != null )
		{
			gridView.setSelector( new ColorDrawable( Color.TRANSPARENT ) );
			gridView.setOnTouchListener(new OnTouchListener() {
				
				@Override
				public boolean onTouch(View v, MotionEvent event) {
					// TODO Auto-generated method stub
					float currentXPosition = event.getX();
		            float currentYPosition = event.getY();
		            int position = gridView.pointToPosition((int) currentXPosition, (int) currentYPosition);
		            //position no equal to -1 prevent don't touch effective area 
		            //itempressflag must is false because should to prevent touch more than one item.
		            if(position != -1 && !itempressflag ){
			            if( event.getAction() == MotionEvent.ACTION_MOVE || event.getAction() == MotionEvent.ACTION_DOWN )
						{
			            	itempressflag = true;
							itempressposition = position;
							if( mAllAppsList.get(itempressposition).getCurrentstate() == ApplicationInfo.APP_PAUSE || mAllAppsList.get(itempressposition).getCurrentstate() == ApplicationInfo.APP_DOWNLOADING 
									|| mAllAppsList.get(itempressposition).getCurrentstate() == ApplicationInfo.APP_DOWNLOAD_COMPLATE)
							{
								((AppView)gridView.getChildAt(itempressposition)).virtualOrRealAppBackgroud( false );
							}
							else
							{
								((AppView)gridView.getChildAt(itempressposition)).virtualOrRealAppBackgroud( true );
							}
							
						}
		            }else{
		            	if(itempressflag){
		            		if(position != itempressposition){
		            			if( mAllAppsList.get(itempressposition).getCurrentstate() == ApplicationInfo.APP_PAUSE || mAllAppsList.get(itempressposition).getCurrentstate() == ApplicationInfo.APP_DOWNLOADING 
										|| mAllAppsList.get(itempressposition).getCurrentstate() == ApplicationInfo.APP_DOWNLOAD_COMPLATE)
								{
									((AppView)gridView.getChildAt(itempressposition)).virtualOrRealAppBackgroud( true );
								}
								else
								{
									((AppView)gridView.getChildAt(itempressposition)).virtualOrRealAppBackgroud( false );
								}
			      
		            		}
		            		if(event.getAction() == MotionEvent.ACTION_UP){
		            			if( mAllAppsList.get(itempressposition).getCurrentstate() == ApplicationInfo.APP_PAUSE || mAllAppsList.get(itempressposition).getCurrentstate() == ApplicationInfo.APP_DOWNLOADING 
										|| mAllAppsList.get(itempressposition).getCurrentstate() == ApplicationInfo.APP_DOWNLOAD_COMPLATE)
								{
									((AppView)gridView.getChildAt(itempressposition)).virtualOrRealAppBackgroud( true );
								}
								else
								{
									((AppView)gridView.getChildAt(itempressposition)).virtualOrRealAppBackgroud( false );
								}
			            		itempressflag = false;
			            		itempressposition = -1;
		            		}
		            	}
		            	
		            }
					return false;
				}
			});
总结:

1,如果girdview中的每一个sub view与数据相关联,不要在sub view中写监听器

2,girdview item同时实现onclick和ontouch同时实现的方式




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值