Android开发中ListView 和 ScrollView 冲突如何解决

ListView 与 ScrollView 同在一界面会导致ListView 显示变形,ListView只显示出了一个条目的高度,本文我们来谈谈如何解决Android应用中ListView 和 ScrollView 共生的问题。

一开始就想着用一个ScrollView把主要内容和评论区的ListView包起来,然后添加各个控件的内容即可,但是写出来之后发现ListView只显示出了一个条目的高度,并且不能滑动,网上搜了一下发现原因是ScrollView和ListView都是可滑动的,把它们放在一块会有冲突,最后还是ScrollView获得了焦点,ListView不能滑动。网上的解决方法最多的是在加载ListView时用getMeasure计算每个条目和分割线的高度,然后相加,把结果设置为ListView控件的高度,不过貌似是只适用于ListView每个条目高度都一样的情况(没有试过,很奇怪为什么会这样)。要么就是自定义一个继承自ListView的控件,也是事先设置好ListView的高度,但这样总归比较麻烦,而且准确度不如由系统自己构造好。

懒癌发作实在不想自己去做这些事情,于是便想试一下比较投机的方法,就是在ListView的Adapter的getView方法中根据position构造不同的界面,即如果position是0,则用原来主要信息的xml文件取inflate convertView,否则就用评论条目的xml去inflate,经试验果然可行。之后不死心想看下有没有更好的实现方法,去overflow上找了一下,发现有人推荐的方法和我的差不多,所以认为这种方法是比较好的,不需要做额外的工作,只需要把inflate的工作由主Activity放在Adapter里就可以了。

getView方法

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
    /*主信息界面*/
    if(0 == position)
    {
        MainHolder holder = null;
        convertView = inflater.inflate(R.layout.info, parent, false);
        holder = new MainHolder();
        convertView.setTag(holder);
                ······
                ······
    }
    /*评论界面*/
    else
    {
        ItemHolder holder = null;
        convertView = inflater.inflate(R.layout.item, parent, false);
        holder = new ItemHolder();
        convertView.setTag(holder);
        ······
        ······
        return convertView;
    }
}

另一个方法解决

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

ListView 与 ScrollView 同在一界面会导致ListView 显示变形,因为ListView 也有自带的滚动事件,故无法与ScrollView 相容,可能造成的现象是ListView 只能显示一行或者两行,其他数据在那一点儿宽的地方做滚动,甚不雅观。

下面是我的一个实现 步骤:

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

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

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->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 封装的一个通过下标获取相应数据的方法请参考上文。

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

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索int
, view
, 数据
, 控件
, this
linearlayout
listview scrollview、scrollview套listview、scrollview和listview、scrollview与listview、listview在scrollview,以便于您获取更多的相关知识。

时间: 2024-10-21 18:17:42

Android开发中ListView 和 ScrollView 冲突如何解决的相关文章

android开发中listview添加图片

问题描述 android开发中listview添加图片 map1.put("image",R.drawable.jiantou); 我在listview中添加图像时,引用图像的地址,如上所示,但提示错误The method put(String, String) in the type HashMap is not applicable for the arguments (String, int) 但我看别人的代码都可以直接引用图像地址的,请大神帮忙解决一下,谢啦!! 解决方案 Ma

Android开发中Listview动态加载数据的方法示例

本文实例讲述了Android开发中Listview动态加载数据的方法.分享给大家供大家参考,具体如下: 最近在研究网络数据加载的问题,比如我有几百,甚至上千条数据,这些数据如果一次性全部加载到arraylist,然后再加载到Listview中.我们必然会去单独开线程来做,这样造成的结果就是会出现等待时间很长,用户体验非常不好.我的想法是动态加载数据,第一次加载十条,然后往下面滑动的时候再追加十条,再往下面滑动的时候再去追加,这样大大减少了用户等待的时间,同时给处理数据留下了时间.网上看到了这样一

android开发中webview保存cookie问题的解决

最近老是发现在IE里会有Cookie的问题,如IE下面无法登出,或无法登录,或者登录后信息却无法取到,而Firefox下面一直是通过的,都试过好多次了,今天终于找回的主要的原因: Cookie的问题: 首先看一下我的Cookie存取代码 (这个Cookie操作支持二级域名访问) #region 存取Cookie /// 〈summary〉 /// 存Cookie /// Json Lee 2007-09-24 /// 〈/summary〉 /// 〈param name="strName&quo

Android开发中听筒无法播放音乐的解决方法_Android

本文实例讲述了Android开发中听筒无法播放音乐的解决方法.分享给大家供大家参考,具体如下: 这个问题让我蛋疼了,既然百度也木有资料. 耗时的主要原因是因为权限不足时,而没有终止程序,只用了一小行日志提醒,没有看到 用听筒播放很简单 AudioManager.setMode(AudioManager.MODE_IN_CALL) //设定为通话中即可 还是这一句代码的事,不过记得要加上权限 Android.permission.MODIFY_AUDIO_SETTINGS 不然会像我一样蛋疼半天

Android开发中听筒无法播放音乐的解决方法

本文实例讲述了Android开发中听筒无法播放音乐的解决方法.分享给大家供大家参考,具体如下: 这个问题让我蛋疼了,既然百度也木有资料. 耗时的主要原因是因为权限不足时,而没有终止程序,只用了一小行日志提醒,没有看到 用听筒播放很简单 AudioManager.setMode(AudioManager.MODE_IN_CALL) //设定为通话中即可 还是这一句代码的事,不过记得要加上权限 Android.permission.MODIFY_AUDIO_SETTINGS 不然会像我一样蛋疼半天

android开发中ListView与Adapter使用要点介绍_Android

1. Adapter.getView() public View getView(int position, View convertView , ViewGroup parent){...} 这个方法就是用来获得指定位置要显示的View.官网解释如下: Get a View that displays the data at the specified position in the data set. You can either create a View manually or infl

Android开发中ListView嵌套GridView问题详解

开发中,遇到一个问题,是ListView嵌套GridView,需要点击整个ListView的Item进行跳转.但是在点击GridView区域时无法进行页面的跳转.这是因为GridView获得了焦点.导致点击无法跳转. 解决方法就是: 1.在Item最外层加上 android:descendantFocusability="blocksDescendants" 2.在Adapter中添加 holder.mGridView.setClickable(false); holder.mGrid

浅谈Android开发中ListView控件性能的一些优化方法

ListView优化一直是一个老生常谈的问题,不管是面试还是平常的开发中,ListView永远不会被忽略掉,那么这篇文章我们来看看如何最大化的优化ListView的性能. 1.在adapter中的getView方法中尽量少使用逻辑 2.尽最大可能避免GC 3.滑动的时候不加载图片 4.将ListView的scrollingCache和animateCache设置为false 5.item的布局层级越少越好 6.使用ViewHolder 下面就具体来看一些 1.在adapter中的getView方

Android开发中ListView自定义adapter的封装_Android

[引入]  我们一般编写listView的时候顺序是这样的:  •需要展示的数据集List<T>  •为这个数据集编写一个ListView  •为这个ListView编写一个Adapter,一般继承自BaseAdapter  •在BaseAdapter内部编写一个ViewHolder类,对应ListView里面的item控件,提高控件的查询效率  分析: List<T>:ListView --> Adapter extends BaseAdapter --> ViewH