一、ListView
习题页面显示章节习题
习题详情页面显示习题的题目及选项,选择选项后判断选项是否正确
1.简单介绍ListView
listview是一个以垂直方式在项目中显示视图的列表。是一种不能实现确定视图中的内容的适配器视图(adapter view)。数据和视图的绑定,需要通过继承ListViewAdapter接口的适配器实现。确保当上下滚动的时候,能够动态刷新视图内容。通常我们都会自定义一个继承自BaseAdapter(已继承ListViewAdapter),ArrayAdapter(继承自BaseAdapter),SimpleAdapter(继承自BaseAdapter)的类,重写getView()方法,实现自己想要的功能。
getView方法详情
View getView (int position, View convertView, ViewGroup parent)
Get a View that displays the data at the specified position in the data set.
You can either create a View manually or inflate it from an XML layout file.
When the View is inflated, the parent View (GridView, ListView...) will apply
default layout parameters unless you useinflate(int, android.view.ViewGroup,boolean)to
specify a root view and to prevent attachment to the root
备注:使用适配器构建布局。
如果布局的内容是属于动态或未预先确定的内容,您可以使用这样一种布局:在运行时通过子类AdapterView用视图填充布局。AdapterView类的子类使用Adapter将数据与其布局绑定。
Adapter充当数据源与AdapterView布局之间的中间人—Adapter(从数组或数据库查询等来源)检索数据,并将每个条目转换为可以添加到AdapterView布局中的视图。
适配器支持的常见布局包括:
使用数据填充适配器视图
您可以通过将AdapterView实例与Adapter绑定来填充AdapterView(如ListView或GridView),此操作会从外部来源检索数据,并创建表示每个数据条目的View。
Android 提供了几个Adapter子类,用于检索不同种类的数据和构建AdapterView的视图。 两种最常见的适配器是:ArrayAdapter和SimpleCursorAdapter。
2.ListView使用步骤
1).在布局的XML文件中,添加如下代码:
android:id="@+id/list_view" android:layout_width="match_parent" android:layout_height="match_parent" /> 2)新建list_item的布局文件,确定每一个View的样式。 3).新建一个适配器类。 4).绑定数据到视图。 二、Adapter和AdapterView 根据记录数,加载每个view ListView在Android开发中十分常见 今天,我将为大家带来ListView与AdapterView全面解析,含其特点、工作原理等,希望你们会喜欢。 目录 示意图 1. 简介 Android中的一种列表视图组件 继承自AdapterView抽象类,类图关系如下 示意图 2. 作用 集合多个 “项”(称为:Item) & 以列表的形式 展示 示意图 3. 工作原理 3.1 本质原理 ListView仅作为容器(列表),用于装载 & 显示数据(即 列表项Item) 而容器内的具体数据(列表项Item)则是由 适配器(Adapter)提供 适配器(Adapter):作为View和 数据之间的桥梁 & 中介,将数据映射到要展示的View中 当需显示数据时,ListView会向Adapter取出数据,从而加载显示,具体如下图 示意图 结论 ListView负责以列表的形式显示Adapter提供的内容 3.2 缓存原理 试想一个场景:若把所有数据集合的信息都加载到ListView上显示,若ListView要为每个数据都创建一个视图,那么会占用非常多的内存 为了节省空间和时间,ListView不会为每一个数据创建一个视图,而是采用了Recycler组件,用于回收 & 复用View 当屏幕需显示x个Item时,那么ListView会创建x+1个视图;当第1个Item离开屏幕时,此Item的View被回收至缓存,入屏的Item的View会优先从该缓存中获取 注: 只有Item完全离开屏幕后才可复用,这也是为什么ListView要创建比屏幕需显示视图多1个的原因:缓冲 显示视图 即:第1个Item离开屏幕是有过程的,会有1个第1个Item的下半部分 & 第8个Item上半部分同时在屏幕中显示的状态,此时仍无法使用缓存的View,只能继续用新创建的视图View 实例演示 设:屏幕只能显示5个Item,那么ListView只会创建(5+1)个Item的视图;当第1个Item完全离开屏幕后才会回收至缓存从而复用(用于显示第7个Item) 三、适配器 初始化控件、获取控件、设置布局 Adapter(适配器的讲解) 适配器就我自己来看,我觉得这是一个非常重要的知识点,Adapter是用来帮助填出数据的中间桥梁,简单点说吧:将各种数据以合适的形式显示在View中给用户看。Adapter有很多的接口、抽象类、子类可以使用,这里就我们常用的几个进行讲解 BaseAdapter,ArrayAdapter,SimpleAdapter,为了配合讲解这几个适配器,这里提前使用一下ListView来展示一下适配器的使用,后面会对ListView进行进一步总结。 一、ArrayAdapter(数组适配器),这个适配器使用有一定的局限性,只能显示一行文本数据 (1)基本使用实例 布局文件: xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> android:id="@+id/ll1" android:layout_width="match_parent" android:layout_height="wrap_content"> Java文件 package com.example.test3;import android.app.Activity;import android.os.Bundle;import android.widget.ArrayAdapter;import android.widget.ListView;publicclassMainActivityextends Activity{// 定义要显示的数据privateString[] datas = {"张三","李四","王五","麻子","小强"}; privateArrayAdapter adapter; private ListView listView; @Override protectedvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.ll1);// 初始化适配器adapter =newArrayAdapter<>(this,android.R.layout.simple_expandable_list_item_1,datas); listView.setAdapter(adapter); } } 效果图: (2)实现上面还可以先在res\value下创建一个数组资源的xml文件:arrays.xml,然后在listview中使用entries 3、ArrayAdapter也支持泛型,那么集合肯定必须的,还可以如下所写 4、ArrayAdapter的参数说明: 第一个参数:context上下文对象 第二个参数:每一个item的样式,可以使用系统提供,也可以自定义就是一个TextView 第三个参数:数据源,要显示的数据 系统提供的item的样式,可以试一试 simple_list_item1:单独的一行文本框 simple_list_item2:有两个文本框组成 simple_list_item_checked每项都是由一个已选中的列表项 simple_list_item_multiple_choice:都带有一个复选框 simple_list_item_single_choice:都带有一个单选框 四、RecyclerView控件 为RecyclerView准备一个适配器,新建RecyclerViewAdapter类,让适配器继承自RecyclerView.Adapter,并将泛型指定RecyclerViewAdapter.ViewHolder。 RecyclerView 的基本用法 打开 app/build.gradle 文件,在 dependencies 闭包中添加如下内容: compile'com.android.support:recyclerview-v7:24.2.1' 添加完之后记得要点击一下 Sync Now 来进行同步。然后修改 activity_main.xml 中的代码, 如下所示: android:layout_width="match_parent" android:layout_height="match_parent"> android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent"/> 新建Fruit 类和 fruit_item.xml,代码如下所示: publicclassFruit{ privateString name; privateintimageId; publicFruit(String name,intimageId){ this.name = name; this.imageId = imageId; } publicStringgetName(){ returnname; } publicintgetImageId(){ returnimageId; } } Fruit 类中只有两个字段,name 表示水果的名字,imageId 表示水果对应图片的资源 id。 然后需要指定一个我们自定义的布局,在layout目录下新建fruit_item.xml, 代码如下所示: android:layout_width="match_parent" android:layout_height="wrap_content"> android:id="@+id/fruit_image" android:layout_width="wrap_content" android:layout_height="wrap_content"/> android:id="@+id/fruit_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginLeft="10dp"/> 接下来需要为 RecyclerView 准备一个适配器,新建 FruitAdapter 类,让这个适配器继承自 RecyclerView.Adapter,并将泛型指定为 FruitAdapter.ViewHolder。其中,ViewHolder 是我们在 FruitAdapter 中定义的一个内部类,代码如下所示: publicclassFruitAdapterextendsRecyclerView.Adapter{ privateList mFruitList; staticclassViewHolderextendsRecyclerView.ViewHolder{ ImageView fruitImage; TextView fruitName; publicViewHolder(View view){ super(view); fruitImage = (ImageView) view.findViewById(R.id.fruit_image); fruitName = (TextView) view.findViewById(R.id.fruit_name); } } publicFruitAdapter(List mFruitList = fruitList; } @Override publicViewHolderonCreateViewHolder(ViewGroup parent,intviewType){ View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.fruit_item, parent,false); ViewHolder holder =newViewHolder(view); returnholder; } @Override publicvoidonBindViewHolder(ViewHolder holder,intposition){ Fruit fruit = mFruitList.get(position); holder.fruitImage.setImageResource(fruit.getImageId()); holder.fruitName.setText(fruit.getName()); } @Override publicintgetItemCount(){ returnmFruitList.size(); } } 这里我们首 先定义了一个内部类 ViewHolder,ViewHolder 要继承自 RecyclerView.ViewHolder。然后 ViewHolder 的构造函数中要传入一个 View 参数,这个参数通常就是 RecyclerView 子项的最外层布局,那么我们就可以通过 findViewById()方法来获取到布局中的 ImageView 和 TextView 的实例了。 接着往下看,FruitAdapter 中也有一个构造函数,这个方法用于把要展示的数据源传进来, 并赋值给一个全局变量 mFruitList,我们后续的操作都将在这个数据源的基础上进行。 继续往下看,由于 FruitAdapter 是继承自 RecyclerView.Adapter 的,那么就必须重写 onCreateViewHolder()、onBindViewHolder()和 getItemCount()这 3 个方法。onCreateViewHolder()方法是用于创建 ViewHolder 实例的,我们在这个方法中将 fruit_item 布局加载 进来,然后创建一个 ViewHolder 实例,并把加载出来的布局传入到构造函数当中,最后将 ViewHolder 的实例返回。onBindViewHolder()方法是用于对 RecyclerView 子项的数据进行赋值 的,会在每个子项被滚动到屏幕内的时候执行,这里我们通过 position 参数得到当前项的 Fruit 实例,然后再将数据设置到 ViewHolder 的 ImageView 和 TextView 当中即可。getItemCount() 方法就非常简单了,它用于告诉 RecyclerView 一共有多少子项,直接返回数据源的长度就可以了。 适配器准备好了之后,我们就可以开始使用 RecyclerView 了,修改 MainActivity 中的代码, 如下所示: publicclassMainActivityextendsAppCompatActivity{ privateList fruitList =newArrayList<>(); @Override protectedvoidonCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initFruits();// 初始化水果数据 RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view); LinearLayoutManager layoutManager =newLinearLayoutManager(this); recyclerView.setLayoutManager(layoutManager); FruitAdapter adapter =newFruitAdapter(fruitList); recyclerView.setAdapter(adapter); } privatevoidinitFruits(){ for(inti =0; i <2; i++) { Fruit apple =newFruit("Apple", R.drawable.apple_pic); fruitList.add(apple); Fruit banana =newFruit("Banana", R.drawable.banana_pic); fruitList.add(banana); Fruit orange =newFruit("Orange", R.drawable.orange_pic); fruitList.add(orange); Fruit watermelon =newFruit("Watermelon", R.drawable.watermelon_pic); fruitList.add(watermelon); Fruit pear =newFruit("Pear", R.drawable.pear_pic); fruitList.add(pear); Fruit grape =newFruit("Grape", R.drawable.grape_pic); fruitList.add(grape); Fruit pineapple =newFruit("Pineapple", R.drawable.pineapple_pic); fruitList.add(pineapple); Fruit strawberry =newFruit("Strawberry", R.drawable.strawberry_pic); fruitList.add(strawberry); Fruit cherry =newFruit("Cherry", R.drawable.cherry_pic); fruitList.add(cherry); Fruit mango =newFruit("Mango", R.drawable.mango_pic); fruitList.add(mango); } } } 可以看到,这里使用了一个同样的 initFruits()方法,用于初始化所有的水果数据。接着 在 onCreate()方法中我们先获取到 RecyclerView 的实例,然后创建了一个 LinearLayoutManager 对象,并将它设置到 RecyclerView 当中。LayoutManager 用于指定 RecyclerView 的布局 方式,这里使用的 LinearLayoutManager 是线性布局的意思,可以实现和 ListView 类似的效果。 接下来我们创建了 FruitAdapter 的实例,并将水果数据传入到 FruitAdapter 的构造函数中, 最后调用 RecyclerView 的 setAdapter()方法来完成适配器设置,这样 RecyclerView 和数据之间 的关联就建立完成了。