ListView

1)ListView的简单用法

2)定制ListView界面

3)提升ListView的运行效率

4)ListView的点击事件

3.5 ListView

3.5.1 ListView的简单用法

1.新建项目,修改activity_main.xml中的代码,插入<ListView>控件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"> <ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"> </ListView>
</LinearLayout>

2.修改MainActivity中的代码

public class MainActivity extends AppCompatActivity {

    private String[] data = new String[]{"gareen","teemo","shana","annie",
"gareen","teemo","shana","annie","gareen","teemo","shana","annie","gareen","teemo","shana","annie",
"gareen","teemo","shana","annie",};
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity_layout); ArrayAdapter<String> adapter = new ArrayAdapter<String>(
MainActivity.this, android.R.layout.simple_list_item_1,data);
ListView listView = (ListView)findViewById(R.id.list_view);
listView.setAdapter(adapter);
}
}

a.提供好数据,用一组字符串数组data来测试。

b.数组中数据无法直接传递给ListView,需要借助适配器来完成。

ArrayAdapter通过泛型来指定要适配的数据类型,然后在构造函数中把要适配的数据传入。

将ArrayAdapter的泛型指定为String,在构造函数中依次上传当前上下文、ListView子项布局的id、以及要适配的数据。

运行程序的结果

3.5.2 定制ListView的界面

对ListView界面进行定制,让显示更丰富的内容,实现让英雄名称旁边都有各自对应的英雄头像

1.准备好一组图片存在drawable-hdpi

2.定义一个实体类,作为ListView适配器的适配类型。新建类Hero

public class Hero {
private String name;
private int imageId; public Hero(String name, int imageId) {
this.name = name;
this.imageId = imageId;
} public String getName() { return name;
}
public int getImageId(){
return imageId;
}
}

name表示英雄名字,imageId表示对应的图片资源id

3.在layout目录下新建hero_item.xml为ListView指定自定义的布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"> <ImageView
android:id="@+id/hero_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" /> <TextView
android:id="@+id/hero_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"/> </LinearLayout>

4.创建一个自定义的适配器,继承自ArrayAdapter,并将泛型指向Hero类。

新建类HeroAdapter。

HeroAdapter重写了父类的一组构造方法,用于将上下文,ListView子项布局的id和数据都传递进来。

另外又重写了getView()方法。首先通过getItem()方法得到当前项的Hero实例,然后使用LayoutInflater来为这个子项加载传入的布局。inflate()方法接受3个参数,第三个参数指定成false,表明只让在父布局中声明layout属性生效,但不会为这个View添加父布局。

接下来调用View的findViewById()方法分别获取ImageView和TextView的实例,并分别调用它们的setImageResource()和setText()方法来设置显示的图片和文字,最后将布局返回。

import android.content.Context;
import android.provider.ContactsContract;
import android.support.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView; import java.util.List; public class HeroAdapter extends ArrayAdapter<Hero> {
private int resourceId; public HeroAdapter(Context context, int textViewResoureced,
List<Hero> objects){
super(context, textViewResoureced, objects);
resourceId = textViewResoureced;
} @NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Hero hero = getItem(position);
View view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
ImageView heroImage = (ImageView) view.findViewById(R.id.hero_image);
TextView heroName = (TextView)view.findViewById(R.id.hero_name);
heroImage.setImageResource(hero.getImageId());
heroName.setText(hero.getName());
return view;
}
}

5.修改MainActivity中的代码

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView; import java.util.ArrayList;
import java.util.List; public class MainActivity extends AppCompatActivity {
private List<Hero> heroList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initHeros();
HeroAdapter adapter = new HeroAdapter(MainActivity.this,
R.layout.hero_item,heroList);
ListView listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);
} private void initHeros(){
for(int i = 0 ; i < 2 ; i ++){
Hero gareen = new Hero("gareen",R.drawable.gareen);
heroList.add(gareen);
Hero annie = new Hero("annie",R.drawable.annie);
heroList.add(annie);
Hero teemo = new Hero("teemo",R.drawable.teemo);
heroList.add(teemo);
Hero shana = new Hero("shana",R.drawable.shana);
heroList.add(shana);
}
}
}

initHeros()方法用于初始化所有的英雄数据。

在Hero类的构造函数中将水果的名字和对应的图片id传入,然后把创建好的对象添加到英雄列表中。

