当前位置: 代码迷 >> Android >> 【转】Android手势研究(textview及listview对照验证)(二)
  详细解决方案

【转】Android手势研究(textview及listview对照验证)(二)

热度:100   发布时间:2016-05-01 17:03:43.0
【转】Android手势研究(textview及listview对比验证)(二)

原文地址:http://mypyg.iteye.com/blog/761461

?

在上文中我们对手势操作进行了基本验证,
我们将上文中添加第二个textview的改为添加Listview,代码如下:

Java代码 复制代码?收藏代码
  1. ListView?lv?=?new?ListView(this); ??
  2. lv.setBackgroundColor(0xff808080); ??
  3. final?String[]?items?=?{"one",?"two",?"three"}; ??
  4. lv.setAdapter(new?ArrayAdapter<String>(this,?android.R.layout.simple_list_item_1,?items)); ??
  5. mVf.addView(lv,new?LayoutParams(LayoutParams.WRAP_CONTENT,?LayoutParams.WRAP_CONTENT));??
ListView lv = new ListView(this);lv.setBackgroundColor(0xff808080);final String[] items = {"one", "two", "three"};lv.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items));mVf.addView(lv,new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));


执行ap,滑动屏幕切换到第二屏,可以看到第二屏被换成了一个ListView,
并且没有填充完整个屏幕,这时如果在底部非ListView区域向左滑动,
仍然可以切换到第一屏,但是在Listview区域滑动就没有效果了,
因为touch事件被Listview处理了,ViewFlipper无法收到touch事件也就无法进行手势判断。
我们给ListView也增加一个touch事件监听器,代码如下:

Java代码 复制代码?收藏代码
  1. lv.setOnTouchListener(new?OnTouchListener()?{??????????? ??
  2. ????@Override??
  3. ????public?boolean?onTouch(View?v,?MotionEvent?event)?{ ??
  4. ????????return?mVfDetector.onTouchEvent(event); ??
  5. ????} ??
  6. });??
lv.setOnTouchListener(new OnTouchListener() {				@Override	public boolean onTouch(View v, MotionEvent event) {		return mVfDetector.onTouchEvent(event);	}});


此时在ListView上滑动也能实现屏幕切换了。
我们再给Listview增加响应点击事件的处理,代码如下:

Java代码 复制代码?收藏代码
  1. lv.setOnItemClickListener(new?OnItemClickListener()?{ ??
  2. ????@Override??
  3. ????public?void?onItemClick(AdapterView<?>?arg0,?View?arg1,? ??
  4. ????????int?arg2,?long?arg3)?{ ??
  5. ????????new?AlertDialog.Builder(MainActivity.this) ??
  6. ????????????.setMessage(items[arg2]) ??
  7. ????????????.create() ??
  8. ????????????.show();???????????????? ??
  9. ????} ??
  10. });??
lv.setOnItemClickListener(new OnItemClickListener() {	@Override	public void onItemClick(AdapterView<?> arg0, View arg1, 		int arg2, long arg3) {		new AlertDialog.Builder(MainActivity.this)			.setMessage(items[arg2])			.create()			.show();					}});


当点击Listview的条目的时候,就会弹出窗口显示点击了哪一项,此时的代码可参见附件1。
截止到此时,似乎Listview支持左右滑动的操作完成了,但实际上仍有两个问题:
首先就是滑动时,Listview有时会有条目被高亮,这个问题倒还不是太严重。
再次就是ContextMenu每次滑动都会被激活,我们可以通过代码验证,
创建ListView的代码稍作修改:

Java代码 复制代码?收藏代码
  1. //使Listview长一些 ??
  2. final?String[]?items?=?{"one",?"two",?"three",?"four",?"five",?"six",?"sevent",?"eight",?"nine"};? ??
  3. registerForContextMenu(lv);??
//使Listview长一些final String[] items = {"one", "two", "three", "four", "five", "six", "sevent", "eight", "nine"}; registerForContextMenu(lv);


另外Activity的代码增加:

