【转】 Pro Android学习笔记(二二):用户界面和控制(10):自定义Adapter
我们可以同继承抽象类BaseAdapter来实现自己的Adapter,自己设置子View的UI,不同子View可以由不同的布局,并自己进行数据和子view中数据的对应关系。图是例子的呈现结果,我们有很多图标,对这些图标按一定大小进行缩放,然后布局在GridView中。这个例子很简单。
设计Adapter的布局
Activity的layout很简单,就只有一个GridView,我们继续沿用之前GridView例子中的XML文件,见Pro Android学习笔记(二十):用户界面和控制(8):GridView和Spinner,不再重复。
我们设计每个网格,即子view的布局,ui_gridimage.xml如下,也很简单,只含有一个控件ImageView,id为R.id.ui_myimage。
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ui_myimage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#555"
android:scaleType="centerInside"
android:padding="5dip"
android:maxHeight="50dip"
android:maxWidth="50dip" />
代码部分
Activity的代码
由于这个例子很小,自定义的Adapter以内部类的方式放在Activity中,一般应当独立为一个class。Activity的代码如下:
public class UiGridCustomTest1 extends Activity{
/* 和系统提供的Adapter方式在调用上没有什么不同,只是我们将在MyAdapter中直接获取数据,和直接指定如何呈现,不需要传递数据源等信息。*/
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ui_gridview);
GridView gv = (GridView)findViewById(R.id.ui_grid);
MyAdapter adapter = new MyAdapter(this);
gv.setAdapter(adapter);
}
/* MyAdatpter是自定义的Adapter。本例以内部类方式出现 */
private class MyAdapter extends BaseAdapter{
......
}
}
接下来,我们重点看看MyAdapter的代码。
MyAdapter的代码:数据源和构造函数
private class MyAdapter extends BaseAdapter{
private static final String TAG="MyAdapter"; //用于Log.d(TAG, ……);
private Context mContext = null;
private LayoutInflater infalter = null;
/* 【数据源(1)】: icons[]是图片资源的ID,是原始数据,通过资源ID生产Bitmap图片 myImages[],这是原始尺寸的图片,实际上,我们对图片做了进行伸缩处理,放置在myThumbs[]中,而myThumbs是需要呈现在UI的图片。 */
private int[] icons = {R.drawable.png01,R.drawable.png02,…(省略)…,R.drawable.png20};
private Bitmap[] myImages = new Bitmap[icons.length]; //原图
private Bitmap[] myThumbs = new Bitmap[icons.length]; //按尺寸伸缩图
private int convertViewCount = 0; //用于Log.d中的跟踪信息。
/* 用于存储子view中的控件,本例只有一个,比较简单。 */
private class ViewHolder{
ImageView image;
}
public MyAdapter(Context context){
/*【初始化(1)】:保存context,创建infalter,并于context关联。infalter可 从xml中创建view对象,非常方便。*/
mContext = context;
infalter = LayoutInflater.from(mContext);
/*【初始化(2)】【数据源(2)】:创建数据源,将资源ID转换为最终呈现的Bitmap信息*/
for(int i = 0 ; i <icons.length; i ++){
myImages[i] = BitmapFactory.decodeResource(context.getResources(), icons[i]);
//还可以使用ThumbnailUtils来处理相关的图片和视频
myThumbs[i] = Bitmap.createScaledBitmap(myImages[i], 100, 100, false);
}
}
......
}
MyAdapter的代码:实现自定义的adapter
MyAdapter集成抽象类BaseAdapter,有4个抽象方法必须实现,实际是来自BaseAdatper实现的Adapter接口。
private class MyAdapter extends BaseAdapter{
... ...
//How many items are in the data set represented by this Adapter.
//需要显示多少个item,本例即图片的数目。
public int getCount() {
Log.d(TAG,"getCount() return " + icons.length);
return icons.length;
}
// Get the data item associated with the specified position in the data set.
// 根据position返回该子view对应的data,用户无需考虑具体的UI布局就可获取data,拘役data如何获取和adapter的具体实现相关,例如CursorAdapter中读取联系人姓名的例子,我们是通过_ID从content provider中读取,在此可以直接返回null。
public Object getItem(int position) {
Log.d(TAG,"getItem(" + position + ")" );
return icons[position];
}
// Get the row id associated with the specified position in the list.
// 根据position获得rowId,在CursorAdapter的例子中,rowId为_ID,不一定和position一致,又例如在ListView中一行数据一行分隔符(分隔符也是一个子view,占一个position)的显示方法, rowId和position也不一致。
public long getItemId(int position) {
Log.d(TAG,"getItemId(position) is " + position);
return position;
}
// Get a View that displays the data at the specified position in the data set.
// 这是子View布局显示的实现,是最关键的代码部分。Android只会询问当前显示的子View的呈现, 也就是不显示的子view,系统不会调用getView(),这就很好地提高了性能。系统要显示某个子view的使用,就会根据position来调用该方法。
//参数2:convertView就是子View,如果第一次要求给出position的子view的呈现,convertView为null,我们上下滚动屏幕,系统会要求获得显示部分的各个子view的具体呈现,如果该子view之前已经创建,则convertView就是之前子view对象,我们可以利用系统保存的之前已经实现的子view对象,简化代码,提升效率。参数3 parent,从本例的层次上看就是GridView
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder; //存放该子view的控件,这样我们不用每次都通过Id来查找,直接引用对象。
Log.d(TAG,"getView() : position = " + position
+ " convertView = " + (convertView == null ? "null" : convertView.toString())
/*+ " parent : " + (parent == null ? "null" : parent.toString())*/);
//实现布局
if(convertView == null){ //子view第一次出现,需要构造,将重要内容(本例为控件对象)放置在viewHolder,并通过setTag()存放。
convertView = infalter.inflate(R.layout.ui_gridimage, null ); //通过xml来创建view
convertViewCount ++;
Log.d(TAG,"convertViewCount is " + convertViewCount);
holder = new ViewHolder();
holder.image = (ImageView) convertView.findViewById(R.id.ui_myimage);
// holder.image.setImageBitmap(myThumbs[position]);
convertView.setTag(holder);
}else{ //子view已经出现过,利用原来已经创建的对象,获得控件信息
holder = (ViewHolder)convertView.getTag();
Log.d(TAG,"image is " + holder.image.toString());
}
//将图片在view中呈现,这里有个地方不是很明白,我们如果放在convertView == null中,即只在第一次出现的时候对设置控件的图片,如果我们上下滚动屏幕,发现图片显示出现混乱现象,为何?
holder.image.setImageBitmap(myThumbs[position]);
return convertView; //返回子view的对象
}
}
MyAdapter的代码:继续探讨BaseAdapter
实现上面四个抽象函数,以及可以完成我们的例子,我们继续对BaseAdapter的其他一些有趣函数进行分析,我们还可以在例子中增加一些重写的方法。
private class MyAdapter extends BaseAdapter{
... ...
//返回在AdapterView中需要显示多少种子view,本例只有ImageView一种,故返回1。例如ListView,如果在数据之间有separator,即一行textView,一行separator,则返回2。
public int getViewTypeCount() {
Log.d(TAG, "in getViewTypeCount() :only one Type");
return 1;
}
//在创建每个子view,也就是在getView()之前,都调用该函数,询问这是哪种子view,如果有2种子view的,在返回值为0或1,如果有3种,返回0,1,2。本例只有一种子view,所以无论是哪个position,都返回0。在使用separator的例子中中,根据奇偶返回0,1,此外还要使用isEanble(int position),对于separator要返回false。
public int getItemViewType(int position) {
Log.d(TAG, "in getItemViewType() for position " + position);
return 0;
}
}
有更多的自定义Adapter的例子,可以参考Android学习笔记(十五):Activity-GalleryView、Android学习笔记(十九):建立自己的ListView 。
相关链接: 我的Android开发相关文章
【转】 Pro Android学习笔记(二二):用户界面和控制(10):自定义Adapter的更多相关文章
- 【转】Pro Android学习笔记(二五):用户界面和控制(13):LinearLayout和TableLayout
目录(?)[-] 布局Layout 线性布局LinearLayout 表格布局TableLayout 布局Layout Layout是容器,用于对所包含的view进行布局.layout是view的子类 ...
- 【转】 Pro Android学习笔记(二九):用户界面和控制(17):include和merge
目录(?)[-] xml控件代码重用include xml控件代码重用merge 横屏和竖屏landsacpe portrait xml控件代码重用:include 如果我们定义一个控件,需要在不同的 ...
- 【转】Pro Android学习笔记(二):开发环境:基础概念、连接真实设备、生命周期
在Android学习笔记(二):安装环境中已经有相应的内容.看看何为新.这是在source网站上的Android架构图,和标准图没有区别,只是这张图颜色好看多了,录之.本笔记主要讲述Android开发 ...
- 【转】 Pro Android学习笔记(二十):用户界面和控制(8):GridView和Spinner
目录(?)[-] GridView Spinner GridView GridView是网格状布局,如图所示.在了解ListView后,很容易了解GridView.下面是例子的XML文件. <? ...
- 【转】 Pro Android学习笔记(二一):用户界面和控制(9):Gallery和SimpleAdapter
Gallery画廊式控件,如图所示,但是在API level 16,也即Android 4.1,被deprecated,可以使用HorizontableScroolView和ViewPager.但是后 ...
- 【转】Pro Android学习笔记(二六):用户界面和控制(14):RelativeLayout
相对布局:RelativeLayout RelativeLayout也是非常常用的布局,能够精确对控件的位置进行网格对齐,可以设置在控件与其他控件的相对位置,以及控件在容器中的位置.缺省控件的位置为最 ...
- 【转】Pro Android学习笔记(二四):用户界面和控制(12):Style和Theme
目录(?)[-] 静态格式 代码中设定 Style Theme 静态格式 在res/values中设置静态的Style,在资源中设置静态Style可使用的HTML格式有<i> <u& ...
- 【转】 Pro Android学习笔记(五二):ActionBar(5):list模式
可以在action bar中加入spinner的下来菜单,有关spinner,可以参考Pro Android学习笔记(二十):用户界面和控制(8):GridView和Spinner. list的样式和 ...
- 【转】 Pro Android学习笔记(八二):了解Package(1):包和进程
文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ 在之前,我们已经学习了如何签发apk,见P ...
随机推荐
- What Every Computer Scientist Should Know About Floating-Point Arithmetic
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
- thymeleaf基本应用
Thymeleaf是个XML/XHTML/HTML5模板引擎,可以用于Web与非Web应用. Thymeleaf的主要目标在于提供一种可被浏览器正确显示的.格式良好的模板创建方式,因此也可以用作静态建 ...
- Bootstrap 第一天
Bootstrap第一天 1.什么是Bootstrap? Bootstrap是由两位设计开发的. Bootstrap主要是前端的框架(HTML.CSS.JS). 2.为什么使用Boot ...
- python网络爬虫之scrapy 调试以及爬取网页
Shell调试: 进入项目所在目录,scrapy shell “网址” 如下例中的: scrapy shell http://www.w3school.com.cn/xml/xml_syntax.as ...
- Nodejs课堂笔记-第二课 package.json的作用
本文由Vikings(http://www.cnblogs.com/vikings-blog/) 原创,转载请标明.谢谢! 上节课,我们打造了一下IDE工具-web storm的显示界面.至少现在回到 ...
- 如何禁止eclipse对js文件的校验(building validate)
在项目(project)上点击右键,依次选择1.Select Properties -> JavaScript -> Include Path2.Select Source tab. ( ...
- Arduino 看门狗使用
1.需要调用 #include <avr/wdt.h> 2.设置看门狗复位时间 wdt_enable(WDTO_2S); 代码时间定义的底层查看 #define WDTO_15MS 0 / ...
- C#调用大漠插件
大漠插件是一个很不错的东西,在按键精灵和易语言里面用得很多,可以后台找图找字,写游戏自动脚本用得特别多.前面写一个微信的自动脚本,查了一些资料,易语言不太熟悉,按键精灵功能上可能不好实现,就找了些资料 ...
- HDU - 5703 Desert 【找规律】
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5703 题意 给出一杯容量为N的水 每次至少喝1个单位 有多少种不同的方式喝完 比如 给出3 就有4种方 ...
- android OTA升级包制作【转】
本文转载自:http://www.thinksaas.cn/topics/0/445/445670.html 0.签名 java -Xmx2048m -jar out/host/linux-x86/f ...