接着在onCreat()方法中创建了HeroAdapter对象,并将HeroAdapter作为适配器传递给ListView。

运行程序。

定制界面完成。

3.5.3 提升ListView的运行效率

getView()方法中有一个convertView参数,这个参数用于将之前加载好的布局进行缓存,以便之后可以重用。

1.HeroAdapter的gatView()方法中每次都将布局重新加载一边,当ListView快速滚动时,就有可能成为性能的瓶颈。

修改HeroAdapter中的代码

 @Override
public View getView(int position, View convertView, ViewGroup parent) {
Hero hero = getItem(position);
View view;
if(convertView == null){
view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
}else{
view = convertView;
}
ImageView heroImage = (ImageView) view.findViewById(R.id.hero_image);
TextView heroName = (TextView)view.findViewById(R.id.hero_name);
heroImage.setImageResource(hero.getImageId());
heroName.setText(hero.getName());
return view;
}
 if(convertView == null){
view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
}else{
view = convertView;
}

表示对convertView进行判断,如果为null,则使用LayoutInflater去加载布局,如果不为null则直接对convertView直接重用。

2. 每次在getView()中会调用View的findViewById()方法来获取一次控件的实例。可以用ViewHolder来对这部分进行优化。

修改HeroAdapter中的代码。

  @Override
public View getView(int position, View convertView, ViewGroup parent) {
Hero hero = getItem(position);
View view;
ViewHolder viewHolder;
if(convertView == null){
view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
viewHolder = new ViewHolder();
viewHolder.heroImage = (ImageView)view.findViewById(R.id.hero_image);
viewHolder.heroName = (TextView)view.findViewById(R.id.hero_name);
view.setTag(viewHolder);
}else{
view = convertView;
viewHolder = (ViewHolder)view.getTag();//重新获取ViewHolder
}
viewHolder.heroImage.setImageResource(hero.getImageId());
viewHolder.heroName.setText(hero.getName());
return view;
} class ViewHolder{
ImageView heroImage;
TextView heroName;
}
     View view;
ViewHolder viewHolder;
if(convertView == null){
view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
viewHolder = new ViewHolder();
viewHolder.heroImage = (ImageView)view.findViewById(R.id.hero_image);
viewHolder.heroName = (TextView)view.findViewById(R.id.hero_name);
view.setTag(viewHolder);
}else{
view = convertView;
viewHolder = (ViewHolder)view.getTag();//重新获取ViewHolder
}
viewHolder.heroImage.setImageResource(hero.getImageId());
viewHolder.heroName.setText(hero.getName());
  class ViewHolder{
ImageView heroImage;
TextView heroName;
}

提供一个内部类ViewHolder,用于对控件进行缓存。当convertView为null时,创建一个ViewHolder对象,并将控件的实例都存放在ViewHolder中,然后调用setTag()方法,将ViewHolder对象储存在VIew中。当convertView不为null时,则调用View的getTag()方法,把ViewHolder重新取出。

所有控件实例都缓存在VIewHolder中,就没有必要每次通过findViewById()方法来获取控件实例了。

3.5.4 ListView的点击事件

给每一个Item添加Toast,修改MainActivity中的代码。

     ListView listView = (ListView) findViewById(R.id.list_view);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Hero hero = heroList.get(position);
Toast.makeText(MainActivity.this, hero.getName(), Toast.LENGTH_SHORT).show();
}
});

用setOnItemClikListener()方法为ListView注册一个监听器,当用户点击了ListView中的任何一个子项时,就会回调onItemClick()方法。在该方法中即可通过position参数判断出用户点击的是哪一个子项,然后获得相应的name,通过Toast展现出来。

