Android UI组件----自定义ListView实现动态刷新

简介:

【正文】

一、具体步骤:

(1)在activiy_main.xml中加一个ListView控件;再添加一个item的模板activity_main_item.xml,加一个底部加载的视图activity_main_load.xml;

(2)初始化item中的数据;

(3)自定义适配器BaseAdapter;

(4)ListiView绑定监听器OnScrollListener,并实现该监听器的两个方法:

    • public void onScrollStateChanged(AbsListView view, int scrollState)
    • public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount)

      注:如果屏幕滑到最下面了,并且scrollState的状态为:滚动完毕之后ListView处于停止状态(手离开屏幕),此时可以加载新数据了

(5)通过额外的线程,来模拟加载新数据;

(6)新数据加载完成后,通过handle通知主线程,将这个新数据显示在UI界面上(因为涉及到线程安全问题),此时要调用notifyDataSetChanged()方法来刷新。

       注:handler为线程之间通信的桥梁

 

二、代码实现: 

完整版代码如下:

activiy_main.xml代码如下:

复制代码
 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     tools:context=".MainActivity" >
 6     <ListView
 7         android:id="@+id/listView1"
 8         android:layout_width="match_parent"
 9         android:layout_height="match_parent" >
10     </ListView>
11 </LinearLayout>
复制代码

注:为优化起见,第9行的代码一定要写成"match_parent",而不是“wrap_content”(解释略)

 

activity_main_item.xml代码如下:(作为一个item的模板)

复制代码
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical" >
 6     <TextView
 7     android:id="@+id/textView1_title"
 8     android:layout_width="match_parent"
 9     android:layout_height="wrap_content"
10     android:text="Large Text"
11     android:textAppearance="?android:attr/textAppearanceLarge" />
12     <TextView
13         android:id="@+id/textView2_content"
14         android:layout_width="match_parent"
15         android:layout_height="wrap_content"
16         android:text="TextView" />
17 </LinearLayout>
复制代码

 

activity_main_load.xml代码如下:(作为加载时底部的显示)

复制代码
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="wrap_content"
 5     android:orientation="horizontal"
 6     android:gravity="center" >
 7 
 8     <ProgressBar
 9         android:id="@+id/progressBar1"
10         android:layout_width="25dp"
11         android:layout_height="25dp" />
12 
13     <TextView
14         android:id="@+id/textView1"
15         android:layout_width="wrap_content"
16         android:layout_height="wrap_content"
17         android:text="正在加载···" />
18 
19 </LinearLayout>
复制代码

 

MainActivity.java代码如下:

