ListView 是手机系统上应用非常非常广泛的一种组件,它以垂直列表的形式显示所有列表项。
一、怎样去布局ListView
ListView额外提供如图以下的xml属性:
android:divider="#000"设置分割条为纯黑色
android:dividerHeight="3sp" 设置分割条高度为3dp
android:divider="@drawable/news_test1" 设置分割条为图片news_test1
android:entries="@array/books" 指定books列表数组,还需在应用中定义一个名为books的数组,一般是提供Adapter
布局ListView的一个条目item的布局:当布局好ListView之后,可以根据需要对每个条目进行布局,以新闻的条目为例如下:
条目中的初始数据可以假设初设定。当代码进行操作后,会产生如下布局: 在条目上分别设有图片、新闻题目、新闻内容简介。 二、代码组成和适配器Adapter 先看下代码: package com.itheima.news_listview.adapter; import java.util.ArrayList; import com.itheima.news_listview.R; import com.itheima.news_listview.bean.NewsBean; import android.content.Context; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; public class NewsAdapter extends BaseAdapter { private ArrayList list; private Context context; public NewsAdapter(Context context,ArrayList list){ this.list = list; this.context = context; } @Override public int getCount() { return list == null?0:list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { Log.i("TAG", "$$$$$$$$$$$$"+position); View view = null; if(convertView != null){ view = convertView; }else { LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = layoutInflater.inflate(R.layout.item_news_layout, null); } //获取子控件的对象 ImageView item_img_icon = (ImageView) view.findViewById(R.id.item_img_icon); TextView item_tv_des = (TextView) view.findViewById(R.id.item_tv_des); TextView item_tv_title = (TextView) view.findViewById(R.id.item_tv_title); // 获取postion位置的对应list集合中的新闻数据 NewsBean newsBean = list.get(position); //设置标题 item_tv_title.setText(newsBean.title); //设置内容 item_tv_des.setText(newsBean.des); item_img_icon.setImageDrawable(newsBean.icon); return view; } } 先讲ListView和Adapter怎样工作的: 每当有一个条目暴露在屏幕下,adapter适配器就会为这个条目创建出item布局。每次滑动就会把新暴露出来的条目进行加载。在代码中添加的打印:Log.i("TAG", "$$$$$$$$$$$$创建的条目个数为:"+position);如果当前代码如下: public View getView(int position, View convertView, ViewGroup parent) { Log.i("TAG", "$$$$$$$$$$$$创建的条目个数为:"+position); View view = null; // if(convertView != null){ // view = convertView; // }else { LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = layoutInflater.inflate(R.layout.item_news_layout, null); //} //获取子控件的对象 ImageView item_img_icon = (ImageView) view.findViewById(R.id.item_img_icon); TextView item_tv_des = (TextView) view.findViewById(R.id.item_tv_des); TextView item_tv_title = (TextView) view.findViewById(R.id.item_tv_title); // 获取postion位置的对应list集合中的新闻数据 NewsBean newsBean = list.get(position); //设置标题 item_tv_title.setText(newsBean.title); //设置内容 item_tv_des.setText(newsBean.des); item_img_icon.setImageDrawable(newsBean.icon); return view; } } 当滑动ListView时,LogCat的反馈应用信息如下: 创建太多的条目,占用运行资源。但是,如果有1万条条目时,不可能去全部加载出来。故会添加一个判断,复用已经完全消失在屏幕的条目进行复用,只会产生屏幕显示的条目个数+1(头一个没有完成消失,新暴露出来的已经加载,固此处要+1),代码如下: public View getView(int position, View convertView, ViewGroup parent) { Log.i("TAG", "$$$$$$$$$$$$创建的条目个数为:" + position); View view = null; if (convertView != null) { view = convertView; } else { LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = layoutInflater.inflate(R.layout.item_news_layout, null); } // 获取子控件的对象 ImageView item_img_icon = (ImageView) view.findViewById(R.id.item_img_icon); TextView item_tv_des = (TextView) view.findViewById(R.id.item_tv_des); TextView item_tv_title = (TextView) view.findViewById(R.id.item_tv_title); // 获取postion位置的对应list集合中的新闻数据 NewsBean newsBean = list.get(position); // 设置标题 item_tv_title.setText(newsBean.title); // 设置内容 item_tv_des.setText(newsBean.des); item_img_icon.setImageDrawable(newsBean.icon); return view; } } 这样会把复用view=converView。 BaseAdapter的四个方法实现: 适配器的使用必须要实现4个方法,现在分别介绍4个方法的代表含义: public int getCount() { return list == null ? 0 : list.size(); } 有多少个项目放在适配器的数据中。返回一个int类型的数,此处返回一个数字的个数,但要用三目算法判断下数字是否为空。必须要判断下。 public Object getItem(int position) { return list.get(position); } 得到相关的数据项的指定位置的数据集,一般指对象数组的元素内容。返回一个Obj类型,此次数组存放的为对象 public long getItemId(int position) { return position; } 得到相关的行id列表中指定的位置 指item的id 返回一个long型 public View getView(int position, View convertView, ViewGroup parent) { //得到一个视图显示数据集的数据在指定的位置。你可以手动创建一个视图或指定XML布局文件。 返回一个View布局的展示,这里要设置引入布局的各项参数 View view = null; if (convertView != null) { view = convertView; //复用convertView } else { LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = layoutInflater.inflate(R.layout.item_news_layout, null); //引用自己设定的xml布局格式 } // 获取子控件的对象 ImageView item_img_icon = (ImageView) view.findViewById(R.id.item_img_icon); //拿到图片 TextView item_tv_des = (TextView) view.findViewById(R.id.item_tv_des); //拿到新闻内容 TextView item_tv_title = (TextView) view.findViewById(R.id.item_tv_title); //拿到新闻题目 // 获取postion位置的对应list集合中的新闻数据 NewsBean newsBean = list.get(position); // 设置标题 item_tv_title.setText(newsBean.title); // 设置内容 item_tv_des.setText(newsBean.des); // 设置图片 item_img_icon.setImageDrawable(newsBean.icon); //显示当前条目内容 return view; } 4个方法是关键,大部分是固定格式。 创建适配器和条目的点击监控: 先看主方法的代码: package com.itheima.news_listview; import java.util.ArrayList; import com.itheima.news_listview.adapter.NewsAdapter; import com.itheima.news_listview.bean.NewsBean; import com.itheima.news_listview.utils.NewsUtils; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; public class MainActivity extends Activity implements OnItemClickListener { private Context mContext; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mContext = this; //找到控件 ListView lv_news = (ListView) findViewById(R.id.lv_news); ArrayList allNews = NewsUtils.getAllNews(mContext); //创建适配器adapter,把当前上下文和新闻资源传递 NewsAdapter newsAdapter = new NewsAdapter(mContext, allNews); lv_news.setAdapter(newsAdapter); // 设置条目的点击事件 lv_news.setOnItemClickListener(this); } @Override public void onItemClick(AdapterView parent, View view, int position, long id) { NewsBean bean = (NewsBean) parent.getItemAtPosition(position); String url = bean.news_url; Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); startActivity(intent); } } 监控方法中有监控条目的方法,直接使用就行: public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 点击后需要执行的操作 } 滚动条的用法和属性: 当文字很多时View的高度不能超过一个固定的值,无法满足需求,因为ScrollView没有maxHeight,所以要了解其用法。 虽然Textview里面有方法可以实现该功能。如下: <TextView android:id="@+id/text_view" android:layout_width="fill_parent" android:layout_height="wrap_content" android:singleLine="false" android:maxLines="10" android:scrollbars="vertical"/> 但还有在java中设定: TextView textView = (TextView)findViewById(R.id.text_view); textView.setMovementMethod(ScrollingMovementMethod.getInstance()); 上述方法需要在两个部分设定,过于麻烦,现在可以直接用ScrollView来实现滚动:代码如下: <ScrollView android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/tv_source"/> </ScrollView>
