Android中ListView与ScrollView混合使用

来源:互联网 发布:java 多线程 字典 编辑:程序博客网 时间:2024/05/16 09:14

ListView与ScrollView混合使用主要有两种效果:

1、ListView在ScrollView中高度固定。滑动ListView时,ListView滚动。ListView到头或者滑动ScrollView时整个页面滚动。

listView.setOnTouchListener(new View.OnTouchListener() {          @Override      public boolean onTouch(View v, MotionEvent event) {          if(event.getAction() == MotionEvent.ACTION_UP){              scrollView.requestDisallowInterceptTouchEvent(false);          }else{              scrollView.requestDisallowInterceptTouchEvent(true);          }          return false;      }  }); 
2、整个ListView显示在ScrollView中,随ScrollView一起滑动。

实现原理:计算整个ListView的高度,填充数据后重新设置ListView高度。

listView.setAdapter(adapter);setListViewHeightBasedOnChildren(listView);
    <pre name="code" class="java">public static void setListViewHeightBasedOnChildren(ListView listView) {          ListAdapter listAdapter = listView.getAdapter();           if (listAdapter == null) {              // pre-condition              return;          }            int totalHeight = 0;          for (int i = 0; i < listAdapter.getCount(); i++) {              View listItem = listAdapter.getView(i, null, listView);              listItem.measure(0, View.MeasureSpec.makeMeasureSpec(0,    View.MeasureSpec.UNSPECIFIED));              totalHeight += listItem.getMeasuredHeight();          }            ViewGroup.LayoutParams params = listView.getLayoutParams();          params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));          listView.setLayoutParams(params);      }

注意:一定要在填充完数据再设置高度。
正常情况下使用上面的方法就可以实现ListView的高度计算了,但有时会出现item中的TextView中数据过长而多行显示的问题,这时计算的高度就会出现偏差。

解决方法:目前网上找到的主要有两种,一是重写TextView(还没试过),二是重写ListView(正在使用)。

重写TextView中的onMeasure()方法

@Override      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {          super.onMeasure(widthMeasureSpec, heightMeasureSpec);            Layout layout = getLayout();          if (layout != null) {              int height = (int)FloatMath.ceil(getMaxLineHeight(this.getText().toString()))                      + getCompoundPaddingTop() + getCompoundPaddingBottom();              int width = getMeasuredWidth();                          setMeasuredDimension(width, height);          }      }        private float getMaxLineHeight(String str) {          float height = 0.0f;          float screenW = ((Activity)context).getWindowManager().getDefaultDisplay().getWidth();          float paddingLeft = ((LinearLayout)this.getParent()).getPaddingLeft();          float paddingReft = ((LinearLayout)this.getParent()).getPaddingRight();          //这里具体this.getPaint()要注意使用,要看你的TextView在什么位置,这个是拿TextView父控件的Padding的,为了更准确的算出换行          int line = (int) Math.ceil( (this.getPaint().measureText(str)/(screenW-paddingLeft-paddingReft)));         height = (this.getPaint().getFontMetrics().descent-this.getPaint().getFontMetrics().ascent)*line;         return height;    }
重写ListView中的onMeasure()方法
@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// TODO Auto-generated method stubint expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,  MeasureSpec.AT_MOST);super.onMeasure(widthMeasureSpec, expandSpec);}

ListView:

import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.ListView;public class ListViewForScrollView extends ListView {public ListViewForScrollView(Context context) {super(context);}public ListViewForScrollView(Context context, AttributeSet attrs) {super(context, attrs);}public ListViewForScrollView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {try {int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);super.onMeasure(widthMeasureSpec, expandSpec);} catch (Exception e) {}}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {// TODO Auto-generated method stubswitch (ev.getAction()) {case MotionEvent.ACTION_DOWN:this.requestDisallowInterceptTouchEvent(true);break;default:break;}return super.onInterceptTouchEvent(ev);}}

0 0