Android进阶之ListView与BaseAdapter的使用

Android进阶之ListView与BaseAdapter的使用

效果图

布局

activity_my_adapter.xml里的my_listview.xml

   
   
   
   
  1.        android:layout_width="match_parent"
  2.        android:layout_height="wrap_content"
  3.        android:id="@+id/listview"
  4.        />


listview_item.xml

   
   
   
   
  1. xml version="1.0" encoding="utf-8"?>
  2. xmlns:android="http://schemas.android.com/apk/res/android"
  3.                android:layout_width="match_parent"
  4.                android:layout_height="match_parent"
  5.                android:padding="16dp"
  6.    >
  7.    
  8.        android:layout_width="48dp"
  9.        android:layout_height="48dp"
  10.        android:id="@+id/photo_ib"
  11.        android:layout_alignParentLeft="true"
  12.        />
  13.    
  14.        android:layout_width="wrap_content"
  15.        android:layout_height="24dp"
  16.        android:gravity="center"
  17.        android:id="@+id/username_tv"
  18.        android:layout_toRightOf="@id/photo_ib"
  19.        android:text="@string/app_name"
  20.        android:paddingLeft="8dp"
  21.        android:paddingRight="8dp"
  22.        android:textSize="12sp"
  23.        />
  24.    
  25.        android:layout_width="24dp"
  26.        android:layout_height="24dp"
  27.        android:id="@+id/vip_ib"
  28.        android:layout_toRightOf="@id/username_tv"
  29.        />
  30.    
  31.        android:layout_width="24dp"
  32.        android:layout_height="24dp"
  33.        android:id="@+id/pop_menu_ib"
  34.        android:layout_alignParentRight="true"
  35.        />
  36.    
  37.        android:layout_width="wrap_content"
  38.        android:layout_height="16dp"
  39.        android:gravity="center"
  40.        android:id="@+id/month_tv"
  41.        android:layout_below="@id/username_tv"
  42.        android:layout_toRightOf="@id/photo_ib"
  43.        android:text="1-1"
  44.        android:textSize="12sp"
  45.        android:paddingLeft="8dp"
  46.        android:paddingRight="8dp"
  47.        />
  48.    
  49.        android:layout_width="wrap_content"
  50.        android:layout_height="16dp"
  51.        android:gravity="center"
  52.        android:id="@+id/comefrom_tv"
  53.        android:layout_below="@id/username_tv"
  54.        android:layout_toRightOf="@id/month_tv"
  55.        android:text="来自 "
  56.        android:textSize="12sp"
  57.        android:paddingRight="4dp"
  58.        />
  59.    
  60.        android:layout_width="match_parent"
  61.        android:layout_height="wrap_content"
  62.        android:id="@+id/content_tv"
  63.        android:text="@string/content"
  64.        android:paddingTop="8dp"
  65.        android:paddingBottom="8dp"
  66.        android:textSize="16sp"
  67.        android:layout_below="@id/photo_ib"
  68.        />
  69.    
  70.        android:layout_width="match_parent"
  71.        android:layout_height="wrap_content"
  72.        android:id="@+id/ll"
  73.        android:paddingTop="8dp"
  74.        android:paddingBottom="8dp"
  75.        android:orientation="horizontal"
  76.        android:layout_below="@id/content_tv"
  77.        >
  78.        
  79.            android:layout_width="0dp"
  80.            android:layout_height="wrap_content"
  81.            android:layout_weight="1"
  82.            android:id="@+id/forward_tv"
  83.            android:gravity="center"
  84.            android:textSize="10sp"
  85.            android:text="1"
  86.            />
  87.        
  88.            android:layout_width="0dp"
  89.            android:layout_height="wrap_content"
  90.            android:layout_weight="1"
  91.            android:id="@+id/common_tv"
  92.            android:gravity="center"
  93.            android:textSize="10sp"
  94.            android:text="评论"
  95.            />
  96.        
  97.            android:layout_width="0dp"
  98.            android:layout_height="wrap_content"
  99.            android:layout_weight="1"
  100.            android:id="@+id/praise_tv"
  101.            android:gravity="center"
  102.            android:textSize="10sp"
  103.            android:text="赞"
  104.            />
  105.    

