- ScrollView:只能用于控件比较少的界面,如果数据有上千上万条,那么使用ScrollView就不好了,因为ScrollView就把所有的控件进行初始化,这是非常消耗性能的操作,所以android就设计了一个类ListView来专门处理列表数据条目的显示。
- ListView:处理条目比较多,并且每个条目都非常相似的场景。就是一个条目控件,会自动回收没有在屏幕上显示的控件,来优化性能。
对于ListView和BaseAdapter
1简单的用法
MainActivity.java
package com.example.listview;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity {
protected static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//找到ListView
ListView lv = (ListView) findViewById(R.id.lv);
//给ListView设置数据(设置适配器 基本适配器)
lv.setAdapter(new BaseAdapter() {
//加工ListView需要的条目 int position 条目的下标
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.i(TAG, "position:"+position);
TextView tv = new TextView(MainActivity.this);
tv.setText("人生自古谁没有年轻的时候"+position);
tv.setTextSize(20);
return tv;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public Object getItem(int position) {
return null;
}
//控制条目的数量
@Override
public int getCount() {
return 100;
}
});
}
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<ListView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</LinearLayout>
上图就是ListView控件的基本图像
2复杂ListView的用法
首先要创建一个ListView和一个条目上的内容
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" > <ListView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/lv">
</ListView> </RelativeLayout>
item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" > <ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
android:layout_centerVertical="true"
android:layout_marginRight="10dp"/> <TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/iv"
android:layout_marginTop="10dp"
android:textSize="22sp"
android:text="姓名"/>
<TextView
android:id="@+id/tv_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/iv"
android:layout_below="@id/tv_name"
android:textSize="16sp"
android:text="年龄"/> </RelativeLayout>
布局填充器layoutinflate:可以把res/layout下面的资源加载到内存,即可以把xml布局变成Java对象。一般就是加载item.xml上的东西
MainActivity.java
package com.example.listiview; import java.util.ArrayList;
import java.util.List; import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import cn.itcast.wh08.lv.domain.Teacher; public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); ListView lv = (ListView) findViewById(R.id.lv);
//模拟对象集合的数据 一般数据都是来自于网络,或者数据库
List<Teacher> data = new ArrayList<Teacher>();
for(int i = 0;i<100;i++){
data.add(new Teacher(i, "隔壁老王"+i, i+20));
}
//适配器
MyAdapter adapter = new MyAdapter(data, this);
//设置适配器
lv.setAdapter(adapter);
} //适配器
private class MyAdapter extends BaseAdapter{
private List<Teacher> data;
private Context context;
private LayoutInflater mInflater; public MyAdapter(List<Teacher> data, Context context) {
super();
this.data = data;
this.context = context;
//获取布局加载器
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
} @Override
public int getCount() {
return data.size();
} //返回条目指定位置的数据
@Override
public Object getItem(int position) {
return data.get(position);
} @Override
public long getItemId(int position) {
return 0;
} //加工条目
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//使用布局加载器加载布局
View view = mInflater.inflate(R.layout.item, null);
//找到条目对应的控件
TextView tv_name = (TextView) view.findViewById(R.id.tv_name);
TextView tv_age = (TextView) view.findViewById(R.id.tv_age);
//获取条目对应的数据
Teacher info = data.get(position);
//把数据绑定给控件
tv_name.setText(info.name);
tv_age.setText(info.age+"");
return view;
} } }
Teacher.java
package com.example.listview.vo; public class Teacher {
public int _id;
public String _name;
public int age; public Teacher(int _id, String _name, int age) {
super();
this._id = _id;
this._name = _name;
this.age = age;
} public Teacher() {
super();
} }
3.与数据库结合来显示
- mode 数据模型(数据) :要被显示到ListView上的数据集合
- view 视图(展示数据) : ListView
- controller控制层(把数据展示到空间上) : 适配器Adapter
我们还是要先建立ListView控件和item控件
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" > <TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingBottom="5dp"
android:paddingTop="5dp"
android:text="闺蜜列表"
android:textSize="22sp" /> <ListView
android:id="@+id/lv"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
- <LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" > <Button
android:id="@+id/bt_pre"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:enabled="false"
android:text="上一页" /> <Button
android:id="@+id/bt_next"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="下一页" />
</LinearLayout> </LinearLayout>
item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" > <ImageView
android:id="@+id/iv_head"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" /> <TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_toRightOf="@id/iv_head"
android:text="老师" /> <TextView
android:id="@+id/tv_phone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv_name"
android:layout_toRightOf="@id/iv_head"
android:text="13787009878" /> </RelativeLayout>
先建立一个数据库,为了得到数据。
MySqliteOpenHelper.java
package com.example.lisview.db; import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper; public class MySqliteOpenHelper extends SQLiteOpenHelper { private static SQLiteOpenHelper mInstance; public static synchronized SQLiteOpenHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new MySqliteOpenHelper(context, "itcast.db", null, 1);
}
return mInstance;
} public MySqliteOpenHelper(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
// TODO Auto-generated constructor stub
} @Override
public void onCreate(SQLiteDatabase db) {
// 设计一个表
db.execSQL("create table friends(_id integer primary key autoincrement,"
+ "name text," + "phone text)");
// 初始化表数据
ContentValues values = new ContentValues();
for (int i = 0; i < 100; i++) {
values.clear();
values.put("name", "老师" + i);
values.put("phone", "13787990" + i);
db.insert("friends", null, values);
}
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub } }
Friend.java
package com.example.lisview.vo; public class Friend {
public int _id;
public String name;
public String phone;
public Friend(int _id, String name, String phone) {
super();
this._id = _id;
this.name = name;
this.phone = phone;
}
public Friend() {
// TODO Auto-generated constructor stub
}
}
对数据库的增、删、查、改
FriendDao.java
package com.example.lisview.dao; import java.util.ArrayList;
import java.util.List; import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; import com.example.lisview.db.MySqliteOpenHelper;
import com.example.lisview.vo.Friend; public class FriendDao {
private Context context;
private SQLiteOpenHelper helper; public FriendDao(Context context) {
this.context = context;
helper = MySqliteOpenHelper.getInstance(context);
} /**
* 获取数据的总条目
* @return
*/
public int queryAllSize(){
int size = 0;
SQLiteDatabase db = helper.getReadableDatabase();
if(db.isOpen()){
Cursor cursor = db.query("friends", new String[]{"*"}, null, null, null, null, null);
size = cursor.getCount();//获取Cursor的大小
cursor.close();
db.close();
}
return size;
} /**
* 分页查询的
*
* @param startIndex
* 查询的开始下标
* @param block
* 每次查询的数据量
* @return
*/
public List<Friend> queryFriendsLimit(int startIndex, int block) {
List<Friend> infos = new ArrayList<Friend>();
SQLiteDatabase db = helper.getReadableDatabase();
if (db.isOpen()) {
Cursor cursor = db.query("friends", new String[] { "*" }, null,
null, null, null, null, startIndex + "," + block);
while (cursor.moveToNext()) {
int _id = cursor.getInt(0);
String name = cursor.getString(1);
String phone = cursor.getString(2);
infos.add(new Friend(_id, name, phone));
}
cursor.close();
db.close();
}
return infos;
}
}
MyAdapter.java
package com.example.lisview.service; import java.util.List; import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView; import com.example.lisview.R;
import com.example.lisview.vo.Friend; public class MyAdapter extends BaseAdapter {
private List<Friend> infos;
private LayoutInflater mInflater; public void setInfos(List<Friend> infos) {
this.infos = infos;
} public MyAdapter(List<Friend> infos, Context context) {
super();
this.infos = infos;
// 布局加载器
mInflater = LayoutInflater.from(context);
} // 返回条目的总数
@Override
public int getCount() {
return infos.size();
} // 得到item.xml代表的对象
@Override
public Object getItem(int position) {
return infos.get(position);
} // 得到Item的id,不过在这里貌似没有用
@Override
public long getItemId(int position) {
return position;
} // 得到Item的视图
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = mInflater.inflate(R.layout.item, null);
TextView tv_name = (TextView) view.findViewById(R.id.tv_name);
TextView tv_phone = (TextView) view.findViewById(R.id.tv_phone); Friend info = infos.get(position); tv_name.setText(info.name);
tv_phone.setText(info.phone);
return view;
} }
MainActivity.java
package com.example.lisview; import java.util.List; import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView; import com.example.lisview.dao.FriendDao;
import com.example.lisview.service.MyAdapter;
import com.example.lisview.vo.Friend; public class MainActivity extends Activity { private ListView lv;
private Button bt_pre;
private Button bt_next;
private FriendDao friendDao;
private int block = 10;// 每一页获取10条数据
private int startIndex = 0;// 获取数据的下标
private MyAdapter adapter;
private int size; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
} private void initView() {
lv = (ListView) findViewById(R.id.lv);
bt_pre = (Button) findViewById(R.id.bt_pre);
bt_next = (Button) findViewById(R.id.bt_next); MyOnClickListener l = new MyOnClickListener();
bt_pre.setOnClickListener(l);
bt_next.setOnClickListener(l); friendDao = new FriendDao(this);
size = friendDao.queryAllSize();
// 查询第一页数据
List<Friend> infos = friendDao.queryFriendsLimit(0, block);
adapter = new MyAdapter(infos, this);
lv.setAdapter(adapter);
// 设置条目点击事件
lv.setOnItemClickListener(new MyOnItemClickListener());
} private class MyOnItemClickListener implements OnItemClickListener { @Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
//获取条目的数据
final Friend info = (Friend) adapter.getItem(position);
//弹出对话框
new AlertDialog.Builder(MainActivity.this)
.setTitle(info.name)
.setMessage("请选择操作")
.setPositiveButton("打电话", new DialogInterface.OnClickListener() { @Override
public void onClick(DialogInterface dialog, int which) {
//打电话需要拨号权限
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:"+info.phone));
startActivity(intent);
}
})
.setNegativeButton("发短信", new DialogInterface.OnClickListener() { @Override
public void onClick(DialogInterface dialog, int which) {
//TODO:学员自己处理
}
})
.show();
} } private class MyOnClickListener implements OnClickListener { @Override
public void onClick(View v) {
List<Friend> infos = null;
switch (v.getId()) {
case R.id.bt_pre:
startIndex = startIndex - block;
if (startIndex == 0) {
bt_pre.setEnabled(false);
} else {
bt_pre.setEnabled(true);
}
bt_next.setEnabled(true);
infos = friendDao.queryFriendsLimit(startIndex, block);
adapter.setInfos(infos);// 把查询的数据设置给适配器
// 刷新界面
adapter.notifyDataSetChanged();
break; case R.id.bt_next:
startIndex = startIndex + block;
// 判断是否是最后页面的数据
// 现在页面的数据 startIndex=startIndex+block
if ((startIndex + block) >= size) {
// 已经是最后一页数据
bt_next.setEnabled(false);
} else {
bt_next.setEnabled(true);
}
bt_pre.setEnabled(true);
infos = friendDao.queryFriendsLimit(startIndex, block);
adapter.setInfos(infos);// 把查询的数据设置给适配器
// 刷新界面
adapter.notifyDataSetChanged();
break; default:
break;
}
} } }