android-BaseAdapter自定义控件深刻理解
一、自定义控件的实现
自定义控件需要继承BaseAdapter抽象类,该类实现了ListAdapter, SpinnerAdapter两个接口,这两个接口继承了Adapter接口类,没错、是继承Adapter接口;而自定义控件实现的四个方法也来自Adapter接口;
1、下面对这四个方法进行详细说明:
<1>public int getCount()
返回记录的数量,如果数据源是数组,返回的就是数组长度;如果数据原是集合,返回的就是集合的大小,即决定了显示了多少行;
<2>Object getItem(int position)
返回指定下标对应的对象;
<3>long getItemId(int position)
返回指定下标对应的id;
<4>View getView(int position, View convertView, ViewGroup parent);
返回下标对应的View视图对象
position:下标
convertView:可复用的缓存视图对象
为null:没有可复用的,必须加载一个item的布局文件,并赋值给convertView;
不为null:直接使用此视图对象。
parent:父容器(常用ListView)
2、给ListView的item设置监听器:
<1>item的点击监听:listView.setOnItemClickListener(listener)
<2>item的长按监听:listView.setOnItemLongClickListener(listener)
3、初步优化---防止内存溢出
a.内存中最多存在n+1个convertView对象
b.只有当convertView为null时才去加载item的布局文件。
练习:

