ListView 与 ScrollView 同在一个界面用头脑想想都觉得不大可能这样做,但还真的有美工这样做了,有点郁闷~!!沟通无果,解决之~~~~!初期还真没啥头绪,Google 一下看到有很多同样碰到这类头痛的问题,不好意思还没描述问题症状。ListView 与 ScrollView 同在一界面会导致
ListView 显示变形,因为ListView 也有自带的滚动事件,故无法与ScrollView 相容,可能造成的现象是ListView 只能显示一行或者两行,其他数据在那一点儿宽的地方做滚动,甚不雅观。
下面是我的一个实现 步骤:
- 1、继承LinearLayout,既然会冲突那就不用ListView 改成线性布局做动态布局效果
- 2、继承BaseAdapter ,可以参照一下Android app源码中 Widget 目录下的SimpleAdapter 为前面扩展的LinearLayout做数据。
- 3、模拟数据填充扩展后的BaseAdapter 为扩展后的LinearLayout 加载数据
第一步:新建LinearLayoutForListView 类使其扩展LinearLayout重写以下两个方法:
super(context);
}
public LinearLayoutForListView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
这两个方法可选,不过建议都写上,第一个方法可以让我们通过 编程的方式 实例化出来,第二个方法可以允许我们通过 XML的方式注册 控件,可以在第二个方法里面为扩展的复合组件加属性,详细使用方法请点击这里 。
为其添加get / set 方法
* 获取Adapter
*
*
@return adapter*/
public AdapterForLinearLayout getAdpater() {
return adapter;
}
/**
* 设置数据
*
*
@param adpater*/
public void setAdapter(AdapterForLinearLayout adpater) {
this.adapter = adpater;
bindLinearLayout();
}
/**
* 获取点击事件
*
*
@return*/
public OnClickListener getOnclickListner() {
return onClickListener;
}
/**
* 设置点击事件
*
*
@param onClickListener*/
public void setOnclickLinstener(OnClickListener onClickListener) {
this.onClickListener = onClickListener;
}
第二步:新建AdapterForLinearLayout 类继承自BaseAdapter,并为其添加构造函数
private int resource;
private List<? extends Map<String, ?>> data;
private String[] from;
private int[] to;
public AdapterForLinearLayout(Context context,
List
<? extends Map<String, ?>> data, int resouce, String[] from,int[] to) {
this.data = data;
this.resource = resouce;
this.data = data;
this.from = from;
this.to = to;
this.mInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
此构造函数模仿 simpleAdapter 通过传进来的resouce 为布局设置数据。通过继承BaseAdapter 重要的实现方法在下面getView ,此方法判断通过传进来的 String[] from 与 int[] to 为分别查找出View 并为View 设置相应的Text,代码如下:
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
convertView
= mInflater.inflate(resource, null);Map
<String, ?> item = data.get(position);int count = to.length;
for (int i = 0; i < count; i++) {
View v
= convertView.findViewById(to[i]);bindView(v, item, from[i]);
}
convertView.setTag(position);
return convertView;
}
/**
* 绑定视图
*
@param view*
@param item*
@param from*/
private void bindView(View view, Map<String, ?> item, String from) {
Object data
= item.get(from);if (view instanceof TextView) {
((TextView) view).setText(data
== null ? “” : data.toString());}
}
Tip:
- BindView 方法是一个自定义方法,在方法体内可以为通过判断使本类更具灵活性,如上,你不仅可以判断是TextView 并且可以传入任何你想要的View 只要在方法体内加入相应判断即可,数据可以通过data 做相应处理,具体如何操作读者可另行测试。
- convertView.setTag(position); 此句代码为View 设置tag 在以后我们可以通过 getTag 找出下标,后文有介绍如何通过下标操作数据。
下面是两个类的全部代码,读者可以无须更改直接使用:
LinearLayoutForListView
private AdapterForLinearLayout adapter;
private OnClickListener onClickListener = null;
/**
* 绑定布局
*/
public void bindLinearLayout() {
int count = adapter.getCount();
for (int i = 0; i < count; i++) {
View v
= adapter.getView(i, null, null);v.setOnClickListener(
this.onClickListener);if (i == count – 1) {
LinearLayout ly
= (LinearLayout) v;ly.removeViewAt(
2);}
addView(v, i);
}
Log.v(
“countTAG“, “” + count);}
public LinearLayoutForListView(Context context) {
super(context);
}
public LinearLayoutForListView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
/**
* 获取Adapter
*
*
@return adapter*/
public AdapterForLinearLayout getAdpater() {
return adapter;
}
/**
* 设置数据
*
*
@param adpater*/
public void setAdapter(AdapterForLinearLayout adpater) {
this.adapter = adpater;
bindLinearLayout();
}
/**
* 获取点击事件
*
*
@return*/
public OnClickListener getOnclickListner() {
return onClickListener;
}
/**
* 设置点击事件
*
*
@param onClickListener*/
public void setOnclickLinstener(OnClickListener onClickListener) {
this.onClickListener = onClickListener;
}
}
AdapterForLinearLayout
private LayoutInflater mInflater;
private int resource;
private List<? extends Map<String, ?>> data;
private String[] from;
private int[] to;
public AdapterForLinearLayout(Context context,
List
<? extends Map<String, ?>> data, int resouce, String[] from,int[] to) {
this.data = data;
this.resource = resouce;
this.data = data;
this.from = from;
this.to = to;
this.mInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
// TODO Auto-generated method stub return data.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub return data.get(position);
}
@SuppressWarnings(
“unchecked“)public String get(int position, Object key) {
Map
<String, ?> map = (Map<String, ?>) getItem(position);return map.get(key).toString();
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
convertView
= mInflater.inflate(resource, null);Map
<String, ?> item = data.get(position);int count = to.length;
for (int i = 0; i < count; i++) {
View v
= convertView.findViewById(to[i]);bindView(v, item, from[i]);
}
convertView.setTag(position);
return convertView;
}
/**
* 绑定视图
*
@param view*
@param item*
@param from*/
private void bindView(View view, Map<String, ?> item, String from) {
Object data
= item.get(from);if (view instanceof TextView) {
((TextView) view).setText(data
== null ? “” : data.toString());}
}
}
对应的XML 如下:
android:orientation
=”vertical” android:layout_width=”fill_parent”android:layout_height
=”fill_parent”><TextView android:id=”@+id/TextView01″
android:layout_marginLeft
=”10px” android:textAppearance=”?android:attr/textAppearanceLarge”android:layout_width
=”wrap_content” android:layout_height=”wrap_content”></TextView>
<TextView android:id=”@+id/TextView02″ android:layout_width=”wrap_content”
android:textAppearance
=”?android:attr/textAppearanceSmall”android:layout_marginLeft
=”10px” android:layout_height=”wrap_content”></TextView>
<View android:layout_height=”1px” android:background=”#FFFFFF”
android:layout_width
=”fill_parent”></View> </LinearLayout>
第三步:主页面使用控件并为其设置数据
- XML如下:
<com.terry.widget.LinearLayoutForListView
android:orientation=”vertical” android:layout_width=”450px”
android:layout_height=”fill_parent” android:id=”@+id/ListView01″>
</com.terry.widget.LinearLayoutForListView>
- 加载数据如下:
lv = (LinearLayoutForListView) findViewById(R.id.ListView01);
HashMap
<String, Object> map = new HashMap<String, Object>();map.put(
“key_name“, “name“ + i);map.put(
“value_name“, “value“ + i);list.add(map);
}
R.id.TextView02 });
- 事件操作,并通过下标得到数据源:
lv.setOnclickLinstener(new OnClickListener() {
@Override
BlueToothActivity.
this,Layoutadpater.get(Integer.parseInt(v.getTag()
.toString()),
“key_name“), 1000).show();}
});
lv.setAdapter(Layoutadpater);
Tip:get方法是在Layoutadpater 封装的一个通过下标获取相应数据的方法请参考上文。
至此完成。有碰到这个问题的朋友可以试试。