zoukankan      html  css  js  c++  java
  • 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);---出现控指针异常

  • 相关阅读:
    Binary Tree Maximum Path Sum
    ZigZag Conversion
    Longest Common Prefix
    Reverse Linked List II
    Populating Next Right Pointers in Each Node
    Populating Next Right Pointers in Each Node II
    Rotate List
    Path Sum II
    [Leetcode]-- Gray Code
    Subsets II
  • 原文地址:https://www.cnblogs.com/iamkk/p/5960924.html
Copyright © 2011-2022 走看看