[实例] Android 解决ListView 和 ScrollView 共存冲突的问题

Android, ListView, ScrollView, 解决
本帖最后由 terryyhl 于 2010-8-13 15:19 编辑

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);
bindView(v, item, from);
}
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 找出下标,后文有介绍如何通过下标操作数据。

下面是两个类的全部代码,读者可以无须更改直接使用:
LinearLayoutForListViewpackage 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;
}

}






AdapterForLinearLayoutpackage 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);
bindView(v, item, from);
}
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"
androidrientation
="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
    androidrientation="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 封装的一个通过下标获取相应数据的方法请参考上文。

至此完成。有碰到这个问题的朋友可以试试。

更多相关文章

  1. 浅谈Java中Collections.sort对List排序的两种方法
  2. mybatisplus的坑 insert标签insert into select无参数问题的解决
  3. python起点网月票榜字体反爬案例
  4. Python list sort方法的具体使用
  5. python list.sort()根据多个关键字排序的方法实现
  6. android上一些方法的区别和用法的注意事项
  7. android EditText设置不可写
  8. 《Android开发从零开始》——25.数据存储(4)
  9. android实现字体闪烁动画的方法

随机推荐

  1. Android(安卓)中的各种控件
  2. Android学习笔记_12_网络通信之从web获取
  3. android通过USB的MTP模式下,禁止用户在根
  4. Android(安卓)GridView的使用方法
  5. 申请 android google map API key
  6. android Can't create handler inside th
  7. 我的Android之旅——UI界面六大布局之认
  8. Activity之间传递对象
  9. Android(安卓)5.X新特性详解
  10. [转]android animation的应用实例