复制代码
  1 package com.smyhvae.smyh005listview5;
  2 
  3 import java.util.Vector;
  4 
  5 import android.app.Activity;
  6 import android.os.Bundle;
  7 import android.os.Handler;
  8 import android.os.Message;
  9 import android.view.Menu;
 10 import android.view.View;
 11 import android.view.ViewGroup;
 12 import android.widget.AbsListView;
 13 import android.widget.AbsListView.OnScrollListener;
 14 import android.widget.BaseAdapter;
 15 import android.widget.ListView;
 16 import android.widget.TextView;
 17 
 18 public class MainActivity extends Activity {
 19 
 20     private ListView listView;
 21     Vector<News> news = new Vector<News>();
 22     //private ArrayList<News> news = new ArrayList<News>();上面一行与这一行,二选一
 23     MyAdapter myAdapter;
 24     
 25     @Override
 26     protected void onCreate(Bundle savedInstanceState) {
 27         super.onCreate(savedInstanceState);
 28         setContentView(R.layout.activity_main);
 29         listView = (ListView)findViewById(R.id.listView1);
 30         
 31         listView.setOnScrollListener(new ListViewListener());  //绑定监听器
 32         
 33         //设置底部视图
 34         View footer = getLayoutInflater().inflate(R.layout.activity_main_load, null);
 35         listView.addFooterView(footer);        
 36         
 37 //        initData();
 38         new LoadDataThread().start();//加载数据的工作线程
 39             
 40         myAdapter = new MyAdapter();
 41         listView.setAdapter(myAdapter);
 42     }
 43 
 44    //定义一个数据的类
 45     class News {
 46         String title;
 47         String content;
 48     }
 49     
 50     int index = 1;//数据的记数器(索引)
 51     //初始化数据
 52     void initData(){        
 53         System.out.println("initData");
 54         for (int i = 0; i < 15; i++) {
 55             News n = new News();  //这句话一定要放在循环的里面,否则每个item显示的内容都是一样的
 56             n.title = "title-"+index;
 57             n.content = "content"+index;
 58             index++;
 59             news.add(n);  //这一步很关键,我就是少了这一步,导致运行时,界面为空
 60         }
 61     }
 62     
 63     
 64     
 65     //自定义适配器
 66     class MyAdapter extends BaseAdapter{
 67 
 68         @Override
 69         public int getCount() {
 70             // TODO Auto-generated method stub
 71             return news.size();
 72         }
 73         public Object getItem(int position) {
 74             return news.get(position);
 75         }
 76 
 77         @Override
 78         public long getItemId(int position) {
 79             return position;
 80         }
 81 
 82         @Override
 83         public View getView(int position, View convertView, ViewGroup parent) {
 84             ViewHolder viewHolder = new ViewHolder();
 85             //通过下面的条件判断语句,来循环利用。如果convertView = null ,表示屏幕上没有可以被重复利用的对象。
 86             if(convertView==null){
 87                 //创建View
 88                 convertView = getLayoutInflater().inflate(R.layout.activity_main_item, null);
 89                 viewHolder.tvTitle = (TextView) convertView.findViewById(R.id.textView1_title);
 90                 viewHolder.tvContent = (TextView) convertView.findViewById(R.id.textView2_content);
 91                 convertView.setTag(viewHolder);
 92             }else{
 93                 viewHolder = (ViewHolder)convertView.getTag();
 94             }
 95             //从Vector中取出数据填充到ListView列表项中
 96             News n = news.get(position);
 97             viewHolder.tvTitle.setText(n.title);
 98             viewHolder.tvContent.setText(n.content);
 99             return convertView;
100         }
101         
102     }
103 
104     static class ViewHolder{
105         TextView tvTitle;
106         TextView tvContent;
107     }    
108 
109     
110 
111     
112     //实现ListView的监听器的接口
113     int visibleLastIndex = 0; //最后一个显示的索引    
114     public class ListViewListener implements OnScrollListener{        
115         @Override
116         public void onScrollStateChanged(AbsListView view, int scrollState) {
117             //如果屏幕滑到最下面了,并且scrollState的状态为:滚动完毕之后ListView处于停止状态(手离开屏幕),
118             if(visibleLastIndex==myAdapter.getCount() && scrollState==OnScrollListener.SCROLL_STATE_IDLE){
119                 new LoadDataThread().start();//如果满足上面的条件,此时,可以加载新数据了
120             }
121         }
122 
123         @Override
124         public void onScroll(AbsListView view, int firstVisibleItem,
125             int visibleItemCount, int totalItemCount) {
126             visibleLastIndex = firstVisibleItem+visibleItemCount-1;
127             
128         }
129         
130     }
131     
132     //额外开启一个线程,模拟加载数据
133     class LoadDataThread extends Thread{
134         @Override
135         public void run() {
136             initData();
137             try {
138                 Thread.sleep(2000);//休眠两秒
139             } catch (InterruptedException e) {
140                 // TODO Auto-generated catch block
141                 e.printStackTrace();
142             }
143             
144             //新数据加载完成后,通过handle通知主线程,将这个新数据显示在UI界面上(因为涉及到线程安全问题)
145             handler.sendEmptyMessage(1);
146         }
147     }      
148     
149     //handler为线程之间通信的桥梁    
150     private Handler handler = new Handler(){
151         public void handleMessage(Message msg) {
152             switch(msg.what){
153             case 1:  //根据上面的提示,当Message为1,表示数据处理完了,可以通知主线程了
154                  myAdapter.notifyDataSetChanged();        //这个方法一旦调用,UI界面就刷新了
155                 break;
156                 
157             default :
158                 break;
159             }
160         }
161         
162     };
163     
164     
165     @Override
166     public boolean onCreateOptionsMenu(Menu menu) {
167         // Inflate the menu; this adds items to the action bar if it is present.
168         getMenuInflater().inflate(R.menu.main, menu);
169         return true;
170     }
171 
172 
173     
174 }
复制代码

运行后,显示结果如下:

下图依次为:刚运行时、滑动到底部时、刷新之后的效果

 

三、总结:

  • 监听事件处理的接口:OnScrollListener
  • Adapter的刷新方法:notifyDataSetChanged()

 

