高级控件Listview

高级控件Listview简介

好奇、学习、总结、分享

说明:本文是整理之前学习安卓的笔记,为了对一些概念性的、自己不太熟悉的知识点有更加清晰、更接近正确的描述,参考了很多网络上优秀的文章。同时为了尊重被人的劳动成果我尽量注明文章地址。在此非常感谢网络上的大牛们,无私的贡献出自己“武功秘密”,让更多的有共同兴趣的童鞋们受益。

本文如有理解或描述错误,请大家批评指正,谢谢。

一、ListView简介

1ListView Android一个高级控件,需要用适配器来设置数据,它以列表的形式展示具体内容,并且能够根据数据的长度自适应显示。比如手机通讯录就使用到了ListView显示联系人信息

2、常用高级控件

Androd中常用的高级控件有:Listview[列表视图]GridView[网格视图]、ViewPage、Gallery[画廊]、Spinner[下拉列表]

普通控件:五大布局,TextView、EditText、Button、Checkbox、ImageView

注意:安卓中所有的控件不仅可以在xml文件中直接布局,也可以在java代码中动态实现布局。因为Android中所有控件都继承自android.view.View,其中android.view.ViewGroupView的一个重要子类,绝大部分的布局都继承自ViewGroup

Android控件的继承关系图如下:

原文地址:http://www.android100.org/html/201406/03/16761.html


3适配器简介:

Android中适配器是连接后端数据和前端显示的适配器接口,是数据和UI之间重要的纽带

常用适配器:ArrayAdapter<T>、BaseAdapterSimpleAdapterSimpleCursorAdapter、PageAdapter

4、上下文简介:【不重复造轮子,请查考下面2篇优秀的文章】

参考文章1

Android系统的角度来理解:Context是一个场景,代表与操作系统的交互的一种过程。从程序的角度上来理解:Context是个抽象类ActivityServiceApplication等都是该类的一个实现

原文地址:http://blog.csdn.net/lmj623565791/article/details/40481055

参考文章2:

安卓中根据作用域的不同,可以把上下文分成两种,一种是Activity的界面的上下文即Activity Content,另一种是Android应用上下文,即Application Content

原文地址:http://www.360doc.com/content/14/0622/12/7044580_388796923.shtml

5、创建Listview2中方式:

5.1、直接在xml布局文件中创建ListView

5.2、在java代码中让Activity继承ListActivity

6、列表的显示需要三个元素:

6.1ListVeiw控件:用来展示列表的View

6.2.适配器:用来把数据映射ListView上的中介。

6.3.数据集:具体的将被映射的字符串,图片,或者基本组件。

、ListView的简单示例代码:

思路:

1.在布局文件中放置一个ListView控件

2.在Activity中创建一个类继承BaseAdapter实现4个方法,getcount,getview是必须实现的,

getcount :告诉listview要展示多少个条目

getview:告诉listview每个条目要显示的内容,屏幕上每显示一条数据时就会调用一次该方法。

代码:

public class MainActivity extends Activity {

private Context myContent;//创建上下文变量

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

//1给上下文变量赋值

myContent = MainActivity.this;

//2加载主布局XML文件

setContentView(R.layout.activity_main);

//3找到listview控件

ListView lv = (ListView) findViewById(R.id.lv);

//4listview设置一个适配器对象,让其显示数据

lv.setAdapter(new MyAdapter());

}

//2、创建Listview的适配器,适配器为listview控件提供数据的,是数据和视图之间的桥梁。

public class MyAdapter extends BaseAdapter {

//创建一个hashMap<key,values>集合来保存每个textview的对象,hashmap的key值不会重复

HashMap<Integer, Integer> hashMapnew HashMap<Integer, Integer>();

@Override

//告诉listview控件有几个条目需要显示【必须实现,否则listview不知道要显示几条数据】

public int getCount() {

return 50;

}

@Override

//获取listview控件上某个条目上的数据对象,根据实际需求实现或不实现【可不实现,不影响listview的展示】

public Object getItem(int position) {

return null;

}

@Override

//返回listview控件指定位置上的ID【可不实现,不影响listview的展示】

public long getItemId(int position) {

return 0;

}

//获取一个视图对象【view】用于给listview的条目做展示用,必须实现,如果不实现listview条目就是无法显示

