是否可以将可滚动的TextView添加到ListView?

时间:2011-11-14 12:20:32

标签: android android-layout android-listview textview android-scroll

我有一个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 个答案:

答案 0 :(得分:13)

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

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

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);

答案 1 :(得分: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;
    }

答案 2 :(得分: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;
  }

}

答案 3 :(得分: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;
    }
}