从以上运行截图可知分别采用了ListView、GridView布局,界面布局过于简单不允给出;
1、ListView+BaseAdapter
该程序中用到一个AppInfo类,对查询出来的信息进行封装;
自定义适配器类继承BaseAdapter类,实现上述说明的四种方法;
为每一个item添加单击和长按事件监听;
getAllAppInfos()方法用于获取手机应用程序信息,packagename、label、icon、占用大小等,获取应用程序信息的详细介绍待续...
界面布局过程中使用到的重要属性:
scaleType="fitXY" //图片填充满View的宽度
minHeight="70dp" //最小高度
layout_gravity //控件本身相对于父视图的位置
gravity //指定控件中的内容的基本位置
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements OnItemLongClickListener{
private ListView lv_main;
private List<AppInfo> data;
private AppAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化成员变量
lv_main=(ListView) findViewById(R.id.lv_main);
data=getAllAppInfos();
adapter=new AppAdapter();
//显示列表
lv_main.setAdapter(adapter);
//设置监听器
lv_main.setOnItemClickListener(new OnItemClickListener() {
/*
* parent:为当前的ListView
* view:当前Item视图对象
* position:当前行的下标
*
* */
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//当前行应用程序名称
String appName=data.get(position).getAppName();
//提示
Toast.makeText(MainActivity.this, appName, 0).show();
}
});
lv_main.setOnItemLongClickListener(this);
}
class AppAdapter extends BaseAdapter{
@Override
public int getCount() {
return data.size();
}
@Override
public Object getItem(int position) {
return data.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
//返回带数据当前行的iten视图对象
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//1、判断如果convertView空,加载item布局文件
if (convertView==null) {
Log.e("TAG","谢荣康");
convertView=View.inflate(MainActivity.this, R.layout.item_main, null);
}
//2、得到当前行数据对象
AppInfo appInfo=data.get(position);
//3、得到当前行需要更新的子View对象
ImageView imageView=(ImageView)convertView.findViewById(R.id.iv_item_icon);
TextView textView=(TextView)convertView.findViewById(R.id.tv_item_name);
//4、给视图设置数据
imageView.setImageDrawable(appInfo.getIcon());
textView.setText(appInfo.getAppName());
//返回convertView
return convertView;
}
}
/*
* 得到手机所有应用信息
* Drawable:可绘制的图片
*
* */
protected List<AppInfo> getAllAppInfos(){
List<AppInfo> list=new ArrayList<>();
//得到应用的PackageManager---获得已经安装应用程序的信息
PackageManager packageManager=this.getPackageManager();
//创建主题界面的intent
Intent intent=new Intent();
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
//得到包含应用信息的列表
List<ResolveInfo> ResolveInfos=packageManager.queryIntentActivities(intent, 0);
//List<ResolveInfo> ResolveInfos=packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
//Collections.sort(ResolveInfos,new ResolveInfo.DisplayNameComparator(packageManager));
//遍历
for (ResolveInfo ri:ResolveInfos) {
//得到包名
String packageName=ri.activityInfo.packageName;
//得到图标
Drawable icon=ri.loadIcon(packageManager);
//得到应用的名称
String appName=ri.loadLabel(packageManager).toString();
//封装应用信息对象
AppInfo appInfo=new AppInfo(icon,appName,packageName);
//添加到list
list.add(appInfo);
}
return list;
}
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long id) {
/*
* 返回值false,长按和单击都会执行同样的功能
* */
//删除当前行并更新列表
data.remove(position);
/*
* 通知更新列表使用所有缓存的item视图对象,设置更新列表不使用
*
* */
adapter.notifyDataSetChanged();
//lv_main.setAdapter(adapter);
return true;
}
}
2、GridView+BaseAdapter
除item使用的父容器不同外基本和以上一致;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import android.widget.Toast;
public class MainActivity extends Activity {
private GridView gridView;
private MainAdapter adapter;
List<AppInfoBean> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gridView=(GridView) findViewById(R.id.gv_main);
adapter=new MainAdapter(this.getAllAppInfos(),this);
gridView.setAdapter(adapter);
gridView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, list.get(position).appName, 0).show();
}
});
}
protected List<AppInfoBean> getAllAppInfos(){
list=new ArrayList<>();
//得到应用的PackageManager---获得已经安装应用程序的信息
PackageManager packageManager=this.getPackageManager();
//创建主题界面的intent
Intent intent=new Intent();
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
//得到包含应用信息的列表
List<ResolveInfo> ResolveInfos=packageManager.queryIntentActivities(intent, 0);
//List<ResolveInfo> ResolveInfos=packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
//Collections.sort(ResolveInfos,new ResolveInfo.DisplayNameComparator(packageManager));
//遍历
for (ResolveInfo ri:ResolveInfos) {
//得到图标
Drawable icon=ri.loadIcon(packageManager);
//得到应用的名称
String appName=ri.loadLabel(packageManager).toString();
//封装应用信息对象
AppInfoBean appInfo=new AppInfoBean(icon,appName);
//添加到list
list.add(appInfo);
}
return list;
}
}
import java.util.List;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class MainAdapter extends BaseAdapter {
List<AppInfoBean> data;
Context context;
public MainAdapter(List<AppInfoBean> list,Context context) {
this.context=context;
data=list;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return data.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return data.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//1、判断如果convertView空,加载item布局文件
if (convertView==null) {
Log.e("TAG","谢荣康");
convertView=View.inflate(context, R.layout.item_main, null);
}
//2、得到当前行数据对象
AppInfoBean appInfo=data.get(position);
//3、得到当前行需要更新的子View对象
ImageView imageView=(ImageView)convertView.findViewById(R.id.iv_item_icon);
TextView textView=(TextView)convertView.findViewById(R.id.tv_item_name);
//4、给视图设置数据
imageView.setImageDrawable(appInfo.getIcon());
textView.setText(appInfo.getAppName());
return convertView;
}
}
二、问题
1、空指针异常
ImageView imageView=(ImageView)convertView.findViewById(R.id.iv_item_icon);
ImageView imageView=(ImageView)findViewById(R.id.iv_item_icon);---出现控指针异常
android-BaseAdapter自定义控件深刻理解的更多相关文章
- android:Layout_weight的深刻理解
最近写Demo,突然发现了Layout_weight这个属性,发现网上有很多关于这个属性的有意思的讨论,可是找了好多资料都没有找到一个能够说的清楚的,于是自己结合网上资料研究了一下,终于迎刃而解,写出 ...
- Android中自定义控件TextSize属性问题
本文主要说明一个自定义控件添加TextSize属性的坑,刚刚从坑里面爬出来,写个随笔,记录一下: *************************************************** ...
- Atitit 图像处理 深刻理解梯度原理计算.v1 qc8
Atitit 图像处理 深刻理解梯度原理计算.v1 qc8 1.1. 图像处理 梯度计算 基本梯度 内部梯度 外部梯度 方向梯度1 2. 图像梯度就是图像边缘吗?2 1.1. 图像处理 梯度计算 ...
- 深刻理解Java中final的作用(一):从final的作用剖析String被设计成不可变类的深层原因
声明:本博客为原创博客,未经同意,不得转载!小伙伴们假设是在别的地方看到的话,建议还是来csdn上看吧(原文链接为http://blog.csdn.net/bettarwang/article/det ...
- for循环,你深刻理解了吗?
前几天,有一个面试机会,去看了看,遇到一个认为不错的面试题! 过了几天看到csdn上说华为的一道面试题,看了下和我遇到的很相似! 我分享出来希望大家有帮助! 你真的深刻理解for循环了吗? ...
- 【转】Android菜单详解——理解android中的Menu--不错
原文网址:http://www.cnblogs.com/qingblog/archive/2012/06/08/2541709.html 前言 今天看了pro android 3中menu这一章,对A ...
- 深刻理解iosBlock
深刻理解iosBlock ///一个控制器里的方法 - (void)setRefreshHeader { ACWeakSelf(self); self.tableView.mj_header = [M ...
- javascript 面向对象程序设计--深刻理解对象
javascript中,每个对象都是基于一个引用类型创建的,我们可以把ECMAScript 的对象想象成散列表:无非就是一组名值对,其中值可以是数据或函数. 深刻理解对象 创建自定义对象的最简单方式就 ...
- [转]深刻理解Python中的元类(metaclass)以及元类实现单例模式
使用元类 深刻理解Python中的元类(metaclass)以及元类实现单例模式 在看一些框架源代码的过程中碰到很多元类的实例,看起来很吃力很晦涩:在看python cookbook中关于元类创建单例 ...
随机推荐
- 推荐一些顶级的Android开发书籍(转)
本帖对Android开发菜鸟和中级老兵同样适用,因为本帖重点列出了那些最常用的Android开发资源. 推荐书籍 你或许觉得,都现在了,再去看个什么书来学习Android开发,这方法应该早就过时了.没 ...
- 智能车学习(五)—— dac学习
一.代码共享: 1.dac.h #ifndef DAC_H_ #define DAC_H_ #include "common.h" // 2.2 DAC控制寄存器0 位定义 #de ...
- Linux学习笔记(22) Linux启动管理
1. 系统运行级别 运行级别 含义 关机 1 单用户模式,可想象为windows的安全模式,主要用于系统修复 2 不完全的命令行模式,不含NFS服务 完全的命令行模式,就是标准字符界面 4 系统保留 ...
- T-SQL 基础编程
Ø Go批处理语句 用于同时执行多个语句 Ø 使用.切换数据库 use master go Ø 创建.删除数据库 方法1. --判断是否存在该数据库,存在就删除 if (exists (select ...
- 【MyEcplise SVN】myEcplise上安装SVN的多种方式
第一种:SVN的在线安装 1.打开MyEclipse,找到顶部菜单栏 Help(帮助)-Install from Site-(从网站安装),如下图 2. 然后: 点击Install from Site ...
- 网页细分图结果分析(Web Page Diagnostics)
Discuz开源论坛网页细分图结果分析(Web Page Diagnostics) 续LR实战之Discuz开源论坛项目,之前一直是创建虚拟用户脚本(Virtual User Generator)和场 ...
- js正则表达式练习
匹配完整的名字 function process_name() { var field = document.getElementById("name_field"); var n ...
- express-9 Handlebars模板引擎(2)
视图和布局 视图通常表现为网站上的各个页面(它也可以表现为页面中AJAX局部加载的内容,或一封电子邮件,或页面上的任何东西).默认情况下,Express会在views子目录中查找视图.布局是一种特殊的 ...
- iOS10 UI教程基础窗口的内容与设置起始窗口
iOS10 UI教程基础窗口的内容与设置起始窗口 iOS10 UI教程基础窗口的内容与设置起始窗口,本章我们从iOS10开发中UI的基础知识开始讲解,其中包括了窗口.视图以及UI层次结构和Views的 ...
- 安装和配置Tomcat
今天第一个技术难题,说难也不难,被鄙视的彻彻底底. 理解上的问题纠正:Xftp里面我们看到的只是自己电脑上和所连接服务器里面的文件,集群里面有master 服务器和slaves 服务器 ,一个Nam ...