Можно ли добавить прокручиваемый TextView в ListView? - PullRequest
4 голосов
/ 14 ноября 2011

У меня есть ListView, где каждая строка имеет фиксированную высоту.
Каждая строка содержит рядом с некоторыми изображениями TextView.
Иногда текст, который я хочу отобразить, слишком велик, и поэтому я хотел бы сделать его прокручиваемым.
Поэтому я добавил (основываясь на Создание прокрутки TextView на 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 ]

13 голосов
/ 03 марта 2013

getLineCount и getLineHieght и проверьте, больше ли Text, чем TextView.

если вы используете этот код, listView можно прокрутить, коснувшись в любом месте, кроме TextView, с (логическим) 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);
0 голосов
/ 26 февраля 2014

Используйте этот Custom для решения вашей проблемы.

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;
    }
}
0 голосов
/ 09 декабря 2011

Возможно, лучшим способом будет создать свой собственный 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;
  }

}
0 голосов
/ 17 ноября 2011

Я могу сделать это, создав подкласс 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;
    }
...