作者:夏至 欢迎转载,也请保留这段申明,谢谢

ListView绝对可以称得上是Android中最常用的UI空间之一,同时也是跟之前难度。几乎所有的应用程序都会应用到它。当我们的程序中有大量的数九需要展示的时候,就可以借助ListView来实现。我们最常用的就是手机设置那里啦。

是不是很熟悉,这里既有图片又有文字。是不是比我们以前学的有意思多无聊?

不过在实践这个功能之前呢,我们先来了解一下Adapter适配器的意思。

1、Adapter 适配器

可以这样简单理解MAC 。 Model(数据)—> Controller(以什么方式显示)—> View (用户界面)
而这个Adapter则是中间的这个Controller的部分。如果还不理解,那就理解成你的电脑的电源的适配器是有型号的,不同电脑对应不同的适配器。相当于一个220V交流电压进来时,以什么样的方式(适配器)传到电脑。当然这只是个人见解,如有错误,也欢迎指出。
图二呢,是Adapter的继承关系图。这里看看就可以了。我们重点来讲解Adapter的三种方法

·BaseAdapter:抽象类,实际开发中我们会继承这个类并且重写相关方法,用得最多的一个Adapter!
·ArrayAdapter:支持泛型操作,最简单的一个Adapter,只能展现一行文字~
·SimpleAdapter:同样具有良好扩展性的一个Adapter,可以自定义多种效果!

这里我们就简单讲解一下ArrayAdapter 和 BaseAdapter 这两个最常用的。

1.1 ArrayAdapter 文字表示

首先,我们先来实现一下文字的方式,即最上面的setting那里,我们不要图片,只显示文字。别急,我们先从简单的开始。效果如这样:

这里之前没写,就直接盗用猪神的例子好了。

在layout那里,添加一个ListView的控件

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">    <ListView  android:id="@+id/list_item" android:layout_width="match_parent" android:layout_height="wrap_content" ></ListView></LinearLayout>

在主activity那里,我们写上:

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    //要显示的数据    String[] strs = {"基神","B神","翔神","曹神","J神"};    //创建ArrayAdapter    ArrayAdapter<String> adapter = new ArrayAdapter<String>                (this,android.R.layout.simple_expandable_list_item_1,strs);    //获取ListView对象,通过调用setAdapter方法为ListView设置Adapter设置适配器    ListView list_test = (ListView) findViewById(R.id.list_test);    list_test.setAdapter(adapter);    }}

代码很简单,你也可以不先定义string,用list_test.add(”“);的方式添加。

1.2 ArrayAdapter 图文并茂

首先,图片和文字我们是一个数据,所以,我们用在一个布局中,设置好相关的属性,然后再调用它。创建一个xml文件。用来显示图片和文字。

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content">    <ImageView  android:id="@+id/content_image" android:layout_width="64dp" android:layout_height="64dp" android:scaleType="fitCenter" android:baselineAlignBottom="true" android:paddingLeft="8dp" />    <LinearLayout  android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingTop="5dp" android:orientation="vertical">        <TextView  android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#1D1D1C" android:gravity="center" android:paddingLeft="10dp" android:textSize="14sp" />        <TextView  android:id="@+id/text2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:textColor="#B4B4B9" android:paddingLeft="10dp" android:layout_marginLeft="10dp" android:layout_marginBottom="10dp" android:textSize="12sp" />       </LinearLayout></LinearLayout>

接下来,创建两个类,Content 和 ContentAdapter。

为什么要创建这两个类,首先,从名字可以看得出来,Content是用来包裹我们刚才在布局写的图片和文字的信息;而这个内容,我们说过大数据都是用适配器来调用的,所以这里我们就用ContentAdapter来实现我们的适配器。那么在Content写上:

public class Content {private String name,say;    private int imageId;    public Content(String name, String say, int imageId) {        this.name = name;        this.imageId = imageId;        this.say = say;    }    public String getName() {        return name;    }    public int getImageId() {        return imageId;    }    public String getSay() {        return say;    }}

接下来我们需要自定义一个适配器ContentAdapter,用来继承ArrayAdapter,并将泛型制定为Content类

