关于android下面girdview item同时实现onclick和ontouch的一点心得.
2014-06-12 21:33
357 查看
源于一个bug.这个bug的是这样.下面是一个girdview当用户反复点击某一个自定义item的时候,比如说是1 ,会导致item 3响应.查了一下原因是由于
onclick实现的架构错误引起的,监听器源代码如下
比如说点击的item 1的view,但是有可能它是利用了item 2 view的缓存,恰好刷新的速度没有更上,item 2 view关联的 data还是 item 2的data,就导致了如上Bug.
如何修正?
girdview中自定义view的监听提取出来放在girdview的onitemlistener中去实现,这样就不会导致刷新频率跟不上监听事件.
每一个自定义view需要有按下的效果是通过setOnTouchListener()实现的,但是如果在girdview去设置了setOnItemClickListener,自定义view是触发到setOnTouchListener事件的,这个原因我也不知道为什么?
那么只好把setOnTouchListener放置在girdview的setOnTouchListener,代码如下:
1,如果girdview中的每一个sub view与数据相关联,不要在sub view中写监听器
2,girdview item同时实现onclick和ontouch同时实现的方式
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同时实现的方式
相关文章推荐
- android 关于view的onTouch和onClick同时触发解决方案
- android 关于view的onTouch和onClick同时触发解决方案
- Android关于OnTouch 和OnClick同时调用冲突的解决方案
- 关于android多任务同时下载的一点心得
- Android关于OnTouch 和OnClick同时调用冲突的解决方案
- Android关于OnTouch 和OnClick同时调用冲突的解决方案
- Android关于OnTouch 和OnClick同时调用冲突的解决方案
- Android关于OnTouch 和OnClick同时调用冲突的解决方案
- Android关于OnTouch 和OnClick同时调用冲突的解决方案
- Android OnTouch 和OnClick同时调用冲突问题(单个View)
- Android关于OnTouch 和OnClick同时调用冲突 重复
- 关于做Android+J2ee系统集成开发的一点心得
- 关于做Android+J2ee系统集成开发的一点心得
- 【android】ListView的item事件和item里面的view的事件同时存在
- 关于做Android+J2ee系统集成开发的一点心得
- android中ListView点击和ListView的item里面的button或ImageView不能同时生效的解决
- 关于做Android+J2ee系统集成开发的一点心得
- 关于做android+J2ee系统集成开发的一点心得
- Android 用ScrollView和HorizontalScrollView同时实现上下、左右滚动
- 关于做Android+J2ee系统集成开发的一点心得