参考文章:http://blog.csdn.net/to_be_designer/article/details/47983017
本文中的demo:
http://download.csdn.net/download/qq_31881469/10005187
http://www.imooc.com/learn/136
(1)回调:A类中调用B类的C方法,然后B类反过来调用A类的D方法,D为回调(就是接口中定义的抽象方法)
B类:自定义view(本例中:CustomListView)
(1)定义接口
(2)设置监听接口的方法
(3)调用接口的方法
本例CustomListView类中:
public interface ILoadMoreListener {
void loadMore();
}
public void setLoadMoreListener(ILoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (lastVisibleItem == totalItemCount && scrollState == SCROLL_STATE_IDLE) {//最后一个item并且停止滚动
if (isLoading) {//正在加载
isLoading = false;
footView.findViewById(R.id.footView).setVisibility(VISIBLE);
//加载更多
loadMoreListener.loadMore();
}
}
}
A类:activity
(1)实现接口
(2)重写接口的方法
(3)在onCreate()中调用监听接口的方法
public class MainActivity extends AppCompatActivity implements CustomListView.ILoadMoreListener{
@Override
public void loadMore() {
Handler handler=new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 20; i++) {
strList.add("测试加载更多" + (i + 1));
}
adapter.notifyDataSetChanged();
listView.loadComplete();
}
},2000);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (CustomListView) findViewById(R.id.listView);
strList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
strList.add("测试" + (i + 1));
}
adapter = new MyBaseAdapter(this, strList);
listView.setAdapter(adapter);
listView.setLoadMoreListener(this);
}
(2)适配器Adapter
Adapter是数据和UI(View)之间一个重要的纽带。在常见的View(ListView,GridView)等地方都需要用到Adapter。如下图直观的表达了Data、Adapter、View三者的关系:
activity中:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
strList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
strList.add("测试" + (i + 1));
}
listView = (CustomListView) findViewById(R.id.listView);
adapter = new MyBaseAdapter(this, strList);
listView.setAdapter(adapter);
listView.setLoadMoreListener(this);
}
自定义的adapter
public class MyBaseAdapter extends BaseAdapter {
private List<String> strList;
private Context context;
public MyBaseAdapter(Context context, List<String> strList) {
this.strList = strList;
this.context = context;
}
@Override
public int getCount() {
return strList.size();
}
@Override
public Object getItem(int position) {
return strList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = View.inflate(context, R.layout.item, null);
TextView textView = (TextView) view.findViewById(R.id.text);
textView.setText(strList.get(position));
return view;
}
}
(1)ArrayAdapter(Context context, int textViewResourceId, List<T> objects)来装配数据
public class MyListView extends Activity {
private ListView listView;
//private List<String> data = new ArrayList<String>();
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
listView = new ListView(this);
listView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1,getData()));
setContentView(listView);
}
private List<String> getData(){
List<String> data = new ArrayList<String>();
data.add("测试数据1");
data.add("测试数据2");
data.add("测试数据3");
data.add("测试数据4");
return data;
}
}
(2)SimpleAdapter
simpleAdapter的扩展性最好,可以定义各种各样的布局出来,可以放上ImageView(图片),还可以放上Button(按钮),CheckBox(复选框)等等。下面的代码都直接继承了ListActivity,ListActivity和普通的Activity没有太大的差别,不同就是对显示ListView做了许多优化,方面显示而已。
使用simpleAdapter的数据用一般都是HashMap构成的List,list的每一节对应ListView的每一行。
案例二
下面的程序是实现一个带有图片的类表。首先需要定义好一个用来显示每一个列内容的xml,vlist.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5px"/>
<LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content">
<TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textColor="#FFFFFFFF" android:textSize="22px" />
<TextView android:id="@+id/info" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textColor="#FFFFFFFF" android:textSize="13px" />
</LinearLayout>
</LinearLayout>
public class MyListView3 extends ListActivity {
// private List<String> data = new ArrayList<String>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SimpleAdapter adapter = new SimpleAdapter(this,getData(),R.layout.vlist,
new String[]{"title","info","img"},
new int[]{R.id.title,R.id.info,R.id.img});
setListAdapter(adapter);
}
private List<Map<String, Object>> getData() {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Map<String, Object> map = new HashMap<String, Object>();
map.put("title", "G1");
map.put("info", "google 1");
map.put("img", R.drawable.i1);
list.add(map);
map = new HashMap<String, Object>();
map.put("title", "G2");
map.put("info", "google 2");
map.put("img", R.drawable.i2);
list.add(map);
map = new HashMap<String, Object>();
map.put("title", "G3");
map.put("info", "google 3");
map.put("img", R.drawable.i3);
list.add(map);
return list;
}
}
(3)
BaseAdapter
有时候,列表不光会用来做显示用,我们同样可以在在上面添加按钮。添加按钮首先要写一个有按钮的xml文件,然后自然会想到用上面的方法定义一个适配器,然后将数据映射到布局文件上。但是事实并非这样,因为按钮是无法映射的,即使你成功的用布局文件显示出了按钮也无法添加按钮的响应,这时就要研究一下ListView是如何现实的了,而且必须要重写一个类继承BaseAdapter。下面的示例将显示一个按钮和一个图片,两行字如果单击按钮将删除此按钮的所在行。并告诉你ListView究竟是如何工作的。
vlist2.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5px"/>
<LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content">
<TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textColor="#FFFFFFFF" android:textSize="22px" />
<TextView android:id="@+id/info" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textColor="#FFFFFFFF" android:textSize="13px" />
</LinearLayout>
<Button android:id="@+id/view_btn" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="@string/s_view_btn" android:layout_gravity="bottom|right" />
</LinearLayout>
public class MyListView4 extends ListActivity {
006
007
008 private List<Map<String, Object>> mData;
009
010 @Override
011 public void onCreate(Bundle savedInstanceState) {
012 super.onCreate(savedInstanceState);
013 mData = getData();
014 MyAdapter adapter = new MyAdapter(this);
015 setListAdapter(adapter);
016 }
017
018 private List<Map<String, Object>> getData() {
019 List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
020
021 Map<String, Object> map = new HashMap<String, Object>();
022 map.put("title", "G1");
023 map.put("info", "google 1");
024 map.put("img", R.drawable.i1);
025 list.add(map);
026
027 map = new HashMap<String, Object>();
028 map.put("title", "G2");
029 map.put("info", "google 2");
030 map.put("img", R.drawable.i2);
031 list.add(map);
032
033 map = new HashMap<String, Object>();
034 map.put("title", "G3");
035 map.put("info", "google 3");
036 map.put("img", R.drawable.i3);
037 list.add(map);
038
039 return list;
040 }
041
042 // ListView 中某项被选中后的逻辑
043 @Override
044 protected void onListItemClick(ListView l, View v, int position, long id) {
045
046 Log.v("MyListView4-click", (String)mData.get(position).get("title"));
047 }
048
049 /**
050 * listview中点击按键弹出对话框
051 */
052 public void showInfo(){
053 new AlertDialog.Builder(this)
054 .setTitle("我的listview")
055 .setMessage("介绍...")
056 .setPositiveButton("确定", new DialogInterface.OnClickListener() {
057 @Override
058 public void onClick(DialogInterface dialog, int which) {
059 }
060 })
061 .show();
062
063 }
064
065
066
067 public final class ViewHolder{
068 public ImageView img;
069 public TextView title;
070 public TextView info;
071 public Button viewBtn;
072 }
073
074
075 public class MyAdapter extends BaseAdapter{
076
077 private LayoutInflater mInflater;
078
079
080 public MyAdapter(Context context){
081 this.mInflater = LayoutInflater.from(context);
082 }
083 @Override
084 public int getCount() {
085 // TODO Auto-generated method stub
086 return mData.size();
087 }
088
089 @Override
090 public Object getItem(int arg0) {
091 // TODO Auto-generated method stub
092 return null;
093 }
094
095 @Override
096 public long getItemId(int arg0) {
097 // TODO Auto-generated method stub
098 return 0;
099 }
100
101 @Override
102 public View getView(int position, View convertView, ViewGroup parent) {
103
104 ViewHolder holder = null;
105 if (convertView == null) {
106
107 holder=new ViewHolder();
108
109 convertView = mInflater.inflate(R.layout.vlist2, null);
110 holder.img = (ImageView)convertView.findViewById(R.id.img);
111 holder.title = (TextView)convertView.findViewById(R.id.title);
112 holder.info = (TextView)convertView.findViewById(R.id.info);
113 holder.viewBtn = (Button)convertView.findViewById(R.id.view_btn);
114 convertView.setTag(holder);
115
116 }else {
117
118 holder = (ViewHolder)convertView.getTag();
119 }
120
121
122 holder.img.setBackgroundResource((Integer)mData.get(position).get("img"));
123 holder.title.setText((String)mData.get(position).get("title"));
124 holder.info.setText((String)mData.get(position).get("info"));
125
126 holder.viewBtn.setOnClickListener(new View.OnClickListener() {
127
128 @Override
129 public void onClick(View v) {
130 showInfo();
131 }
132 });
133
134
135 return convertView;
136 }
137
138 }
139 }
(3)自定义listview,设置滑动监听接口,实现分页加载
public class CustomListView extends ListView implements AbsListView.OnScrollListener {
private View footView;
private Context context;
private int totalItemCount;//总的条目
private int lastVisibleItem;//最后可见的item
private boolean isLoading = true;//正在加载
private ILoadMoreListener loadMoreListener;
public void setLoadMoreListener(ILoadMoreListener loadMoreListener) {
this.loadMoreListener = loadMoreListener;
}
public CustomListView(Context context) {
this(context, null);
}
public CustomListView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
initView();
}
/**
* 加载底部布局
*/
private void initView() {
footView = View.inflate(context, R.layout.view_foot, null);
footView.findViewById(R.id.footView).setVisibility(View.GONE);
this.addFooterView(footView);
this.setOnScrollListener(this);
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (lastVisibleItem == totalItemCount && scrollState == SCROLL_STATE_IDLE) {//最后一个item并且停止滚动
if (isLoading) {//正在加载
isLoading = false;
footView.findViewById(R.id.footView).setVisibility(VISIBLE);
//加载更多
loadMoreListener.loadMore();
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
this.lastVisibleItem = firstVisibleItem + visibleItemCount;
this.totalItemCount = totalItemCount;
}
/**
* 加载完成
*/
public void loadComplete() {
isLoading = true;
footView.findViewById(R.id.footView).setVisibility(GONE);
}
public interface ILoadMoreListener {
void loadMore();
}
}
(4)xml布局
1---main_activity.xml-----在activty中setContentView(R.layout.activity_main);
其中添加了自定义listview的布局------也是在activity中获取布局listView = (CustomListView) findViewById(R.id.listView);
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<demo.com.customlistviewdemo.CustomListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
2----listview每行item布局-----在自定义 MyBaseAdapter extends BaseAdapter中获取
public View getView(int position, View convertView, ViewGroup parent) {
View view = View.inflate(context, R.layout.item, null);
<?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"
android:paddingBottom="10dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingTop="10dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" />
</RelativeLayout>
3----加载底部布局view_footer.xml,在自定义
CustomListView extends ListView implements AbsListView.OnScrollListener 中获取
private void initView() {
footView = View.inflate(context, R.layout.view_foot, null);
footView.findViewById(R.id.footView).setVisibility(View.GONE);
this.addFooterView(footView);
this.setOnScrollListener(this);
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/footView"
android:layout_width="match_parent"
android:layout_height="45dp"
android:gravity="center"
android:orientation="horizontal"
android:paddingBottom="5dp"
android:paddingTop="5dp">
<ProgressBar
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:paddingLeft="5dp"
android:text="正在加载数据..."
android:textSize="16sp" />
</LinearLayout>