之前写过ListView和ScrollView嵌套滑动冲突问题,最近刚好遇到ListView的子View包含可以获取焦点的情况,这种情况下只是单纯的给ListView设置onTouchListener会经常失效,也就是滑动冲突重新出现了。
经过同事提点,我自己也测试了一下,解决滑动冲突的成功率果然提高了很多,话不多说,赶紧分享一下。
最开始解决冲突的方式:
listView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
//关键是这一句
scrollView.requestDisallowInterceptTouchEvent(true);
return false;
}
});
这是最简单的,要做ListView和ScrollView滑动能力自动切换可以看一下我之前的一篇分享。下面直接说这次的重点,ListView的ItemView里包含了Button,CheckBox,EditText(尤其是这个)等会获取焦点的控件,解决冲突的方式其实和之前的差不多,我们在自定义的adapter里增加onTouchListener的对象,在构造函数或者另外提供一个set方法,将用于解决冲突的onTouchListener传进ItemView里。
下面是代码
TestAdapter testAdapter = new TestAdapter(this, Arrays.asList(testArray), new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
//判断是否为滑动,是滑动则让scrollView不可滑动
//这里只判断了滑动,可根据需要判断主要滑动方向(要用到ACTION_DOWN 和ACTION_UP),
//我这对解决冲突的精度没有特别高要求,就单纯判断滑动就完事了
if(event.getAction() == MotionEvent.ACTION_MOVE){
scrollView.requestDisallowInterceptTouchEvent(true);
}
return false;
}
});
然后在会获取焦点的控件里,给它设置传进去的onTouchListener
@Override
public View getView(int position, View convertView, ViewGroup parentView){
ViewHolder holder;
if(convertView == null){
convertView = View.inflate(mContext, R.layout.test_item, null);
holder = new ViewHolder();
holder.tvLabel = (TextView) convertView.findViewById(R.id.tvLabel);
holder.etValue = (EditText) convertView.findViewById(R.id.etValue);
//这个控件会获得焦点,直接给它设置onTouchListener
holder.etValue.setOnTouchListener(onTouchListener);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.tvLabel.setText(dataList.get(position));
holder.etValue.setText(dataList.get(position));
return convertView;
}
冲突问题到这就基本解决了。
其实最开始我还尝试使用过
android:descendantFocusability="blocksDescendants"
但是基本上没效果。最后才用这么麻烦的方法。注意这个方法里没有对ListView包含EditText会导致的数据紊乱,光标异常这些问题进行处理,所以说如果用到TextWatcher这些还是需要自己再处理一下的,记录好位置就好了,有空也分享一下这个,但这个网上也有很多,找一下就好了。