一、自定义控件的实现

  自定义控件需要继承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自定义控件深刻理解的更多相关文章

  1. android:Layout_weight的深刻理解

    最近写Demo,突然发现了Layout_weight这个属性,发现网上有很多关于这个属性的有意思的讨论,可是找了好多资料都没有找到一个能够说的清楚的,于是自己结合网上资料研究了一下,终于迎刃而解,写出 ...

  2. Android中自定义控件TextSize属性问题

    本文主要说明一个自定义控件添加TextSize属性的坑,刚刚从坑里面爬出来,写个随笔,记录一下: *************************************************** ...

  3. Atitit 图像处理 深刻理解梯度原理计算.v1 qc8

    Atitit 图像处理 深刻理解梯度原理计算.v1 qc8 1.1. 图像处理  梯度计算  基本梯度 内部梯度 外部梯度 方向梯度1 2. 图像梯度就是图像边缘吗?2 1.1. 图像处理  梯度计算 ...

  4. 深刻理解Java中final的作用(一):从final的作用剖析String被设计成不可变类的深层原因

    声明:本博客为原创博客,未经同意,不得转载!小伙伴们假设是在别的地方看到的话,建议还是来csdn上看吧(原文链接为http://blog.csdn.net/bettarwang/article/det ...

  5. for循环,你深刻理解了吗?

    前几天,有一个面试机会,去看了看,遇到一个认为不错的面试题!   过了几天看到csdn上说华为的一道面试题,看了下和我遇到的很相似!   我分享出来希望大家有帮助!   你真的深刻理解for循环了吗? ...

  6. 【转】Android菜单详解——理解android中的Menu--不错

    原文网址:http://www.cnblogs.com/qingblog/archive/2012/06/08/2541709.html 前言 今天看了pro android 3中menu这一章,对A ...

  7. 深刻理解iosBlock

    深刻理解iosBlock ///一个控制器里的方法 - (void)setRefreshHeader { ACWeakSelf(self); self.tableView.mj_header = [M ...

  8. javascript 面向对象程序设计--深刻理解对象

    javascript中,每个对象都是基于一个引用类型创建的,我们可以把ECMAScript 的对象想象成散列表:无非就是一组名值对,其中值可以是数据或函数. 深刻理解对象 创建自定义对象的最简单方式就 ...

  9. [转]深刻理解Python中的元类(metaclass)以及元类实现单例模式

    使用元类 深刻理解Python中的元类(metaclass)以及元类实现单例模式 在看一些框架源代码的过程中碰到很多元类的实例,看起来很吃力很晦涩:在看python cookbook中关于元类创建单例 ...

随机推荐

  1. 64位ubuntu下重新编译hadoop2.2流水账

    hadoop官方网站中只提供了32位的hadoop-2.2.0.tar.gz,如果要在64位ubuntu下部署hadoop-2.2.0,就需要重新编译源码包,生成64位的部署包.建议以下操作使用roo ...

  2. 在Salesforce中实现对Object的增删改查操作

    1): Insert Statement    http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#CSHID=ap ...

  3. 编译原理实习(应用预测分析法LL(1)实现语法分析)

    #include<iostream> #include<fstream> #include<iomanip> #include<cstdio> #inc ...

  4. C++ 拷贝构造函数 和 六大函数

    1.  C++什么时候会调用 拷贝构造函数? a.一个对象作为函数参数,以值传递的方式传入函数体: b.一个对象作为函数返回值,以值传递的方式从函数返回:(实际使用时,会被编译器优化掉) c.一个对象 ...

  5. 关于MFC OpenGL环境配置的一点总结

    复制include时要小心..看vs给你load哪一个..名字一样..东西可不一定一样哦 http://www.cppblog.com/wicbnu/archive/2010/09/30/128123 ...

  6. SQLServer 维护脚本分享(10)索引

    --可添加索引的字段 migs.user_seeks,migs.avg_total_user_cost,migs.avg_user_impact,migs.last_user_seek ,mid.st ...

  7. 用super daemon xinetd进行安全配置

    xinetd 可以进行安全性或者是其他的管理机制的控制,这些控制手段都可以让我们的服务更为安全,资源管理更为合理.一些对客户端开放较多权限的服务(例如telnet)或者本身不带有管理机制的服务就可以通 ...

  8. shell实现https登录

    服务端提供了两个api: 一个是用于用户认证,因为要传输密钥,所以用了https方式  如何在服务端配置https请见另外一个博文 https://192.168.1.190:8443/api/aut ...

  9. Shell 编程基础之 Until 练习

    一.语法 until [ condition ] # 和while相反,当 condition 条件成立时,就终止回圈, 否则就持续进行回圈的程序段 do #执行内容 done 二.练习 输入用户输入 ...

  10. 【oracle】oracle启动和关闭步骤

    前言: 首先要知道,Oracle数据库的完整启动过程是分步骤完成的,包含以下3个步骤: 启动实例-->加载数据库-->打开数据库 因为Oracle数据库启动过程中不同的阶段可以对数据库进行 ...