是否可以添加一个可滚动的TextView到ListView



我有一个ListView,每一行都有一个固定的高度。
每一行都包含一个TextView,旁边是一些图片。
有时,我想要显示的文本太大,因此我想让它可滚动。
所以我添加了(基于在Android上使TextView可滚动)以下行到我的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);
  }
}

getLineCount和getlineheight并检查文本是否大于TextView。

如果你使用这段代码,listView可以通过触摸TextView以外的任何地方来滚动(boolean) isbigger = 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);

我可以通过创建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;
    }

一个更好的方法可能是创建自己的MyTextView如下并调用requestDisallowInterceptTouchEvent。通过这样做,您可以向listview指示它不应该拦截事件。

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

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

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

相关内容

  • 没有找到相关文章

最新更新