public class ContentAdapter extends ArrayAdapter<Content>{private int resourceId;   // context 表示我们要传入的内容,比如this // resource 表示我们要传进来刚刚新建的layout文件// List<Content> object 要传入的数据public ContentAdapter(Context context, int resource, List<Content> object) {    super(context, resource, object);    resourceId = resource;}@Override//converView 以前的布局的缓存// position 获取每一个Item的值,填充到制定的XML文件中// parent 当前布局会被加载到父布局中public View getView(int position, View convertView, ViewGroup parent) {    View view;    Content content = getItem(position);  //获取当前的Content实例    // 优化,这样可以减少重复加载;layout 布局文件    if(convertView == null) {  //如果刚开始创建    // LayoutInflater .. 表示动态加载布局,第二个参数我们一般选null    view = LayoutInflater.from(getContext()).inflate(resourceId, null); }else {            view = convertView;  //表示已经创建过了}    // 获取xml文件中的控件    ImageView ContentImage = (ImageView) view.findViewById(R.id.content_image);    TextView ContentName = (TextView)view.findViewById(R.id.text);    TextView ContentSay = (TextView)view.findViewById(R.id.text2);    // 重写方法,让图片和文字显示出来    ContentImage.setImageResource(content.getImageId());    ContentName.setText(content.getName());    ContentSay.setText(content.getSay());    return view;  //返回我们重新定制的布局}}

呼呼,就是这样,我已经把详细解释都注释在那里了,至于getView()方法,是每次我们在滚动屏幕时,都会被加载的。
然后是主activity啦。。。。

public class MainActivity extends AppCompatActivity {private String[] name = {"自古屌丝多薄命","无形被黑 最为致命","我赵日天第一个不服","无敌锐神"};    private String[] say  = {"要脸你就输了","你的贱就是我的贱","我将带头日狗","断剑重铸之日 骑士归来之时"};    private List<Content> contentList = new ArrayList<Content>();    protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.linearlayout);    initContens();  //初始化    ContentAdapter adapter = new ContentAdapter(MainActivity.this,    R.layout.content,contentList);  // 传入参数,我们自定义的适配器    ListView listView = (ListView)findViewById(R.id.list_item);    listView.setAdapter(adapter);  //显示出来// listView.setOnItemClickListener(new ArrayAdapterClick(this,contentList));}public void initContens(){contentList.add(new Content(name[0],say[0],R.drawable.image3));contentList.add(new Content(name[1],say[1],R.drawable.image4));contentList.add(new Content(name[2],say[2],R.drawable.image5));contentList.add(new Content(name[3],say[3],R.drawable.image6));}

这样就实现好了。不过呢,我们再为它添加一个点击事件,如果点了没有反应,那这个就没啥用了。

为了不在MAinActivity 中产生累赘代码,点击事件,我们也用一个class来实现好了,新建一个 ArrayAdapterClick.如:

public class ArrayAdapterClick implements AdapterView.OnItemClickListener{    private Context context;    private List<Content> contentList;    public ArrayAdapterClick(Context context,List<Content> contentList){        this.context = context;        this.contentList = contentList;}@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {        Content content = contentList.get(position);  //获取指定位置的数据        Toast.makeText(context,content.getName()+"\n"+content.getSay(),Toast.LENGTH_SHORT).show();    }}

然后我们再在主函数那里添加:

这样既ok啦。效果如图:

2、BaseAdapter

这里我们要实现的东西都是差不多的,都是图片再加文字,所以Content都是一样的,这里就不再赘述,这里我就讲不同点。 BaseAdapter 是个抽象类,所以里面的几个抽象方法我们都要重写。还是直接撸代码,部分注释我已经弄好了。新建一个类 BaseAdapterData.clss:

public class BaseAdaperData extends BaseAdapter{private String[] name = {"自古屌丝多薄命","无形被黑 最为致命","我赵日天第一个不服","我良辰最喜欢对有能力的人出手","无敌锐神"};private String[] say  = {"要脸你就输了","你的贱就是我的贱","我将带头日狗","我有一百种方法让你混不下去","断剑重铸之日 骑士归来之时"};// 这里初始化,我们在里面,用数组的方式private Content[] data= new Content[]{             new Content(name[0],say[0],R.drawable.image3),             new Content(name[1],say[1],R.drawable.image4),             new Content(name[2],say[2],R.drawable.image5),             new Content(name[3],say[3],R.drawable.image6),             new Content(name[4],say[4],R.drawable.image7),}; private Context context;  // 因为初始化什么的都在里面了,所以我们就只要传入context就行了 public BaseAdaperData(Context context){    this.context = context;  }    // 不要也行,直接传context,只是用getContext()这样标准一点 public Context getContext() {    return context; }@Overridepublic int getCount() {    return data.length;  //返回list所包裹的大小}@Overridepublic Content getItem(int position) {    return data[position];  //返回指定位置的内容}@Overridepublic long getItemId(int position) {    return 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {    View view;    // 优化    if(convertView == null){        // getContext() 用context替代也行        view = LayoutInflater.from(getContext()).inflate(R.layout.baseapaper,null);    }else{            view = convertView;    }    Content content = getItem(position); //获取实例    ImageView image = (ImageView) view.findViewById(R.id.imageview);    TextView ContentName = (TextView) view.findViewById(R.id.text);    TextView ContentSay = (TextView) view.findViewById(R.id.text2);    image.setImageResource(content.getImageId());    ContentName.setText(content.getName());    ContentSay.setText(content.getSay());        return view;    }}

看,和ArrayAdapter基本一样。详细注释可以看上面的ArrayAdapter。然后是主activity的

这样就ok啦,第三行是触发事件。

public class BaseAdapterDataClick implements AdapterView.OnItemClickListener{private BaseAdaperData object;    private Context context;    public BaseAdapterDataClick(Context context,BaseAdaperData object){        this.context = context;        this.object = object;}@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {    Content content = object.getItem(position);    Toast.makeText(context,content.getName()+"\n"+" "+content.getSay(),Toast.LENGTH_SHORT).show();    }}

好了,这样基本就可以了,可以对比一下。只有多对比,多实践才能明白。效果如图:

3. 优化资源

其实上面的优化还不算够好,虽然我们已经对布局进行了优化,但是对控件的优化,还是每次都是调用View 的 findViewById()方法来获取一次控件的实现。所以,这里我们采用ViewHolder 来对这部分进行性能优化。修改 BaseAdaperData.java ,如下:

public class BaseAdaperData extends BaseAdapter{     private String[] name = {"自古屌丝多薄命","无形被黑 最为致命","我赵日天第一个不服","我良辰最喜欢对有能力的人出手","无敌锐神"};     private String[] say  = {"要脸你就输了","你的贱就是我的贱","我将带头日狗","我有一百种方法让你混不下去","断剑重铸之日 骑士归来之时"};     //private String[] picture = {"R.drawable.image4","R.drawable.image5","R.drawable.image6","R.drawable.image7"};    // 这里初始化,我们在里面,用数组的方式     private Content[] data= new Content[]{             new Content(name[0],say[0],R.drawable.image3),             new Content(name[1],say[1],R.drawable.image4),             new Content(name[2],say[2],R.drawable.image5),             new Content(name[3],say[3],R.drawable.image6),             new Content(name[4],say[4],R.drawable.image7),     };    private Context context;  // 因为初始化什么的都在里面了,所以我们就只要传入context就行了    public BaseAdaperData(Context context){        this.context = context;    }    // 不要也行,直接传context,只是用getContext()这样标准一点     public Context getContext() {         return context;     }     @Override    public int getCount() {        return data.length;  //返回list所包裹的大小    }    @Override    public Content getItem(int position) {        return data[position];  //返回指定位置的内容    }    @Override    public long getItemId(int position) {        return 0;    }    class ViewHolder{        ImageView contentImage;        TextView  contentName;        TextView  contentSay;    }    public View getView(int position, View convertView, ViewGroup parent) {        View view;        // 优化        ViewHolder viewHolder;  // 对控件进行优化        if(convertView == null){            // getContext() 用context替代也行            view = LayoutInflater.from(getContext()).inflate(R.layout.baseapaper,null);            viewHolder = new ViewHolder();  //初始化            viewHolder.contentImage = (ImageView) view.findViewById(R.id.imageview);            viewHolder.contentName = (TextView) view.findViewById(R.id.text);            viewHolder.contentSay = (TextView) view.findViewById(R.id.text2);            view.setTag(viewHolder);  // 将ViewHolder 储存在View中        }else{            view = convertView;            viewHolder = (ViewHolder)view.getTag();  // 重新获得ViewHolder        }        Content content = getItem(position); //获取实例        viewHolder.contentImage.setImageResource(content.getImageId());        viewHolder.contentName.setText(content.getName());        viewHolder.contentSay.setText(content.getSay());        return view;    }}

其他都不用改变,这样就可以啦。
这里唠叨几句,很多网上都说 BaseAdapter 比 ArrayAdapter 好用。这里都是一样的,如果你不太明白抽象类的应用,我建议你还是用ArrayAdapter ,相对而言,也比较容易理解,也足够你捣鼓很多东西了。没必要把自己拖入一个死胡同,适用自己的才是最好的。

不过在后面,我将告诉你,为什么BaseAdapter 会比较好用,这里就先放个关子吧,总之都联系总是没错的。

如有错误,欢迎指出,如果喜欢,欢迎收藏!

更多相关文章

  1. android MVP——mvp架构的应用和优化
  2. Android(安卓)TTS 中文 文字转语音 使用TextToSpeech Svox
  3. Android列表选择框Spinner使用方法详解
  4. Android性能优化之Debug GPU Overdraw
  5. Android(安卓)UI性能优化——理论篇
  6. Android(安卓)Framework 框架系列之 App 启动优化
  7. Android(安卓)TextView文字太多显示的最后一行被盖住一半的解决
  8. Android内核开发:系统启动速度优化
  9. Android仿人人客户端(v5.7.1)——网络模块优化

随机推荐

  1. Android之Handler用法总结
  2. Android(java)学习笔记99:android的短信发送
  3. Android(安卓)Intents and Intent Filter
  4. 为android-support-v4.jar打包源码
  5. android获取安装的应用程序
  6. 2012 年最佳 Android(安卓)应用
  7. 软件工程预测一直都太不靠谱,如何做到不“
  8. 年薪百万程序员告诉你为什么说C语言不是
  9. 面试技巧:我是如何从低端面畜到高端面霸的
  10. 马斯克:毕业生擅长做 PPT,但不懂怎么带领企