解决scrollview与listview共存问题 计算listview的宽高(item中有imageview)
2016-02-18 21:19
351 查看
前言:
由于在项目中遇到listview与scrollView共存的时候,导致listview无法正常显示,或者说是有时候只显示一条item的情况,在网上查找了好多资料,基本都是
1.重写listview的onmeasure()方法,使listview能适应scrollview的效果
3....
4...
其他方法我都不做赘述了,基本上网上都能找到资料。
我自己在项目中遇到的问题:
1.我的imageView是设置的GONE的,所以在测量的时候有点麻烦,并不太合适以上的方法
2.当图片右侧的textview占据2行的或者多行的时候,计算的高度并不准确,或者说当多行的时候系统仅仅测量了一行的高度给了textview
而我用的就是计算listview的item的高度,来确定listview的高度,在网上查阅了资料,但是并不合适我所以自己改了下,以下是listView的Item的计算代码:
*要用这个方法listview的Item的父布局一定要用linearlayout,因为Lieanralayout里面重写了view的onMeasure()方法
具体的细节这个没了解,没研究过Lieanrlayout的源码!
以下是dimens以及布局代码:
item布局代码:
到这里仅仅只解决了我遇到的第一个问题,而第二个问题计算textView的高度就要自定义一个TextView来重写它的OnMeasure()
下面是我自定的TextView的代码:
而这样基本就解决,只要调用以下代码就行了
最后:
当然我自己认为还有另一种解决方案,因为这样通过计算listview的高度来解决ScrollView和listView共存的时候,所有的item都会遍历出来,如果item条数多的话,这样就并不太合适。我自己的想法是可以定死listView的高度,然后根据自己的业务需求通过重写ScrollView的dispatchTouchEvent方法解决scrollView与listView的滑动冲突,这样遇到listView中Item数多的情况下就能优化性能了。
由于自己的经验和技术有限,可能自己方法并不是最好的,或者说代码中有问题,希望各位能理解并指点,最后希望能和我一样遇到同样问题的朋友都能解决自己的问题。
由于在项目中遇到listview与scrollView共存的时候,导致listview无法正常显示,或者说是有时候只显示一条item的情况,在网上查找了好多资料,基本都是
1.重写listview的onmeasure()方法,使listview能适应scrollview的效果
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); }2.就是自定义一个linearlayout,来代替scrollview,使listview能正常显示。
3....
4...
其他方法我都不做赘述了,基本上网上都能找到资料。
我自己在项目中遇到的问题:
1.我的imageView是设置的GONE的,所以在测量的时候有点麻烦,并不太合适以上的方法
2.当图片右侧的textview占据2行的或者多行的时候,计算的高度并不准确,或者说当多行的时候系统仅仅测量了一行的高度给了textview
而我用的就是计算listview的item的高度,来确定listview的高度,在网上查阅了资料,但是并不合适我所以自己改了下,以下是listView的Item的计算代码:
*要用这个方法listview的Item的父布局一定要用linearlayout,因为Lieanralayout里面重写了view的onMeasure()方法
具体的细节这个没了解,没研究过Lieanrlayout的源码!
public void getListViewHeight(ListView listView, Context context) { // 获取listView的高度 这里只是伪代码 // listview与Adapter要看你自己项目用的是哪种 Adapter adapter = listView.getAdapter(); if (adapter == null) { return ; } int listViewHeight = 0; int itemHeight = 0; for (int i = 0; i < adapter.getCount(); i++) { // 这里遍历listview中的item个数 View listItem = adapter.getView(i, null, listView); // 我在item中有图片,但是不确定是否显示 ImageView imageView = (ImageView) listItem .findViewWithTag("itemImage"); /** * 获取imageView的高度,是为了与item的高度想比,判断imageView的高度是否高于测量的Item的高度 但是不支持这样做,最好为imageView确定一个固定的高度,这样才能为后面的图片压缩做处理 同样的imageView设定固定的高度也能让你listView的item更好看 再者这里不能用ImageView.getHeight()的方法,因为我这些操作都是在Fragment的Oncreate()中进行的 此时的ImageView并没有显示出来,所以ImageView.getHeight()还是0 而只能获取测量的宽高int imageHeight = imageView.getMeasuredHeight(); */ //我是在dimens中定义了imageView的高度 int imageHeight = context.getResources().getDimensionPixelOffset(R.dimen.item_height); //由于我的imageView是隐藏的View.GONE 所以我在getView()中setTag来判断图片是否显示(根据服务端传来的json判断) if(listItem.getTag().equals("有图片")){ if(imageHeight > listItem.getMeasuredHeight()){ itemHeight = imageHeight; }else if(listItem.getTag().equals("没图片")){ itemHeight = listItem.getMeasuredHeight(); } } /** * 这个方法一定要,因为当测量宽高的时候要提供父View对子View的约束信息 * 而listView的高度我们又不确定是wrap_content所以传入0,0 相当于UNSPECIFIED */ listItem.measure(0, 0); listViewHeight += itemHeight; } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = listViewHeight + (listView.getDividerHeight() * (adapter.getCount() - 1)); listView.setLayoutParams(params); }
以下是dimens以及布局代码:
<dimen name="item_image_width">100dp</dimen> <dimen name="item_image_height">160dp</dimen> <dimen name="text_span_width">100dp</dimen>
item布局代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:background="#ffffff" > <ImageView android:layout_width="@dimen/item_image_width" android:layout_height="@dimen/item_image_height" android:tag="text" android:scaleType="centerInside" android:visibility="gone" android:adjustViewBounds="true" android:padding="3dp"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout style="@style/zfba_form_llframe"> <TextView style="@style/zfba_queryform_span" android:layout_width="@dimen/text_span_width" android:layout_weight="0" android:text="@string/xcdc_xm" android:tag="btkd"/> <cn.com.MeasureMTextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#696969" android:textSize="16sp" android:tag="xm" /> </LinearLayout> </LinearLayout> </LinearLayout>
到这里仅仅只解决了我遇到的第一个问题,而第二个问题计算textView的高度就要自定义一个TextView来重写它的OnMeasure()
下面是我自定的TextView的代码:
public class MeasureMTextView extends TextView { private Context context; public MeasureMTextView(Context context) { super(context); this.context = context; } public MeasureMTextView(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; } public MeasureMTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.context = context; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub super.onMeasure(widthMeasureSpec, heightMeasureSpec); //通过计算多行TextView的高度来重新设为TextView的高度 Layout layout = getLayout(); if (layout != null) { int height = (int) FloatMath.ceil(getMaxLineHeight(this.getText() .toString())) + getCompoundPaddingTop() + getCompoundPaddingBottom(); int width = getMeasuredWidth(); setMeasuredDimension(width, height); } } public float getMaxLineHeight(String str) { float height = 0.0f; int line = 1; float screenW = ((Activity) context).getWindowManager() .getDefaultDisplay().getWidth(); float paddingRight = ((LinearLayout) this.getParent()) .getPaddingRight(); float paddingLeft = ((LinearLayout) this.getParent()).getPaddingLeft(); String tagStr = (String) ((LinearLayout) this.getParent().getParent() .getParent()).getTag(); //这里的计算方法我就不详述了,基本都能看懂,不过这个padding和magin的值是根据我自己项目的 //代码布局来计算的,没有做成通用的,复制代码是不行的哟,这个要自己想想,最好画个图自己就能理解了 if (tagStr.equals("有图片")) { //当有图片时的textview内容的行数 line = (int) Math.ceil((this.getPaint().measureText(str) / (screenW - paddingLeft - paddingRight - context.getResources().getDimensionPixelOffset(R.dimen.item_image_width) - context.getResources().getDimensionPixelOffset(R.dimen.text_span_width)))); } else if (tagStr.equals("没图片")) { //当没有图片时的textview内容的行数 line = (int) Math.ceil((this.getPaint().measureText(str) / (screenW - paddingLeft - paddingRight - context.getResources().getDimensionPixelOffset(R.dimen.text_span_width)))); } height = (this.getPaint().getFontMetrics().descent - this.getPaint() .getFontMetrics().ascent) * line; return height; } }
而这样基本就解决,只要调用以下代码就行了
adapter.addDatas(queryResult); adapter.notifyDataSetChanged(); FormUtilFK.setListViewHeight(listView, context);而我的adapter.addDatas(queryResult);这段代码仅仅是把得到的数据set到Adapter中,肯定要adapter中有数据了才能动态测量listview的宽高嘛!这个要看自己的项目而言,这里仅仅是提供解决方案,而解决问题的话还是要根据自己项目的实际情况才能通过这个解决方法来解决自己的问题,复制代码是不行的!
最后:
当然我自己认为还有另一种解决方案,因为这样通过计算listview的高度来解决ScrollView和listView共存的时候,所有的item都会遍历出来,如果item条数多的话,这样就并不太合适。我自己的想法是可以定死listView的高度,然后根据自己的业务需求通过重写ScrollView的dispatchTouchEvent方法解决scrollView与listView的滑动冲突,这样遇到listView中Item数多的情况下就能优化性能了。
由于自己的经验和技术有限,可能自己方法并不是最好的,或者说代码中有问题,希望各位能理解并指点,最后希望能和我一样遇到同样问题的朋友都能解决自己的问题。
相关文章推荐
- JDBC(Java DataBase Connectivity)连接到MySQL
- 造轮子:Fiddler 抓包工具总结
- REDIS GEO: REDIS新增位置查询功能
- 对于横竖屏切换的生命周期你真的很了解吗
- Linux下Makefile文件编写
- 排序算法(一)——直接插入排序
- OpenCV实践之路——Qt中调用OpenCV打开图片
- 万恶的KPI、新兴的OKR及让人纠结的程序员考核
- 线程:概念与原理
- 希尔排序
- Horizon View 6.0 证书替换 Setp4 更改签发证书的有效期
- Java学习笔记2016.2.18 接口续、单例模式
- hdu3966 点权模板-树链部分
- 使用Intent传递对象
- SSH框架快速搭建
- hdu3966 点权模板-树链部分
- Android事件分发机制完全解析,带你从源码的角度彻底理解(下)
- 页面架构(笔记1)——水平居中布局
- Redis Geo: Redis新增位置查询功能
- 如何创建一个控制器