您的位置:首页 > 移动开发 > Android开发

Android 解决ListView 和 ScrollView 共存冲突的问题

2013-04-08 10:08 579 查看
转自:http://www.cnblogs.com/TerryBlog/archive/2010/08/13/1799045.html
ListView 与 ScrollView 同在一个界面用头脑想想都觉得不大可能这样做,但还真的有美工这样做了,有点郁闷~!!沟通无果,解决之~~~~!初期还真没啥头绪,Google 一下看到有很多同样碰到这类头痛的问题,不好意思还没描述问题症状。ListView 与 ScrollView 同在一界面会导致ListView 显示变形,因为ListView 也有自带的滚动事件,故无法与ScrollView
相容,可能造成的现象是ListView 只能显示一行或者两行,其他数据在那一点儿宽的地方做滚动,甚不雅观。
下面是我的一个实现 步骤:

1、继承LinearLayout,既然会冲突那就不用ListView 改成线性布局做动态布局效果
2、继承BaseAdapter ,可以参照一下Android app源码中 Widget 目录下的SimpleAdapter 为前面扩展的LinearLayout做数据。
3、模拟数据填充扩展后的BaseAdapter 为扩展后的LinearLayout 加载数据

第一步:新建LinearLayoutForListView 类使其扩展LinearLayout重写以下两个方法:

public LinearLayoutForListView(Context context) {

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 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);

}

此构造函数模仿 simpleAdapter 通过传进来的resouce 为布局设置数据。通过继承BaseAdapter 重要的实现方法在下面getView ,此方法判断通过传进来的 String[] from 与 int[] to 为分别查找出View 并为View 设置相应的Text,代码如下:

@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());

}

}

Tip:

BindView 方法是一个自定义方法,在方法体内可以为通过判断使本类更具灵活性,如上,你不仅可以判断是TextView 并且可以传入任何你想要的View 只要在方法体内加入相应判断即可,数据可以通过data 做相应处理,具体如何操作读者可另行测试。
convertView.setTag(position); 此句代码为View 设置tag 在以后我们可以通过 getTag 找出下标,后文有介绍如何通过下标操作数据。

下面是两个类的全部代码,读者可以无须更改直接使用:
LinearLayoutForListView

package com.terry.widget;

import android.content.Context;

import android.util.AttributeSet;

import android.util.Log;

import android.view.View;

import android.widget.LinearLayout;

public class LinearLayoutForListView extends LinearLayout {

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

package com.terry.widget;

import java.util.List;

import java.util.Map;

import android.content.Context;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.TextView;

public class AdapterForLinearLayout extends BaseAdapter {

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 如下:



<?xml version="1.0" encoding="UTF-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

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);

for (int i = 0; i < 10; i++) {

HashMap<String, Object> map = new HashMap<String, Object>();

map.put("key_name", "name" + i);

map.put("value_name", "value" + i);

list.add(map);

}

final AdapterForLinearLayout Layoutadpater = new AdapterForLinearLayout(

this, list, R.layout.test, new String[] { "key_name",

"value_name" }, new int[] { R.id.TextView01,

R.id.TextView02 });

事件操作,并通过下标得到数据源:

lv.setOnclickLinstener(new OnClickListener() {

@Override

public void onClick(View v) {

// TODO Auto-generated method stub

Toast.makeText(

BlueToothActivity.this,

Layoutadpater.get(Integer.parseInt(v.getTag()

.toString()), "key_name"), 1000).show();

}

});

lv.setAdapter(Layoutadpater);

Tip:get方法是在Layoutadpater 封装的一个通过下标获取相应数据的方法请参考上文。

至此完成。有碰到这个问题的朋友可以试试。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: