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);---出现控指针异常

  • 相关阅读:
    pch文件配置出现 Expected unqualified-id 和 Unkown type name 'NSString'
    App Store Connect Operation Error ERROR ITMS-90032: "Invalid Image Path
    Xcode面板的使用
    KVO的使用
    苹果开发者账号注册-您在注册时提供的地址无效或者不完整
    Apple导出p12证书 导出证书为p12 Apple开发
    iOS开发-导出profile文件
    App Store提交审核报错 ERROR ITMS-90087解决办法
    Win10 的操作中心如果不见了
    什么时候调用dealloc
  • 原文地址:https://www.cnblogs.com/iamkk/p/5960924.html
Copyright © 2011-2022 走看看