Java代码 复制代码?收藏代码
  1. @Override??
  2. public?void?onCreateContextMenu(ContextMenu?menu,?View?v,?ContextMenuInfo?menuInfo)?{ ??
  3. ????????menu.add("Menu?1"); ??
  4. ????????menu.add("Menu?2"); ??
  5. ????????menu.add("Menu?3"); ??
  6. ????super.onCreateContextMenu(menu,?v,?menuInfo); ??
  7. }??
@Overridepublic void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {    	menu.add("Menu 1");    	menu.add("Menu 2");    	menu.add("Menu 3");	super.onCreateContextMenu(menu, v, menuInfo);}


当我们在ListView的某一项上长按时就会弹出菜单,
但是当滑动时,即使屏幕切换到了第一屏,此菜单仍然会弹出。
此时的验证代码参加附件2。

为了解决上面的问题,我尝试了以下办法:
1.在ListView的touch事件监听函数中始终返回true,吃掉所有事件,
这样的修改导致不能相应点击,ListView不能上下滑动,此路不通。
2.在GestureDetector的fling函数中向ListView发送一个MotionEvent.ACTION_CANCEL事件,
总是空指针异常,怀疑是因为touch事件没有被ListView处理过,其内部成员状态异常,
于是我从ListView继承实现了一个ListView,在onTouchEvent中呼叫super.onTouchEvent,但是发送MotionEvent.ACTION_CANCEL事件时仍然是空指针异常,再次失败。
3.GestureDetector的onDown函数返回true,吃掉down事件,此时点击时没有高亮项了,
切换时contextmenu也不被trigger了,但是长按也无法弹出contextmenu了。
为了能弹出contextMenu,那么就要在GestureDetector的onLongPress函数中调用ListView.showContextMenuForChild()来弹出菜单,
那么GestureDetector就与ViewFlipper的不通用了,
所以我重新由ListView继承实现了一个类,这个类自身绑定了一个GestureDetector:

Java代码 复制代码?收藏代码
  1. @Override??
  2. public?boolean?onDown(MotionEvent?e)?{ ??
  3. ????return?true;????//吃掉Down事件 ??
  4. } ??
  5. @Override??
  6. public?void?onLongPress(MotionEvent?e)?{???? ??
  7. ????System.out.println("Listview?long?press"); ??
  8. ????int?position?=?pointToPosition((int)e.getX(),?(int)e.getY());??????????????? ??
  9. ????if(?position?!=?ListView.INVALID_POSITION)?{ ??
  10. ????????View?child?=?getChildAt(position?-?getFirstVisiblePosition()); ??
  11. ????????if(child?!=?null)?GestureListView.this.showContextMenuForChild(child); ??
  12. ????} ??
  13. }??
@Overridepublic boolean onDown(MotionEvent e) {	return true;	//吃掉Down事件}@Overridepublic void onLongPress(MotionEvent e) {		System.out.println("Listview long press");	int position = pointToPosition((int)e.getX(), (int)e.getY());					if( position != ListView.INVALID_POSITION) {		View child = getChildAt(position - getFirstVisiblePosition());		if(child != null) GestureListView.this.showContextMenuForChild(child);	}}


另外为了能够显示contextmenu时在哪一项上激活的,在Activity增加函数:

Java代码 复制代码?收藏代码
  1. @Override??
  2. public?boolean?onContextItemSelected(MenuItem?item)?{ ??
  3. ????AdapterContextMenuInfo?info?=?(AdapterContextMenuInfo)?item.getMenuInfo(); ??
  4. ????System.out.println("View?"?+?info.position?+?"?context?menu?activited."); ??
  5. ????return?super.onContextItemSelected(item); ??
  6. }??
@Overridepublic boolean onContextItemSelected(MenuItem item) {	AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();	System.out.println("View " + info.position + " context menu activited.");	return super.onContextItemSelected(item);}


从LogCat即可看到打印输出。
此时此ListView可以响应手势、可以响应点击、可以弹出菜单,
基本的功能已经满足,另外再微调一下ondown函数,当点击时可以高亮一下。
最终代码可参见附件3。
PS:
最好的办法还是直接从AbsListView来修改,将左右方向手势判断加入进去,待研究。

  相关解决方案