strings.xml  

   
   
   
   
  1.   name="content">少的可怜发上来的积分来的是来的是更厉害萨拉合法的三国的塞给了受到法律的塞给了返回搞,士大夫的森林里商大会搞

  2. 加载中...


Model

User.java

   
   
   
   
  1. public class User {
  2. private int mPhoto;
  3. private int mVip;
  4. private int mPopMenu;
  5. private int mContent;
  6. private String mUsername;
  7. private String mMonth;
  8. private String mComefrom;
  9. public int getPhoto() {
  10. return mPhoto;
  11. }
  12. public void setPhoto(int photo) {
  13. mPhoto = photo;
  14. }
  15. public int getVip() {
  16. return mVip;
  17. }
  18. public void setVip(int vip) {
  19. mVip = vip;
  20. }
  21. public int getPopMenu() {
  22. return mPopMenu;
  23. }
  24. public void setPopMenu(int popMenu) {
  25. mPopMenu = popMenu;
  26. }
  27. public String getUsername() {
  28. return mUsername;
  29. }
  30. public void setUsername(String username) {
  31. mUsername = username;
  32. }
  33. public String getMonth() {
  34. return mMonth;
  35. }
  36. public void setMonth(String month) {
  37. mMonth = month;
  38. }
  39. public String getComefrom() {
  40. return mComefrom;
  41. }
  42. public void setComefrom(String comefrom) {
  43. mComefrom = comefrom;
  44. }
  45. public int getContent() {
  46. return mContent;
  47. }
  48. public void setContent(int content) {
  49. mContent = content;
  50. }
  51. }

Activity

MyAdapterActivity.java

   
   
   
   
  1. public class MyAdapterActivity extends AppCompatActivity implements AbsListView.OnScrollListener {
  2. private static final String TAG = "MyAdapterActivity";
  3. private ListView mListView;
  4. private TextView mLoadingTxt;
  5. private MyAdapter mMyAdapter;
  6.    private List<User> mDatas;
  7. private int mLastVisibleIndex ;  // 列表最后可见的项的索引
  8. private int mModCount;  // 记录getDatas调用的次数
  9. private SimpleDateFormat mDateFormat;
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.activity_my_adapter);
  14. mLoadingTxt = new TextView(this);
  15.    mLoadingTxt.setText(R.string.loading_text);
  16.    mLoadingTxt.setGravity(Gravity.CENTER);
  17.    mLoadingTxt.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));  // 字体加粗
  18. // 初始化日期格式
  19. mDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
  20.    // 初始化listview
  21.    mListView = (ListView) findViewById(R.id.listview);
  22.    // 实例化LinkedList
  23.    mDatas = new LinkedList<>();
  24. mMyAdapter = new MyAdapter(this, getDatas(mDatas));// 自定义adapter
  25. mListView.addFooterView(mLoadingTxt);
  26. mListView.setAdapter(mMyAdapter);
  27. mListView.removeFooterView(mLoadingTxt);
  28. }
  29. private List<User> getDatas(List<User> datas) {
  30. int i;
  31. // start i = 1 11 21 31 41
  32. // end   i = 10 20 30 40 50
  33. if (mModCount == 0) {
  34. i = 1;
  35. } else {
  36. i = mModCount * 10 + 1;
  37. }
  38. for (;i <= mModCount *10+10; i++) {
  39. User user = new User();
  40. user.setPhoto(R.mipmap.ic_launcher);
  41. user.setUsername("等风的草" + i + "号");
  42. user.setVip(R.drawable.vip);
  43. user.setPopMenu(R.drawable.pop_pic);
  44. user.setMonth(mDateFormat.format(new Date()));
  45. user.setComefrom("微博weibo" + i);
  46. user.setContent(R.string.content);
  47. datas.add(user);
  48. }
  49. mModCount++;
  50. return datas;
  51. }
  52. }

在getDatas方法中使用model来封装数据.


Adapter

