在ListView中使用HorizontalScrollView:微小的垂直滚动会使水平滚动停止。

5
在我的示例活动中,我有一个包含多个HorizontalScrollView的ListView,每个HorizontalScrollView都包含一组TextView。
然而,水平滚动的体验相当差。当我启动水平滚动(或快速滑动)时,必须非常小心才能使其正常工作。
一旦水平滚动包含了一个(小的)垂直组件,垂直ListView滚动就会接管并完全停止水平滚动。
有什么建议可以改善这种情况吗?
提前感谢,
Marc
import android.app.Activity;
import android.database.DataSetObserver;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class Test extends Activity 
{
private final static int N = 20;//number of HorizontalScrollView
private final static int M = 20;//number of TextViews inside a single HorizontalScrollView


@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    LinearLayout layout = new LinearLayout(this);
    //create a list of HorizontalScrollViews
    final HorizontalScrollView[] hors = new HorizontalScrollView[N];
    for (int i = 0; i < hors.length; i++)
    {
        hors[i] = new HorizontalScrollView(this, null);
        hors[i].setMinimumHeight(60);
        LinearLayout ll = new LinearLayout(this);
        ll.setOrientation(LinearLayout.HORIZONTAL);
        hors[i].addView(ll);
        for (int j = 0; j < M; j++)
        {
            TextView t = new TextView(Test.this);
            t.setText("HorizontalScrollView: "+i+"; TextView: "+j);
            t.setMinimumHeight(40);
            ll.addView(t);
        }
    }
    //add a ListView
    ListView list = new ListView(this);
    layout.addView(list);
    list.setAdapter(new BaseAdapter()
    {

        @Override
        public View getView(int position, View convertView, ViewGroup parent)
        {
            return hors[position];
        }

        @Override
        public long getItemId(int position)
        {
            return 0;
        }

        @Override
        public Object getItem(int position)
        {
            return hors[position];
        }

        @Override
        public int getCount()
        {
            return N;
        }
    });

    setContentView(layout);

}


}

我认为我可以重新表述这个问题,即“子视图是否能够接收被ListView父视图消耗的TouchEvents”。这将允许ListView处理移动的垂直部分,而HorizontalScrollView可以处理移动的水平部分。 - Marc Van Daele
4个回答

5
问题在于ListView(或其父类AbsListView)实现了onInterceptTouchEvent,因此只要ListView认为自己更适合处理触摸事件,它就可以拦截所有的触摸事件。
这可以通过调用requestDisallowInterceptTouchEvent来避免,例如通过继承HorizontalScrollView并在其dispatchTouchEvent方法中实现。
public boolean dispatchTouchEvent(MotionEvent ev)
{
  boolean ret = super.dispatchTouchEvent(ev);
  if(ret) 
  {
    requestDisallowInterceptTouchEvent(true);
  }
  return ret;
}       

它需要进行一些改进(比如只有当水平分量大于垂直分量时才调用requestDisallowInterceptTouchEvent),因为现在它几乎不允许ListView 接管控制。


1

虽然我没有深入研究你的代码,但人们通常犯的一个错误是将listView插入ScrollView中。

由于listview是自动滚动的,因此请将其放在scrollView之外,而其他内容可以放在scrollView中。

如果这是情况,请检查XML布局;否则,请分享XML布局。


我的ListView是父组件,HorizontalScrollViews是ListView的子组件(所以在您的情况下似乎是相反的)。我没有使用XML布局;所有视图都是在代码中创建的。 - Marc Van Daele

0

最佳方法是这样的。

将给定的代码放在您的水平ListView的onScroll方法中,它可以完美地工作。

   ViewParent view_parent = getParent();
   if (view_parent != null) 
   {
     view_parent.requestDisallowInterceptTouchEvent(true);
   }

0

我认为mTouchSlop在这里不相关。最初的问题是,一个轻微的垂直滚动会停止水平滚动,因为此时ListView接管了控制权。 - Marc Van Daele

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接