Is it possible to add scrollable TextView to ListView?

I have a ListView where each row has a fixed height.
Each row contains next to some TextView images.
Sometimes the text I want to display is too large, and so I would like to make it scrollable.
So I added (based on Scrolling TextView on Android ) the following lines to my TextView

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

This works fine if I use TextView separately, but not when I put a TextView in a ListView:
as soon as I do a vertical scroll, the events seem to be consumed by the ListView.

Any suggestions on how I can make this work?

Below is the full (test) activity (no 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
source share
4 answers

It is best to probably create your own MyTextView as follows and call requestDisallowInterceptTouchEvent. By doing so, you indicate to the list that "events should not be intercepted."

 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
source

getLineCount and getLineHieght and check if the text is longer than a TextView.

if you use this code, the listView can be scrolled by touching anywhere other than the TextView using (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); 
+11
source

I can do this work by subclassing the ListView and overriding onTouchEvent as follows:
- I first check if the MotionEvent is inside the childView
- if so, I call child onTouchEvent

This is really pretty basic functionality, so I am surprised that the ListView itself is not being processed. Did I miss something?

  @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; } 
0
source

Use this custom option to solve your problem.

 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
source

Source: https://habr.com/ru/post/1381120/


All Articles