MyAdapter.java

   
   
   
   
  1. public class MyAdapter extends BaseAdapter {
  2. private Context mContext;
  3. private List<User> mDatas;
  4. public MyAdapter(Context context, List<User> datas) {
  5. mContext = context;
  6. mDatas = datas;
  7. }
  8. @Override
  9. public int getCount() {
  10. return mDatas.size();
  11. }
  12. @Override
  13. public Object getItem(int position) {
  14. return mDatas.get(position);
  15. }
  16. @Override
  17. public long getItemId(int position) {
  18. return position;
  19. }
  20. @Override
  21. public View getView(int position, View convertView, ViewGroup parent) {
  22. /*
  23. 通过convertview的setTag方法和getTag方法来将我们要显示的数据来绑定在convertview 上。
  24. 如果convertview 是第一次展示,就创建新的Holder对象与之绑定,并在最后通过return convertview 返回来显示新数据;
  25. 如果convertview 是回收来的那么就不必创建新的holder对象,只需要把原来的绑定的holder取出加上新的数据就行了。
  26. */
  27. View v = convertView;
  28. ViewHolder viewHolder;
  29. if (v == null) {
  30. v = LayoutInflater.from(mContext).inflate(R.layout.listview_item, parent, false);
  31. viewHolder = new ViewHolder();
  32. viewHolder.photo = (ImageButton) v.findViewById(R.id.photo_ib);
  33. viewHolder.username = (TextView) v.findViewById(R.id.username_tv);
  34. viewHolder.vip = (ImageButton) v.findViewById(R.id.vip_ib);
  35. viewHolder.popmenu = (ImageButton) v.findViewById(R.id.pop_menu_ib);
  36. viewHolder.month = (TextView) v.findViewById(R.id.month_tv);
  37. viewHolder.comefrom = (TextView) v.findViewById(R.id.comefrom_tv);
  38. viewHolder.content = (TextView) v.findViewById(R.id.content_tv);
  39. v.setTag(viewHolder);
  40. } else {
  41. viewHolder = (ViewHolder) v.getTag();
  42. }
  43. User user = (User) getItem(position);
  44. viewHolder.photo.setImageResource(user.getPhoto());
  45. viewHolder.vip.setImageResource(user.getVip());
  46. viewHolder.popmenu.setImageResource(user.getPopMenu());
  47. viewHolder.username.setText(user.getUsername());
  48. viewHolder.month.setText(user.getMonth());
  49. viewHolder.comefrom.setText(user.getComefrom());
  50. viewHolder.content.setText(user.getContent());
  51. return v;
  52. }
  53. /**
  54. * 静态内部类,只实例化一次
  55. */
  56. static class ViewHolder {
  57. ImageButton photo;
  58. TextView username;
  59. ImageButton vip;
  60. ImageButton popmenu;
  61. TextView month;
  62. TextView comefrom;
  63. TextView content;
  64. }
  65. }

该类使用一个ViewHolder静态内部类来优化listview的显示.


实现模拟网络数据自动加载

在onCreate方法中添加,设置监听listview滚动状态

   
   
   
   
  1. mListView.setOnScrollListener(this);

实现bsListView.OnScrollListener接口的两个方法

   
   
   
   
  1. @Override
  2. public void onScrollStateChanged(AbsListView view, int scrollState) {
  3. // 当当前可见索引是列表最后一个并且不滚动时,加载数据
  4. if (mLastVisibleIndex == mMyAdapter.getCount() - 1 && scrollState == SCROLL_STATE_IDLE) {
  5. mListView.addFooterView(mLoadingTxt); // 添加页脚(放在ListView最后)
  6. // simple adapter实现分页加载
  7. // 另起一个线程加载
  8. new Thread(new Runnable() {
  9. @Override
  10. public void run() {
  11. try {
  12. Thread.sleep(2000);
  13. getDatas(mDatas);
  14. runOnUiThread(new Runnable() {
  15. @Override
  16. public void run() {
  17. mMyAdapter.notifyDataSetChanged();
  18. if (mListView.getFooterViewsCount() > 0)
  19. mListView.removeFooterView(mLoadingTxt);   // 加载完数据后移除页脚
  20. }
  21. });
  22. Log.d(TAG, "onScrollStateChanged: 模拟网络数据加载。。。");
  23. } catch (InterruptedException e) {
  24. e.printStackTrace();
  25. }
  26. }
  27. }).start();
  28. }
  29. }
  30. @Override
  31. public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
  32. mLastVisibleIndex = firstVisibleItem + visibleItemCount - 1;
  33. }