<Android基础>(三) UI开发 Part 2 ListView的更多相关文章

  1. <Android基础>(三) UI开发 Part 3 RecyclerView

    RecyclerView 1)RecyclerView的基本用法 2)横向滚动和瀑布流滚动 3)注册点击事件 3.6 强大的滚动控件 RecyclerView ListView缺点: 1.不使用技巧优 ...

  2. <Android基础>(三) UI开发 Part 1

    1.常用控件 1)TextView 2)Button 3)EditText 4)ImageView 5)ProgressBar 6)AlertDialog 7)ProgressDialog 2.四种布 ...

  3. android 基础项目及开发出现:error opening trace file: No such file or directory错误解决

    本身这个错误不影响运行,但是看着烦啊.解决方案几种如下: 1.xml标签不完整或者未关闭,常有的事.Eclipse并不是所有的xml标记都检查,单双标记什么的. 2.有人说,据说是 android a ...

  4. UI开发模式对比:JSP、Android、Flex

    前一篇文章分析了Java平台下不同类型WEB框架对开发模式的影响,多数Java领域的WEB框架都是聚焦于服务端MVC的实现,这些框架对View的支持,通常是基于标准的JSP或类似JSP的模板技术如Fr ...

  5. Android与Swift iOS开发:语言与框架对比

    Swift是现在Apple主推的语言,2014年新推出的语言,比Scala等“新”语言还要年轻10岁.2015年秋已经开源.目前在linux上可用,最近已经支持Android NDK:在树莓派上有Sw ...

  6. Android UI开发第三十一篇——Android的Holo Theme

    好长时间没写Android UI方面的文章了,今天就闲扯一下Android的Holo主题.一直做android开发的可能都知道,Android 系统的UI有过两次大的变化,一次是android 3.0 ...

  7. 【Android】11.0 UI开发(二)——列表控件ListView的简单实现1

    ************************ 转载请注明出处:https://www.cnblogs.com/xiaofu007/p/10342462.html ***************** ...

  8. 【转】Android UI开发第三十一篇——Android的Holo Theme

    好长时间没写Android UI方面的文章了,今天就闲扯一下Android的Holo主题.一直做android开发的可能都知道,Android 系统的UI有过两次大的变化,一次是android 3.0 ...

  9. Android UI开发第三十九篇——Tab界面实现汇总及比较

    Tab布局是iOS的经典布局,Android应用中也有大量应用,前面也写过Android中TAb的实现,<Android UI开发第十八篇——ActivityGroup实现tab功能>.这 ...

随机推荐

  1. Python进阶之模块

    在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护. 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很 ...

  2. java实现Windows记事本

    给大家分享下我之前的作品: 源文件下载: 链接:https://pan.baidu.com/s/1N45VsS9aVgmvhvYjRLxBrA  提取码:b9fg  源码: JF_Notpad.jav ...

  3. Spring MVC 表单校验 (七)

    完整的项目案例: springmvc.zip 目录 实例 除了依赖spring-webmvc还需要依赖jackson-databind(用于转换json数据格式)和hibernate-validato ...

  4. 微信js-sdk开发获取签名和获取地理位置接口示例

    ###微信js-sdk开发获取签名和获取地理位置接口示例 前言:在做微信公众号开发时需要获取用户的地理位置信息,之前通过高德或者百度.腾讯等地图的api时发现经常获取不到,毕竟第三方的东西,后来改为采 ...

  5. SQLServer之创建INSTEAD OF INSERT,UPDATE,DELETE触发器

    INSTEAD OF触发器工作原理 INSTEAD OF表示并不执行其所定义的操作INSERT,UPDATE ,DELETE,而仅是执行触发器本身,即当对表进行INSERT.UPDATE 或 DELE ...

  6. SQLServer之创建非聚集索引

    开始之前 典型实现 可以通过下列方法实现非聚集索引: UNIQUE 约束 在创建 UNIQUE 约束时,默认情况下将创建唯一非聚集索引,以便强制 UNIQUE 约束. 如果不存在该表的聚集索引,则可以 ...

  7. C#默认参数原理探究

    起因 写这一篇的起因是想要通过新增默认参数来代替以前的方法,结果发现尽管在调用时写起来一样,实际上也没有被当做同样的方法,两个方法大致如下: // 先前的方法-删除 private static st ...

  8. django自定义分页器

    一 django 的分页器 1 批量创建数据 批量导入数据: Booklist=[] for i in range(100): Booklist.append(Book(title="boo ...

  9. 【js】this问题

    var obj = { a: 10, b: () => { console.log(this.a); // undefined console.log(this); // Window {pos ...

  10. 前端——DOM

    什么是DOM? DOM是W3C(万维网联盟)的标准,是Document Object Model(文档对象模型)的缩写,它定义了访问HTML和XML文档的标准: “W3C文档对象模型(DOM)是中立于 ...