 @Override

public View getView(int position, View convertView,ViewGroup parent) {

//暂时创建一个textview对象,用于返回视图,做listview的展示

TextView textView = new TextView(myContent);

textView.setText("当前位置"+position);

textView.setTextSize(20);

textView.setTextColor(Color.BLUE);

//把每次创建的textview对象保存到hashmap

hashMap.put(textView.hashCode(), textView.hashCode());

Log.e("textview对象个数"""+hashMap.size());

Log.i("适配器""当前位置"+position);

//可以返回任何类型的视图对象,如:button、linelayout...

return textView;

}

}

}

由打印的日志可以看出,在滑动屏幕时,不停的创建textview对象,这样的话,会浪费大量的CPU时间和内存控件,而且GC垃圾回收器也在不停的回收看不到的对象,来释放内存空间,所以非常的消耗时间和内存空间。

 

三、listview优化 

针对上面的缺陷,需要对listview对象优化。

ListView有三种优化方式:【本文只介绍第一种,以后在详细介绍后两种】

1、复用convertView对象

2、分页分批加载。

3、使用ViewHolder减少FindViewById的次数

在适配器中的getview方法中会传递过来一个convertView【转换视图】对象,我们可以复用该对象作为getview的返回对象,在使用前需要判断该对象是否为null,如果不为空直接使用,如果为空就需要手动创建返回对象。

代码如下:

@Override

public View getView(int position, View convertView, ViewGroup parent) {

//1先创建一个空的textview对象,主要用于返回视图,给listview做展示用

TextView textView = null;

//2判断convertView是否为空

if (convertView != null) {

//2.1不为空,就复用convertView

textView = (TextView) convertView;

}else {

//2.2如果convertView为空,表示无复用的对象,此时需要创建textview对象

textView = new TextView(myContent);

}

textView.setText("当前位置"+position);

textView.setTextSize(20);

textView.setTextColor(Color.BLUE);

//把每次创建的textview对象保存到hashmap

hashMap.put(textView.hashCode(), textView.hashCode());

Log.e("textview对象个数"""+hashMap.size());

Log.i("适配器""当前位置"+position);

//可以返回任何类型的视图对象,如:button、linelayout...

return textView;

}

输出结果如下:由输出结果可知,无论listview的条目如何滑动,都只创建最初的20textview对象【屏幕能显示的最大数量,不用尺寸的手机可能显示的条目不一样】,系统在复用被隐藏的convertView对象【即textview对象】

 

四、listview中的MVC模式

MVC模式在 listview的体现

M:model模型,一般对于javabean

V:view视图,对应xml布局中的Listview控件,用户和用户交互

C:control控制器,对应Activity中的Adapter,是model与view之间的桥梁

五、listview显示原理

1.首先知道listview显示的条数,getCount

2.listview显示的内容, getview

3.要知道listview中每个条目的高度,要知道一屏显示多少条

4.要监听listview的滑动,移除一个旧的条目,显示一个新的条目

注意:屏幕展示多少个条目,就会调用多少次getview方法。

当getCoun的数量不足以铺满整个屏幕时,就会出现怪异的现象,例如getCoun = 5时,系统会调用多次getview()方法,直到getview()方法创建的对象能铺满整个屏幕为止,所以在实际设计时,listview的条目最好能铺满整个窗口。

六、复杂listview界面显示 ,新闻列表

思路:

1.主xml文件中增加Listview布局

2.javabean来模拟新闻数据,用集合保存java对象

3.集合中的数据传递给adapter适配器,适配器给listview设置展示数据

4.定义一个显示新闻的xml布局文件,转换成视图对象作为适配器getview方法做返回内容

5.找到listview设置adapter适配器

6.设置listview每个条目的点击事件,点击跳转看新闻

XML布局文件:

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

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:paddingBottom="@dimen/activity_vertical_margin"

    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@dimen/activity_vertical_margin"

    tools:context="com.lee.news.MainActivity" >

<!--设置一个listview控件:铺满屏幕-->

    <ListView 

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"

        android:id="@+id/lv_news">

    </ListView>

</RelativeLayout>

效果图如下:

 

Listview条目xml布局文件:

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

<LinearLayout 

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

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    android:padding="10dp"

    android:orientation="horizontal" >

