关于scrollview嵌套listview的方法。但官方并不推荐这种做法。
来源:互联网 发布:数据可视化软件 ta 编辑:程序博客网 时间:2024/06/01 10:37
scrollview嵌套listview确实有方法实现,但是并不为官方推荐。
You should never use a ScrollView with a ListView
, because ListView takes care of its own vertical scrolling. Most importantly, doing this defeats all of the important optimizations in ListView for dealing with large lists, since it effectively forces the ListView to display its entire list of items to fill up the infinite container supplied by ScrollView.
至于应该怎么做最合适我大概有个思路还没有实现,就是只用一个listview,填充不同的布局,这只是我的想法,我并不知道这种做法是否是最恰当的做法,但这种做法确实没有用到scrollview嵌套listview。
但是我还是总结了网上分享的方法以备不时之需:
原文:http://www.lai18.com/content/2146670.html
解决方案一 手动设置ListView高度
解决思路: 手动设定ListView的高度,在ListView设置了Adapter之后使用。注意: Adapter中getView方法返回的View的布局只能是LinearLayout组成,因为只有LinearLayout才有measure()方法,如果使用其他的布局,在调用listItem.measure(0, 0);时就会抛异常,除LinearLayout外的其他布局的这个方法就是直接抛异常的。
[code] /** * 动态改变ListView的高度 * @param listView */ public static void setListViewHeightBasedOnChildren(ListView listView) { if(listView == null) return; ListAdapter adapter = listView.getAdapter(); if (adapter == null) { return; } int totalHeight = 0; // 开始计算ListView里所有Item加起来的总高度 for (int i = 0; i < adapter.getCount(); i++) { View listItem = adapter.getView(i, null, listView); listItem.measure(0, 0); totalHeight += listItem.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); // 高度 = 所有分割线高度 + Item总高度 params.height = totalHeight + (listView.getDividerHeight() * (adapter.getCount() - 1)); listView.setLayoutParams(params); }
解决方案二 一个ListView渲染整个ScrollView内容
解决思路: 把ScrollView内的所用内容,全部都放到ListView中去渲染,ListView上、下方的View都作为ListView的Item去渲染,ListView中的普通Item是平级关系。注意: 这里涉及到一个打破ViewHolder复用问题。我们可以看getView源代码,convertView返回的是旧视图(可以看看Android 万能ViewHolder,这里详解了convertView来源)。那么问题来了!如果一个ListView渲染整个ScrollView内容,那么不同Item之间的复用问题如何解决。其实AdapterView已经提供了支持,这里涉及到Adapter.getItemViewType(position),覆写getItemViewType,自己写不同Item的判断逻辑,再定制对应的ViewHolder去进行相同Type的Item的复用。
[code] @Override public View getView(int position, View convertView, ViewGroup parent) { int viewType = this.getItemViewType(position); switch (viewType) { case TYPE_ONE: TypeOneHolder holderOne; View v = convertView; if (v == null) { LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.layout_mylistlist_item_type_1, parent, false); holderOne = new TypeOneHolder(); holderOne.text = (TextView) v.findViewById(R.id.mylist_itemname); v.setTag(holderOne); } else { holderOne = (TypeOneHolder) v.getTag(); } MyListItem myItem = adapterData.get(position); if (myItem != null) { if (holderOne.text != null) { holderOne.text.setText(myItem.getItemName()); } } return v; case TYPE_TWO: TypeTwoHolder holder2; View v = convertView; if (v == null) { LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.layout_mylistlist_item_type_2, parent, false); holder2 = new TypeTwoHolder(); holder2.text = (TextView) v.findViewById(R.id.mylist_itemname); holder2.icon = (ImageView) v.findViewById(R.id.mylist_itemicon); v.setTag(holderOne); } else { holder2 = (TypeTwoHolder) v.getTag(); } MyListItem myItem = adapterData.get(position); if (myItem != null) { if (holder2.text != null) { holder2.text.setText(myItem.getItemName()); } if (holder2.icon != null) holder2.icon.setDrawable(R.drawable.icon1); } return v; default: //Throw exception, unknown data type break; } }
解决方案三 自定义LinearLayout取代ListView
解决思路: 手动调用Adapter.getView把一个一个子View拿到后,循环有序添加到LinearLayout中(LinearLayout.addView)。注意: 这里需要依赖外部的Adapter和各种Listener,那些OnClick,OnLongClick等,都要自己写,在每个子View添加到LinearLayout前,给每个子View加这些事件。
[code]public class ListViewLayout extends LinearLayout { private BaseAdapter adapter; private OnClickListener onClickListener; public ListViewLayout(Context context) { super(context); } public ListViewLayout(Context context, AttributeSet attrs) { super(context, attrs); } @TargetApi(Build.VERSION_CODES.HONEYCOMB) public ListViewLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public ListViewLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } /** * 设置BaseAdapter和OnClickListener * * @param adapter * @param onClickListener */ public void setAdapterAndListener(BaseAdapter adapter, OnClickListener onClickListener) { this.init(adapter, onClickListener); int count = this.adapter.getCount(); this.removeAllViews(); // 初始化LinearLayout内容 for (int i = 0; i < count; i++) { View v = this.adapter.getView(i, null, null); v.setOnClickListener(this.onClickListener); this.addView(v, i); } } private void init(BaseAdapter adapter, OnClickListener onClickListener) { this.adapter = adapter; this.onClickListener = onClickListener; }}
[code]ListViewLayout listViewLayout = (ListViewLayout) this.findViewById(R.id.listViewLayout);listViewLayout.setAdapterAndListener(adapter,listener);
解决方案四 自定义拓展ListView
解决思路: 通过重写ListView.onMeasure方法,达到对ScrollView适配的效果。注意: 默认显示的首项还是ListView,要手动把ScrollView滚动至顶端。
[code]public class SVListView extends ListView { public SVListView(Context context) { super(context); } public SVListView(Context context, AttributeSet attrs) { super(context, attrs); } public SVListView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public SVListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } /** * 重新算高度,适应ScrollView的效果 * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); }}
[code]ScrollView sv = (ScrollView) findViewById(R.id.scrollview);// 手动把ScrollView滚动至顶端sv.smoothScrollTo(0, 0);
对比总结
方案一:不用对控件做任何修改,只需要调用一个方法。但是每次Adapter数据变的时候,又要重新调用。方案二:原本在不同Type的Item这块,复用问题就很头疼,这里后续添加了不同Type的Item的复用方案,一个不错的方案。
方案三:这个方案缺点非常明显,各种监听都要自己去给Item逐个添加,也不能达到复用效果,更何况要是多种Type类型的Item呢?
方案四:仅仅只是重写了onMeasure,原生的ListView的好多特性都还保存着,其中也包括notifyDataSetChanged方法,相比其他方法是最趋近于完美的方法,也只是需要在Activity中设定ScrollView滚动至顶端。
0 0
- 关于scrollview嵌套listview的方法。但官方并不推荐这种做法。
- ScrollView嵌套ListView方法
- 关于ScrollView嵌套Listview遇到的问题
- 关于ScrollView嵌套ListView的一些问题
- android ScrollView嵌套ListView的方法分析
- ScrollView嵌套ListView的问题解决方法
- ScrollView与ListView的嵌套,不推荐这样做
- 关于ScrollView嵌套ListView冲突
- ScrollView嵌套ListView方法汇总
- ScrollView嵌套Listview处理方法
- 关于ListView和ScrollView嵌套问题的解决
- 关于Android中ScrollView嵌套ListView的问题
- 关于ScrollView嵌套ListView与GridView的问题
- 关于ScrollView中嵌套Listview和GridView的解决方案
- 总结关于在ScrollView里面嵌套listView的一些坑
- ScrollView嵌套ListView的解决方案
- ScrollView嵌套ListView的使用
- ScrollView嵌套ListView的解决办法
- maven导出项目依赖的jar包
- jsp页面防止刷新重复提交解决方案
- 常用js特效之左上角菜单
- 页面设计
- 用php调用接口api
- 关于scrollview嵌套listview的方法。但官方并不推荐这种做法。
- 适配所有机型的保存图片工具
- Flex 字符串拼接、去掉字符串两端空字符
- delphi idHttp下载文件
- windows下apache+php+mysql 环境配置方法
- poj 2184 Cow Exhibition 01背包
- ps如何制作霓虹字体
- java获取最新地区
- iOS滤镜效果的实现:CoreImage