相关文章
|
24天前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
19天前
|
前端开发 搜索推荐 开发者
「Mac畅玩鸿蒙与硬件20」鸿蒙UI组件篇10 - Canvas 组件自定义绘图
Canvas 组件在鸿蒙应用中用于绘制自定义图形,提供丰富的绘制功能和灵活的定制能力。通过 Canvas,可以创建矩形、圆形、路径、文本等基础图形,为鸿蒙应用增添个性化的视觉效果。本篇将介绍 Canvas 组件的基础操作,涵盖绘制矩形、圆形、路径和文本的实例。
58 12
「Mac畅玩鸿蒙与硬件20」鸿蒙UI组件篇10 - Canvas 组件自定义绘图
|
19天前
|
搜索推荐 前端开发 开发者
「Mac畅玩鸿蒙与硬件19」鸿蒙UI组件篇9 - 自定义动画实现
自定义动画让开发者可以设计更加个性化和复杂的动画效果,适合表现独特的界面元素。鸿蒙提供了丰富的工具,支持通过自定义路径和时间控制来创建复杂的动画运动。本篇将带你学习如何通过自定义动画实现更多样化的效果。
68 11
「Mac畅玩鸿蒙与硬件19」鸿蒙UI组件篇9 - 自定义动画实现
|
19天前
|
UED 开发者
「Mac畅玩鸿蒙与硬件18」鸿蒙UI组件篇8 - 高级动画效果与缓动控制
高级动画可以显著提升用户体验,为应用界面带来更流畅的视觉效果。本篇将深入介绍鸿蒙框架的高级动画,包括弹性动画、透明度渐变和旋转缩放组合动画等示例。
58 12
「Mac畅玩鸿蒙与硬件18」鸿蒙UI组件篇8 - 高级动画效果与缓动控制
|
15天前
|
UED
「Mac畅玩鸿蒙与硬件31」UI互动应用篇8 - 自定义评分星级组件
本篇将带你实现一个自定义评分星级组件,用户可以通过点击星星进行评分,并实时显示评分结果。为了让界面更具吸引力,我们还将添加一只小猫图片作为评分的背景装饰。
54 6
「Mac畅玩鸿蒙与硬件31」UI互动应用篇8 - 自定义评分星级组件
|
19天前
|
UED
「Mac畅玩鸿蒙与硬件17」鸿蒙UI组件篇7 - Animation 组件基础
在应用开发中,动画效果可以增强用户体验。鸿蒙框架提供了 translate、scale 和 rotate 等动画功能,允许对组件进行平移、缩放和旋转等操作。本篇将介绍 Animation 组件的基础知识和示例代码。
70 10
「Mac畅玩鸿蒙与硬件17」鸿蒙UI组件篇7 - Animation 组件基础
|
17天前
|
前端开发 开发者
「Mac畅玩鸿蒙与硬件21」鸿蒙UI组件篇11 - Canvas 组件的静态进阶应用
在鸿蒙应用开发中,Canvas 组件不仅用于基础绘图,还提供了处理复杂路径和渐变效果的多种手段,帮助开发者实现精美的静态图形。本篇将介绍如何在 Canvas 中绘制复杂路径、创建渐变填充效果。
43 7
「Mac畅玩鸿蒙与硬件21」鸿蒙UI组件篇11 - Canvas 组件的静态进阶应用
|
19天前
|
大数据 UED
「Mac畅玩鸿蒙与硬件16」鸿蒙UI组件篇6 - List 和 Grid 组件展示数据列表
List 和 Grid 是鸿蒙开发中的核心组件,用于展示动态数据。List 适合展示垂直或水平排列的数据列表,而 Grid 则适用于展示商品或图片的网格布局。本篇将展示如何封装组件,并通过按钮实现布局切换,提升界面的灵活性和用户体验。
56 9
「Mac畅玩鸿蒙与硬件16」鸿蒙UI组件篇6 - List 和 Grid 组件展示数据列表
|
17天前
|
前端开发 开发者
「Mac畅玩鸿蒙与硬件22」鸿蒙UI组件篇12 - Canvas 组件的动态进阶应用
在鸿蒙应用中,Canvas 组件可以实现丰富的动态效果,适合用于动画和实时更新的场景。本篇将介绍如何在 Canvas 中实现动画循环、动态进度条、旋转和缩放动画,以及性能优化策略。
41 6
「Mac畅玩鸿蒙与硬件22」鸿蒙UI组件篇12 - Canvas 组件的动态进阶应用
|
17天前
|
前端开发 开发者
「Mac畅玩鸿蒙与硬件23」鸿蒙UI组件篇13 - 自定义组件的创建与使用
自定义组件可以帮助开发者实现复用性强、逻辑清晰的界面模块。通过自定义组件,鸿蒙应用能够提高代码的可维护性,并简化复杂布局的构建。本篇将介绍如何创建自定义组件,如何向组件传递数据,以及如何在不同页面间复用这些组件。
33 5
「Mac畅玩鸿蒙与硬件23」鸿蒙UI组件篇13 - 自定义组件的创建与使用