最后贴上activity的完整清单

   
   
   
   
  1. public class MyAdapterActivity extends AppCompatActivity implements AbsListView.OnScrollListener {
  2. private static final String TAG = "MyAdapterActivity";
  3. private ListView mListView;
  4. private TextView mLoadingTxt;
  5. private MyAdapter mMyAdapter;
  6.    private List<User> mDatas;
  7. private int mLastVisibleIndex ;  // 列表最后可见的项的索引
  8. private int mModCount;  // 记录getDatas调用的次数
  9. private SimpleDateFormat mDateFormat;
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.activity_my_adapter);
  14. mLoadingTxt = new TextView(this);
  15.    mLoadingTxt.setText(R.string.loading_text);
  16.    mLoadingTxt.setGravity(Gravity.CENTER);
  17.    mLoadingTxt.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));  // 字体加粗
  18. // 初始化日期格式
  19. mDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
  20.    // 初始化listview
  21.    mListView = (ListView) findViewById(R.id.listview);
  22.    // 实例化LinkedList
  23.    mDatas = new LinkedList<>();
  24. mMyAdapter = new MyAdapter(this, getDatas(mDatas));
  25. mListView.addFooterView(mLoadingTxt);
  26. mListView.setAdapter(mMyAdapter);
  27. mListView.removeFooterView(mLoadingTxt);
  28. mListView.setOnScrollListener(this);
  29. }
  30. private List<User> getDatas(List<User> datas) {
  31. int i;
  32. // start i = 1 11 21 31 41
  33. // end   i = 10 20 30 40 50
  34. if (mModCount == 0) {
  35. i = 1;
  36. } else {
  37. i = mModCount * 10 + 1;
  38. }
  39. for (;i <= mModCount *10+10; i++) {
  40. User user = new User();
  41. user.setPhoto(R.mipmap.ic_launcher);
  42. user.setUsername("等风的草" + i + "号");
  43. user.setVip(R.drawable.vip);
  44. user.setPopMenu(R.drawable.pop_pic);
  45. user.setMonth(mDateFormat.format(new Date()));
  46. user.setComefrom("微博weibo" + i);
  47. user.setContent(R.string.content);
  48. datas.add(user);
  49. }
  50. mModCount++;
  51. return datas;
  52. }
  53. @Override
  54. public void onScrollStateChanged(AbsListView view, int scrollState) {
  55. // 当当前可见索引是列表最后一个并且不滚动时,加载数据
  56. if (mLastVisibleIndex == mMyAdapter.getCount() - 1 && scrollState == SCROLL_STATE_IDLE) {
  57. mListView.addFooterView(mLoadingTxt); // 添加页脚(放在ListView最后)
  58. // simple adapter实现分页加载
  59. // 另起一个线程加载
  60. new Thread(new Runnable() {
  61. @Override
  62. public void run() {
  63. try {
  64. Thread.sleep(2000);
  65. getDatas(mDatas);
  66. runOnUiThread(new Runnable() {
  67. @Override
  68. public void run() {
  69. mMyAdapter.notifyDataSetChanged();
  70. if (mListView.getFooterViewsCount() > 0)
  71. mListView.removeFooterView(mLoadingTxt);   // 加载完数据后移除页脚
  72. }
  73. });
  74. Log.d(TAG, "onScrollStateChanged: 模拟网络数据加载。。。");
  75. } catch (InterruptedException e) {
  76. e.printStackTrace();
  77. }
  78. }
  79. }).start();
  80. }
  81. }
  82. @Override
  83. public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
  84. mLastVisibleIndex = firstVisibleItem + visibleItemCount - 1;
  85. }
  86. }


如有疑问请指出交流,谢谢!


你可能感兴趣的:(Android进阶)