4

我有一个 ListView ,其中每一行都有一个固定的高度。
每行在一些图像旁边都包含一个 TextView。
有时,我想显示的文本太大,因此我想让它可滚动。
所以我添加(基于Making TextView scrollable on Android)将以下行添加到我的 TextView

text.setMaxLines(5);
text.setVerticalScrollBarEnabled(true);
text.setMovementMethod(ScrollingMovementMethod.getInstance());

如果我单独使用 TextView,但当我将 TextView 放在 ListView 中时,这很好用:
只要我进行垂直滚动,ListView 似乎就会消耗这些事件。

关于如何完成这项工作的任何建议?

下面添加了完整的(测试)活动(无 layout.xml)

public class TestScrollableTextView extends Activity
{ 
  protected void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);

    LinearLayout layout = new LinearLayout(this);
    //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)
        {
            TextView text = new TextView(TestScrollableTextView.this);
            String s = "";
            //add 10 lines of text, all but first are indented
            for (int i = 0; i < 10; i++)
            {
                if(i>0) s+="\t";
                s += "position "+position+"; line="+i+"\n";
            }
            text.setText(s);                
            text.setMaxLines(5);
            text.setVerticalScrollBarEnabled(true);
            text.setMovementMethod(ScrollingMovementMethod.getInstance());
            return text;
        }

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

        @Override
        public Object getItem(int position)
        {

            return null;
        }

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

      setContentView(layout);

  }
}
4

4 回答 4

14

getLineCount 和 getLineHieght 并检查 Text 是否大于 TextView。

如果您使用此代码,则可以通过使用 (boolean)isLarger = true 触摸 TextView 以外的任何位置来滚动 listView。

text.setText(s);                
text.setMaxLines(100);
text.setVerticalScrollBarEnabled(true);
text.setMovementMethod(new ScrollingMovementMethod());
OnTouchListener listener = new OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
                boolean isLarger;

                isLarger = ((TextView) v).getLineCount()
                        * ((TextView) v).getLineHeight() > v.getHeight();
                if (event.getAction() == MotionEvent.ACTION_MOVE
                        && isLarger) {
                    v.getParent().requestDisallowInterceptTouchEvent(true);

                } else {
                    v.getParent().requestDisallowInterceptTouchEvent(false);

                }
                return false;
            }
        };

text.setOnTouchListener(listener);
于 2013-03-03T19:59:52.430 回答
0

我可以通过创建 ListView 的子类并覆盖 onTouchEvent 来完成这项工作,如下所示:
- 我首先检查 MotionEvent 是否在 childView 内
- 如果是,我调用孩子的 onTouchEvent

这看起来确实是非常基本的框架功能,所以我很惊讶这不是由 ListView 本身处理的。我错过了什么吗?

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        //find correct child
        View theChild = null;
        boolean handled = false;
        for (int i = 0; i < getChildCount(); i++)
        {
            View child = getChildAt(i);
            Rect rect = new Rect();
            child.getDrawingRect(rect);
            offsetDescendantRectToMyCoords(child, rect);
            if(rect.contains((int)event.getX(), (int)event.getY()))
            {
                theChild = child;
            }
        }
        if(theChild!=null)
        {
            handled = theChild.onTouchEvent(event);
        }
        if(!handled) handled = super.onTouchEvent(event);

        return handled;
    }
于 2011-11-17T07:55:20.040 回答
0

更好的方法可能是创建自己的 MyTextView,如下所示并调用 requestDisallowInterceptTouchEvent。通过这样做,您向列表视图表明它不应该拦截事件。

class MyTextView extends TextView
{

  public MyTextView(Context context)
  {
    super(context);
    // TODO Auto-generated constructor stub
  }

  @Override
  public boolean dispatchTouchEvent(MotionEvent event)
  {
    boolean ret;
    ret = super.dispatchTouchEvent(event);
    if(ret)
    {
        list.requestDisallowInterceptTouchEvent(true);
    }
    return ret;
  }

}
于 2011-12-09T11:38:49.323 回答
0

使用此自定义来解决您的问题。

public class ScrollableListView extends ListView {

    public ScrollableListView(Context context) {
        super(context);
    }

    public ScrollableListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ScrollableListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        final int action = ev.getAction();
        switch (action) {
        case MotionEvent.ACTION_DOWN:
            Log.i("VerticalScrollview", "onInterceptTouchEvent: DOWN super false");
            super.onTouchEvent(ev);
            break;

        case MotionEvent.ACTION_MOVE:
            return false; // redirect MotionEvents to ourself

        case MotionEvent.ACTION_CANCEL:
            Log.i("VerticalScrollview", "onInterceptTouchEvent: CANCEL super false");
            super.onTouchEvent(ev);
            break;

        case MotionEvent.ACTION_UP:
            Log.i("VerticalScrollview", "onInterceptTouchEvent: UP super false");
            return false;

        default:
            Log.i("VerticalScrollview", "onInterceptTouchEvent: " + action);
            break;
        }

        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        super.onTouchEvent(ev);
        Log.i("VerticalScrollview", "onTouchEvent. action: " + ev.getAction());
        return true;
    }
}
于 2014-02-26T06:46:12.883 回答