博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 解决ListView 和 ScrollView 共存冲突的问题
阅读量:7230 次
发布时间:2019-06-29

本文共 8231 字,大约阅读时间需要 27 分钟。

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 封装的一个通过下标获取相应数据的方法请参考上文。

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

 本文转自 terry_龙 51CTO博客,原文链接:http://blog.51cto.com/terryblog/373509,如需转载请自行联系原作者

你可能感兴趣的文章
Netty Channel源码分析
查看>>
基于 HTML5 WebGL 的 3D 机房
查看>>
Java编程——数据库两大神器:索引和锁
查看>>
springMvc学习笔记(2)
查看>>
吐槽Javascript系列二:数组中的splice和slice方法
查看>>
什么是Javascript函数节流?
查看>>
MQ框架的比较
查看>>
oschina
查看>>
Octave 入门
查看>>
深度学习入门:10门免费线上课程推荐
查看>>
React组件设计模式(一)
查看>>
E-HPC支持多队列管理和自动伸缩
查看>>
express + mock 让前后台并行开发
查看>>
30天自制操作系统-2
查看>>
小程序开发之路(一)
查看>>
Odoo domain写法及运用
查看>>
JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
查看>>
猫头鹰的深夜翻译:Java 2D Graphics, 简单的仿射变换
查看>>
面试题:给你个id,去拿到name,多叉树遍历
查看>>
go append函数以及写入
查看>>