<!-- 新闻条目布局 ,不用来直接展示,而是被转换成java对象,通过java代码来动态的显示-->

    <!-- 图片:左边 -->

    <ImageView

        android:id="@+id/img_newspic"

        android:layout_marginRight="10dp"

        android:layout_width="60dp"

        android:layout_height="60dp"

        android:src="@drawable/ic_launcher" />

    <!-- 标题、内容描述用相对布局包裹相对布局的高度和图片的高度一致让2个文本框垂直居中:gravity=center_vertical -->

    <RelativeLayout

        android:layout_width="fill_parent"

        android:layout_height="58dp" 

        android:gravity="center_vertical"   >

        <!-- 标题颜色:可以直接写十六进制的值,也可以写安卓自带的颜色属性,只显示一行:singleLine="true"  -->

        <TextView

            android:id="@+id/tv_title"

            android:singleLine="true"

            android:textSize="18dp"

            android:layout_marginBottom="2dp"

            android:textColor="@android:color/black"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="title" />

        <!-- 描述 -->

        <TextView

            android:layout_below="@id/tv_title"

            android:id="@+id/tv_des"

            android:textSize="15dp"

            android:textColor="#666666"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="des" />

     </RelativeLayout>

</LinearLayout>

效果图如下:

 

适配器代码如下:

class MyAdapter extends BaseAdapter{

//创建一个javabean对象的集合,用于获取集合长度,把长度值赋值给适配器

private ArrayList<NewsBean> allNews;

//构造函数,获取要显示的新闻集合

public MyAdapter(ArrayList<NewsBean> allNews) {

this.allNews = allNews;

}

//告知listview要显示的数量

@Override

public int getCount() {

return allNews.size();//集合长度

}

//获取listview要显示的条目,【可以不用设置】在设置点击事件时需要设置,此时返回位置对于的对象即可

@Override

public Object getItem(int position) {

return allNews.get(position);//返回集合中javabean对象

}

//获取listview条目的ID号,一般不用,在设置点击事件时需要设置,此时返回位置即可

@Override

public long getItemId(int position) {

return position;

}

// 在getview()方法中既可以用java代码给他动态的设置一个普通的view对象,

// 也可以通过xml布局文件 给他设置一个复杂的布局,通过填充器把xml文件转换成视图对象

@Override

public View getView(int position, View convertView, ViewGroup parent) {

View view = null;

//listview优化

if (convertView != null) {

view = convertView;

else {

/**

 * inflate打气筒[填充器]:作用把xml布局文件转换成视图对象,供java代码直接使用

 * 参数1:上下文

 * 参数2:要转换的布局文件ID

 * 参数3:视图组,里边可以包含多个子视图,一般为空null,即不挂载到任何父控件上

 */

view = View.inflate(mContext, R.layout.newsitem_layoutnull);

//xml布局文件转换成视图对象方法2:不常用

//View view2 = LayoutInflater.from(mContext).inflate(R.layout.newsitem_layout, null);

//xml布局文件转换成视图对象方法3:不常用

//3.1、通过上下文获取系统服务对象,强转为LayoutInflater类型

//LayoutInflater systemService = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);

//3.2、再获取打气筒,把xml转换成视图对象

//systemService.inflate(R.layout.newsitem_layout, null);

}

//为视图设置要显示的内容

 //1、在view视图下查找需要的控件【即在newsitem_layout.xml文件中查找】

TextView tv_title = (TextView) view.findViewById(R.id.tv_title);

TextView tv_des = (TextView) view.findViewById(R.id.tv_des);

ImageView img_newspic = (ImageView)view.findViewById(R.id.img_newspic);

//2、给控件设置值,先通过位置position从集合中获取javabean对象,然后把javabean对象中的值赋值给控件

NewsBean newsBean = allNews.get(position);

tv_title.setText(newsBean.title);//设置标题

tv_des.setText(newsBean.des);//设置描述

img_newspic.setImageDrawable(newsBean.pic);//设置图片资源

return view;

}
}

最终效果图


六、inflate【填充器 / 打气筒】的3写法,inflate的作用是把xml布局文件转换成视图对象,一般用在适配器的getView()方法中,把较为复杂的listview条目的xml布局文件转换成视图对象,把该对象设置好要显示的参数后返回给listview显示。

1.view = View.inflate(mContext, R.layout.item_news_layout, null);【常用】

2.view = LayoutInflater.from(mContext).inflate( R.layout.item_news_layout, null);

3.LayoutInflater systemService = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);

view = systemService.inflate(R.layout.item_news_layout, null); 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值