- <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
- <ScrollView
- android:id="@+id/scrollview"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
- <ListView
- android:id="@+id/listview"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" >
- </ListView>
- </ScrollView>
- </FrameLayout>
然后我发现了ScrollView有一个属性,叫 android:fillViewport="true",如果设置这个属性为true,那么ListView会全屏显示,但是依旧不可滑动。先看看这个属性是什么意思。
XML Attributes | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
android:fillViewport | setFillViewport(boolean) | Defines whether the scrollview should stretch its content to fill the viewport. |
- <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
- <ScrollView
- android:id="@+id/scrollview"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- <span style="color:#ff0000;">android:fillViewport="true"</span> >
- <ListView
- android:id="@+id/listview"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" >
- </ListView>
- </ScrollView>
- </FrameLayout>
- public class Utility {
- public static void setListViewHeightBasedOnChildren(ListView listView) {
- ListAdapter listAdapter = listView.getAdapter();
- if (listAdapter == null) {
- // pre-condition
- return;
- }
- int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
- for (int i = 0; i < listAdapter.getCount(); i++) {
- View listItem = listAdapter.getView(i, null, listView);
- if (listItem instanceof ViewGroup) {
- listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
- }
- listItem.measure(0, 0);
- totalHeight += listItem.getMeasuredHeight();
- }
- ViewGroup.LayoutParams params = listView.getLayoutParams();
- params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
- listView.setLayoutParams(params);
- }
- }
好了,解决了ListView显示不全的问题,下一步要解决的就是ListView滑动的问题了。
有大神说可以重写ScrollView,拦截相关的点击事件,已达到listview可以滑动的效果。
- public class VerticalScrollview extends ScrollView {
- public VerticalScrollview(Context context) {
- super(context);
- }
- public VerticalScrollview(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- public VerticalScrollview(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;
- }
- }
另外,还可以对ListView设置onTouchListener,在onTouch中去控制外层ScrollView是否拦截触摸事件。
- mListView.setOnTouchListener(new OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- int action = event.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- // Disallow ScrollView to intercept touch events.
- v.getParent().requestDisallowInterceptTouchEvent(true);
- break;
- case MotionEvent.ACTION_UP:
- // Allow ScrollView to intercept touch events.
- v.getParent().requestDisallowInterceptTouchEvent(false);
- break;
- }
- // Handle ListView touch events.
- v.onTouchEvent(event);
- return true;
- }
- });
可以重写ListView去解决这个问题,这个是我所知道的最好的解决方案。
- public class NestedListView extends ListView implements OnTouchListener,
- OnScrollListener {
- private int listViewTouchAction;
- private static final int MAXIMUM_LIST_ITEMS_VIEWABLE = 99;
- public NestedListView(Context context, AttributeSet attrs) {
- super(context, attrs);
- listViewTouchAction = -1;
- setOnScrollListener(this);
- setOnTouchListener(this);
- }
- @Override
- public void onScroll(AbsListView view, int firstVisibleItem,
- int visibleItemCount, int totalItemCount) {
- if (getAdapter() != null
- && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
- if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
- scrollBy(0, -1);
- }
- }
- }
- @Override
- public void onScrollStateChanged(AbsListView view, int scrollState) {
- }
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- int newHeight = 0;
- final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
- if (heightMode != MeasureSpec.EXACTLY) {
- ListAdapter listAdapter = getAdapter();
- if (listAdapter != null && !listAdapter.isEmpty()) {
- int listPosition = 0;
- for (listPosition = 0; listPosition < listAdapter.getCount()
- && listPosition < MAXIMUM_LIST_ITEMS_VIEWABLE; listPosition++) {
- View listItem = listAdapter.getView(listPosition, null,
- this);
- // now it will not throw a NPE if listItem is a ViewGroup
- // instance
- if (listItem instanceof ViewGroup) {
- listItem.setLayoutParams(new LayoutParams(
- LayoutParams.WRAP_CONTENT,
- LayoutParams.WRAP_CONTENT));
- }
- listItem.measure(widthMeasureSpec, heightMeasureSpec);
- newHeight += listItem.getMeasuredHeight();
- }
- newHeight += getDividerHeight() * listPosition;
- }
- if ((heightMode == MeasureSpec.AT_MOST) && (newHeight > heightSize)) {
- if (newHeight > heightSize) {
- newHeight = heightSize;
- }
- }
- } else {
- newHeight = getMeasuredHeight();
- }
- setMeasuredDimension(getMeasuredWidth(), newHeight);
- }
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (getAdapter() != null
- && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
- if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
- scrollBy(0, 1);
- }
- }
- return false;
- }
- }
参考资料
http://stackoverflow.com/questions/6210895/listview-inside-scrollview-is-not-scrolling-on-android
http://developer.android.com/reference/android/widget/ScrollView.html