一、引言
AdapterView本身是一个抽象类,而它派生的子类在用法上也基本相似,只是在显示上有一定区别,因此把他们也归为一类。
AdapterView具有如下特征:
- AdapterView继承自ViewGroup,本质是个容器
- AdapterView可以包含多个"列表项",并将这多个列表项以合适的形式展示。
- AdapterView显示的多个列表项的内容由Adapter提供
AdapterView及其子类的继承关系如下图所示:
由于Gallery是一个过时的API,Android推荐使用HorizontalScrollView来替代,所以我也不再对它进行学习。
而由AdapterView直接派生的三个类:AbsListView、AbsSpinner、AdapterViewAnimator也都是抽象类,所以我们用的最多的也就是图中第四行及以下的子类。
二、ListView
ListView就是我们所说的列表视图,也是我们最常用的一个组件,它是以垂直列表的形式展示所有数据项,而生成列表视图的方式主要有两种:
- 直接用ListView进行创建
- 让Activity继承ListActivity
而一旦获取到ListView后,对数据的填充就是由Adapter提供内容了,通常使用setAdapter方法。
ListView、GridView、Spinner等AdapterView都只是容器,而Apdater负责提供容器的内容。
AdapterView则负责采用合适的方式显示Adapter提供的内容。
AbsListView的常用属性和相关方法见下表:
属性 | 相关方法 | 说明 |
android:choiceMode | 设置AbsListView的选择方式: singleChoice:允许单选 multipleChoice:允许多选 multipleChoiceModal:允许多选 | |
android:drawSelectorOnTop | setDrawSelectorOnTop(boolean) | 如果该属性设置为true,选中的列表项将会显示在上面 |
android:fastScrollEnabled | 设置是否允许快速滚动。如果该属性设置为true,将会显示滚动图标,并允许用户拖动该滚动图标进行快速滚动。 | |
android:listSelector | setSelector(int) | 指定被选中的列表项上绘制的Drawable |
android:scrollingCache | 如果设置为true,则在滚动时将会使用缓存 | |
android:smoothScrollbar | setSmoothScrollbarEnabled(boolean) | 如果设置为false,则不在header View之后绘制分隔条 |
android:stackFromBottom | 设置是否从底端开始排列列表项 | |
android:textFilterEnabled | 设置是否对列表项进行过滤。只有当该AdapterView对应的Adapter实现了Filter接口时该属性才会作用。 | |
android:transcriptMode | 设置组件的滚动模式: disabled:关闭滚动(默认) normal:当该AbsListView收到数据改变通知,且最后一个列表项可见时,该AbsListView将会滚动到底端。 alwaysScroll:该AbsListView总会自动滚动到底端 |
ListView提供的属性如下表:
属性 | 说明 |
android:divider | 设置List列表项的分隔条(可用颜色分隔,也可用drawable对象分隔) |
android:dividerHeiht | 设置分隔条的高度 |
android:entries | 指定一个数组资源,Android将根据该数组资源来生成ListView |
android:footerDividerEnabled | 如果设置成false,则不在footer View之前绘制分隔条 |
andorid:headerDividerEnabled | 如果设置成false,则不再header View之前绘制分隔条 |
示例代码及显示效果图如下:
示例布局中只定义了一个ListView,并通过android:entries指定了数据源,通过android:divider指定了红色的分隔条。
数据源位于value/arrays.xml中,代码如下:
使用数组作为数据源十分简单,但是局限性也很大,能定制的内容也非常少,甚至字号大小,颜色都不能改变。
如果想对ListView的外观、行为进行定制,就需要把ListView作为AdapterView使用,通过Adapter控制列表项的显示和交互。
三、Adapter接口及其实现类
Adapter本身是一个接口,它派生了ListAdapter和SpinnerAdapter两个子接口,其中ListAdapter为AbsAdapter提供列表项,而SpinnerAdapter为AbsSpinner提供列表项。Adapter及其实现类的继承关系如下图所示:
其中ArrayAdapter、SimpleAdapter、SimpleCursorAdapter、BaseAdapter都是常用的实现类。
1.ArrayAdapter:简单、易用的Adapter,通常用于将数组或者List集合的多个值包装为列表项的数据源
2.SimpleAdapter:功能强大的Adapter,可用于将List集合的多个对象包装为列表项的数据源
3.SimpleCursorAdapter:与SimpleAdapter类似,只是用于包装Cursor提供的数据
4.BaseAdapter:通用用于被扩展。扩展BaseAdapter可以对各个列表项进行最大程度的定制。
3.1 ArrayAdapter
布局页和示意图如下:
布局中只有一个ListView,设置了分隔条为红色。看一下后台代码:
什么是单例
什么是单例模式:(Singleton)
单例模式的意图是是的类的对象成为系统中唯一的实例,供一个访问点,供客户类 共享资源
单例的使用场景
1.类只能有一个实例,而且必须从一个为人熟知的访问点对其进行访问,比如工厂方法
2.这个唯一的实例只能通过子类化进行扩展,而且扩展的对象不会破坏客户端代码
单例设计模式的要点:
1. 某个类只能有一个实例。
2.他必须自行创建这个对象
3.必须自行向整个系统供这个实例;
4.为了保证实例的唯一性,我们必须将
5.这个方法必须是一个静态类
代码实现:
Tools.h
// Person.h
// 练习2
//
// Created by king on 15/11/8.
// Copyright © 2015年 king. All rights reserved.
//
/*
创建一个person的单利对象。使用alloc,copy创建的时候时候只会产生一个对象,并且提供一个单利接入的方法(shareInstance)。
*/
#import <Foundation/Foundation.h>
// 遵守copy协议
@interface Tools : NSObject <NSCopying, NSMutableCopying>
// 一般情况下创建一个单例对象都有一个与之对应的类方法
// 一般情况下用于创建单例对象的方法名称都以share开头, 或者以default开头
+ (instancetype)shareInstance;
@end
Tools.m
@implementation Tools
+(instancetype)shareInstance {
Tools *instance = [[self alloc] init];
return instance;
}
// 定义一个全局变量
static Tools *_instance = nil;
+(instancetype)allocWithZone:(struct _NSZone *)zone {
/*
// 当前代码在多线程是可能会出现问题
if (_instance == nil) {
// 由于 alloc new copy mutableCopy 创建对象都会调用这个方法
// 所有我们只需要这里控制当前对象只创建一次
_instance = [[super allocWithZone:zone] init];
}
return _instance;
*/
// 当前代码在多线程也能用
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[super allocWithZone:zone] init];
});
return _instance;
}
- (id)copyWithZone:(NSZone *)zone {
return _instance;
}
- (id)mutableCopyWithZone:(NSZone *)zone {
return _instance;
}
@end
而在MRC中 如果调用 release 会发生运行时错误
所以我们需要从写 release retain retainCount
- (oneway void)release {
// 因为只会创建一次 所以我们不能释放当前对象
// 所有这里什么都不做
}
- (instancetype)retain {
return _instance;
}
- (NSUInteger)retainCount {
// 为了程序员之间方便交流 我们一般不写 1
// 而是写一个较大的值,让人一看就知道,这个对象时单例
// return 1;
return MAXFLOAT;
}
利用宏抽取优化代码
Singleton.h
#define interfaceSingleton(name) +(instancetype)share##name
#if __has_feature(objc_arc)
// ARC
#define implementationSingleton(name) \
+ (instancetype)share##name \
{ \
name *instance = [[self alloc] init]; \
return instance; \
} \
static name *_instance = nil; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [[super allocWithZone:zone] init]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instance; \
}
#else
// MRC
#define implementationSingleton(name) \
+ (instancetype)share##name \
{ \
name *instance = [[self alloc] init]; \
return instance; \
} \
static name *_instance = nil; \
+ (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
_instance = [[super allocWithZone:zone] init]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instanc
没有评论:
发表评论