返回腳本百事通
php
這裏正好在項目有這麼一個bt的需求,以下圖ListView的item能夠響應點擊事件也能夠響應item的左右滑動事件,兩個事件能夠相互獨立互不影響。html
據說iphone的list選項就有這樣bt的功能,安卓版的手機QQ和微信和QQ通信錄也有相似的效果,在網上各類尋早方案都試過,要不僅能滑動不能點擊要麼就只能點擊不能滑動,並且操做很不靈敏,網上的代碼都是在itemView的onTouch方法裏處理,判斷down和up的像素差。其實這樣操做至關不便,down-up這樣的其實只能算拖動事件而不是滑動事件,因此你會聯想到scroll和fling的區別。前端
你們能夠看看我以前的作法,使用ontouch方法處理的,很難獨立滑動事件跟點擊事件,就算能夠滑動也是很靈敏,操做10次可貴一次成功。web
class SwipeListener implements View.OnTouchListener{
ViewHolder holder;
HouseList_Item item;
int startX = 0;
int endX = 0;
public SwipeListener(ViewHolder holder, HouseList_Item item) {
super();
this.holder = holder;
this.item = item;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if(event.getAction() == MotionEvent.ACTION_DOWN){
startX = (int)event.getX();
Debuger.log_e("startX", ""+startX);
return true;
}else if(event.getAction() == MotionEvent.ACTION_UP){
endX = (int)event.getX();
Debuger.log_e("endX", ""+endX);
if(startX - endX > 120){
Debuger.log_e("觸發", "左劃");
holder.llMenu.setVisibility(View.VISIBLE);
return false;
}else if(endX - startX >120){
Debuger.log_e("觸發", "右劃");
holder.llMenu.setVisibility(View.GONE);
return true;
}else{
Toast.makeText(ctx, "點擊item", 3000).show();
return true;
}
}
return true;
}
}面試
代碼有註釋相信你們都看得懂,像上面這樣子也差很少讓滑動事件和點擊事件獨立出來了。一開始還傻乎乎的用ListView的OnItemClick事件,搭配這樣功能真的是碉堡。微信
通過半天的努力探索,今天終於很流暢得實現這效果。下面是新的代碼:eclipse
這個是適配器的代碼,有部分省略,主要是GestureDetector 這樣一個手勢監聽器。iphone
public class HouseList_Adapter extends BaseAdapter{
private GestureDetector detector;
private List<HouseList_Item> list ;
private Context ctx = null;
private LayoutInflater inflater = null;
FlingListeber listener;
public HouseList_Adapter( Context ctx,List<HouseList_Item> list) {
super();
this.list = list;
this.ctx = ctx;
inflater = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
listener = new FlingListeber();
detector = new GestureDetector(listener);
}
@Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
// TODO Auto-generated method stub
ViewHolder holder = null;
if(arg1==null){
arg1 = inflater.inflate(R.layout.house_item_layout, null);
holder = new ViewHolder();
holder.llItem = (LinearLayout)arg1.findViewById(R.id.llItem);
holder.tvTitle = (TextView)arg1.findViewById(R.id.tvTitle);
holder.tvBuildeArea = (TextView)arg1.findViewById(R.id.tvArea);
holder.tvPrice = (TextView)arg1.findViewById(R.id.tvPrice);
holder.tvPriceUnit = (TextView)arg1.findViewById(R.id.tvPriceUnit);
holder.tvRoom = (TextView)arg1.findViewById(R.id.tvRoom);
holder.llFlag = (LinearLayout)arg1.findViewById(R.id.llFlag);
holder.ivFlag1 = (ImageView)arg1.findViewById(R.id.ivFlag1);
holder.ivFlag2 = (ImageView)arg1.findViewById(R.id.ivFlag2);
holder.ivFlag3 = (ImageView)arg1.findViewById(R.id.ivFlag3);
holder.ivFlag4 = (ImageView)arg1.findViewById(R.id.ivFlag4);
holder.llMenu = (LinearLayout)arg1.findViewById(R.id.house_ltem_menu);
holder.ivCall = (Button)arg1.findViewById(R.id.ivCall);
holder.ivDetails = (Button)arg1.findViewById(R.id.ivCall);
holder.ivMap = (Button)arg1.findViewById(R.id.ivMap);
holder.ivSend = (Button)arg1.findViewById(R.id.ivSend);
arg1.setTag(holder);
}else{
holder = (ViewHolder)arg1.getTag();
}
final HouseList_Item item = list.get(arg0);
listener.setItem(item);
//holder.llItem.setOnTouchListener(new SwipeListener(holder,item));
holder.llItem.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return detector.onTouchEvent(event);
}
});
}
class FlingListeber implements GestureDetector.OnGestureListener{
HouseList_Item item;
ViewHolder holder;
public HouseList_Item getItem() {
return item;
}
public void setItem(HouseList_Item item) {
this.item = item;
}
public ViewHolder getHolder() {
return holder;
}
public void setHolder(ViewHolder holder) {
this.holder = holder;
}
@Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// TODO Auto-generated method stub
if(e2.getX()-e1.getX()>20){
Toast.makeText(ctx, "左滑"+item.areaName, 3000).show();
}else if(e1.getX()-e2.getX()>20){
Toast.makeText(ctx, "右滑"+item.areaName, 3000).show();
}
return false;
}
@Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
// TODO Auto-generated method stub
return false;
}
@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
Toast.makeText(ctx, "點擊item", 3000).show();
return false;
}
}
} 異步
這樣讓item的滑動事件交給onFling去處理,點擊事件交給onSingleTapUp這樣就可讓兩個事件相互獨立了,可是這樣執行發現仍是會有很不暢滑動的時候,後來我一想那確定是listview的上下滑動跟item的左右滑動事件有衝突,因此就把以前定義的一個ScrollView裏處理touch事件拷過去就很靈敏了,百發百中。ide
// 滑動距離及座標
private float xDistance, yDistance, xLast, yLast;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
xDistance = yDistance = 0f;
xLast = ev.getX();
yLast = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
final float curX = ev.getX();
final float curY = ev.getY();
xDistance += Math.abs(curX - xLast);
yDistance += Math.abs(curY - yLast);
xLast = curX;
yLast = curY;
if(xDistance > yDistance){
return false;
}
}
return super.onInterceptTouchEvent(ev);
}
把這段代碼複製到一個ListView的擴展類裏覆蓋就行。
原文連接:/link.php?url=http://www.cnblogs.com/bvin/p/3153191.html,轉載請註明。