扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
以下是我自己花功夫编写了一种非常简单的下拉刷新实现方案,现在拿出来和大家分享一下。相信在阅读完本篇文章之后,大家都可以在自己的项目中一分钟引入下拉刷新功能 最近项目中需要用到ListView下拉刷新的功能,一开始想图省事,在网上直接找一个现成的,可是尝试了网上多个版本的下拉刷新之后发现效果都不 怎么理想。有些是因为功能不完整或有Bug,有些是因为使用起来太复杂,十全十美的还真没找到。因此我也是放弃了在网上找现成代码的想法,自己花功夫编写 了一种非常简单的下拉刷新实现方案,现在拿出来和大家分享一下。相信在阅读完本篇文章之后,大家都可以在自己的项目中一分钟引入下拉刷新功能。首先讲一下实现原理。这里我们将采取的方案是使用组合View的方式,先自定义一个布局继承自LinearLayout,然后在这个布局中加入下拉 头和ListView这两个子元素,并让这两个子元素纵向排列。初始化的时候,让下拉头向上偏移出屏幕,这样我们看到的就只有ListView了。然后对 ListView的touch事件进行监听,如果当前ListView已经滚动到顶部并且手指还在向下拉的话,那就将下拉头显示出来,松手后进行刷新操 作,并将下拉头隐藏。原理示意图如下:那我们现在就来动手实现一下,新建一个项目起名叫PullToRefreshTest,先在项目中定义一个下拉头的布局文件pull_to_refresh/apk/res/android"xmlns:tools="schemas/tools"android:id="@+id/pull_to_refresh_head"android:layout_width="fill_parent"android:layout_height="60dip" LinearLayoutandroid:layout_width="200dip"android:layout_height="60dip"android:layout_centerInParent="true"android:orientation="horizontal" RelativeLayoutandroid:layout_width="0dip"android:layout_height="60dip"android:layout_weight="3"ImageView android:id="@+id/arrow"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:src="@drawable/arrow"/ProgressBar android:id="@+id/progress_bar"android:layout_width="30dip"android:layout_height="30dip"android:layout_centerInParent="true"android:visibility="gone"//RelativeLayoutLinearLayoutandroid:layout_width="0dip"android:layout_height="60dip"android:layout_weight="12"android:orientation="vertical" TextViewandroid:id="@+id/description"android:layout_width="fill_parent"android:layout_height="0dip"android:layout_weight="1"android:gravity="center_horizontalbottom"android:text="@string/pull_to_refresh" /TextViewandroid:id="@+id/updated_at"android:layout_width="fill_parent"android:layout_height="0dip"android:layout_weight="1"android:gravity="center_horizontaltop"android:text="@string/updated_at" //LinearLayout/LinearLayout/RelativeLayout 在这个布局中,我们包含了一个下拉指示箭头,一个下拉状态文字提示,和一个上次更新的时间。当然,还有一个隐藏的旋转进度条,只有正在刷新的时候我们才会将它显示出来。布局中所有引用的字符串我们都放在stringsmit();new HideHeaderTask()/apk/res/android"xmlns:tools="schemas/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity" com.example.pulltorefreshtest.RefreshableViewandroid:id="@+id/refreshable_view"android:layout_width="fill_parent"android:layout_height="fill_parent" ListViewandroid:id="@+id/list_view"android:layout_width="fill_parent"android:layout_height="fill_parent" /ListView/com.example.pulltorefreshtest.RefreshableView/RelativeLayout 可以看到,我们在自定义的RefreshableView中加入了一个ListView,这就意味着给这个ListView加入了下拉刷新的功能,就是这么简单!然后我们再来看一下程序的主Activity,打开或新建MainActivity,加入如下代码:复制代码 代码如下: public class MainActivity extends Activity {RefreshableView refreshableView;ListView listView;ArrayAdapterString adapter;String[] items = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L" };@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);refreshableView = (RefreshableView) findViewById(R.id.refreshable_view);listView = (ListView) findViewById(R.id.list_view);adapter = new ArrayAdapterString(this, android.R.layout.simple_list_item_1, items);listView.setAdapter(adapter);refreshableView.setOnRefreshListener(new PullToRefreshListener() {@Overridepublic void onRefresh() {try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}refreshableView.finishRefreshing();}}, 0);}} 可 以看到,我们通过调用RefreshableView的setOnRefreshListener方法注册了一个监听器,当ListView正在刷新时就 会回调监听器的onRefresh方法,刷新的具体逻辑就在这里处理。而且这个方法已经自动开启了线程,可以直接在onRefresh方法中进行耗时操 作,比如向服务器请求最新数据等,在这里我就简单让线程睡眠3秒钟。另外在onRefresh方法的最后,一定要调用RefreshableView中的 finishRefreshing方法,这个方法是用来通知RefreshableView刷新结束了,不然我们的ListView将一直处于正在刷新的 状态。不知道大家有没有注意到,setOnRefreshListener这个方法其实是有两个参数的,我们刚刚也是传入了一个不起眼的 0。那这第二个参数是用来做什么的呢?由于RefreshableView比较智能,它会自动帮我们记录上次刷新完成的时间,然后下拉的时候会在下拉头中 显示距上次刷新已过了多久。这是一个非常好用的功能,让我们不用再自己手动去记录和计算时间了,但是却存在一个问题。如果当前我们的项目中有三个地方都使 用到了下拉刷新的功能,现在在一处进行了刷新,其它两处的时间也都会跟着改变!因为刷新完成的时间是记录在配置文件中的,由于在一处刷新更改了配置文件, 导致在其它两处读取到的配置文件时间已经是更改过的了。那解决方案是什么?就是每个用到下拉刷新的地方,给setOnRefreshListener方法 的第二个参数中传入不同的id就行了。这样各处的上次刷新完成时间都是单独记录的,相互之间就不会再有影响。好了,全部的代码都在这里了,让我们来运行一下,看看效果吧。效果看起来还是非常不错的。我们最后再来总结一下,在项目中引入ListView下拉刷新功能只需三步:1. 在Activity的布局文件中加入自定义的RefreshableView,并让ListView包含在其中。2. 在Activity中调用RefreshableView的setOnRefreshListener方法注册回调接口。3. 在onRefresh方法的最后,记得调用RefreshableView的finishRefreshing方法,通知刷新结束。从此以后,在项目的任何地方,一分钟引入下拉刷新功能妥妥的。好了,今天的讲解到此结束,有疑问的朋友请在下面留言。源码下载,请点击这里
让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:主机域名、网络空间、营销软件、网站建设、营口网站维护、网站推广。
用自定义标题栏。
用自定义标题栏,只要把系统自带的标题栏去掉就行。做法:requestWindowFeature(Window.FEATURE_NO_TITLE),自己再写两个布局块(LinearLayout布局)充当顶部和底部的标题栏即可,中间使用ScrollView即可完成。
如果应用需要添加水平滚动条,则可借助于另一个滚动视图HorizontalScrollView来实现。
让gallery自动滚动可以通过以下两种方法实现:
一、使用Timer和TimerTask类来完成图片的自动定时滚动:
思路:循环调用Gallery类的onFling()方法。
代码:
span style="white-space:pre" /spantask = new TimerTask() {
@Override
public void run() {
/**
* 参数1和2:手指在gallery上的动作
* 参数3和4:x方向和y方向的滚动的速度,-数表示向左滚,+数表示向右
*/
gallery.onFling(null, null, -750, 0);
}
};
timer.schedule(task, 1000, 5000);
span style="font-size:32px;"strong
/strong/span
span style="font-size:32px;"strong方式2:/strong/span
二、使用Handler消息机制完成
思路:子线程内死循环使用handler每隔多长时间向主线程发送消息,通知gallery改变位置。
代码:
子线程部分:
span style="white-space:pre" new Thread(new Runnable() {
span style="white-space:pre" /spanint flag = 1;
span style="white-space:pre" /span@Override
span style="white-space:pre" /spanpublic void run() {
span style="white-space:pre" /spanwhile (isalive) {
span style="white-space:pre" /span//images为装图片的集合
span style="white-space:pre" /spanif ((cur_index + 1) == images.size()) {
span style="white-space:pre" /spanflag = -1;
span style="white-space:pre" /span} else if (cur_index == 0) {
span style="white-space:pre" /spanflag = 1;
span style="white-space:pre" /span}
span style="white-space:pre" /spanMessage msg = handler.obtainMessage(MSG_UPDATE, cur_index,
span style="white-space:pre" /span0);
span style="white-space:pre" /spanhandler.sendMessage(msg);
span style="white-space:pre" /spantry {
span style="white-space:pre" /spanThread.sleep(4000);
span style="white-space:pre" /span} catch (InterruptedException e) {
span style="white-space:pre" /spane.printStackTrace();
span style="white-space:pre" /span}
span style="white-space:pre" /spanswitch (flag) {
span style="white-space:pre" /spancase 1:
span style="white-space:pre" /spancur_index++;
span style="white-space:pre" /spanbreak;
span style="white-space:pre" /spancase -1:
span style="white-space:pre" /spancur_index--;
span style="white-space:pre" /spanbreak;
span style="white-space:pre" /span}
span style="white-space:pre" /span}
span style="white-space:pre" /span}
span style="white-space:pre" /span}).start();/span
主线程部分:
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == MSG_UPDATE) {
gallery.setSelection(msg.arg1);
}
}
};
两种方式的优缺点:
优点:
使用方式1来实现,效果和手指拖动的效果一样,滚动速度可以自己调。
使用方式2来实现,可以使用继承Gallery的子类,重写onFling方法,返回false来实现手指拖动时图片只滚动一张的效果。
缺点:
使用方式1来实现,当你用手指拖动,就会发现图片滚动的太快了,不是一张一张的滚动的,没法使用继承Gallery的子类,重写onFling方法,返回false来实现手
使用方式2来实现 ,效果没那么好看,图片说换就换了,没缓冲,滚动速度没法控制。
给TextView加上滚动条非常简单,只需要把TextView标签放在ScrollView标签中
[html] view plain copy print?
ScrollView android:layout_width="wrap_content" android:layout_height="wrap_content"
TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/txtViewHtml" /
/ScrollView
可以设置ListView的滚动事件
ListView.setOnScrollListener(OnScrollListener listener)
OnScrollListener是滚动事件监听接口
有两个需要实现的方法
public void onScrollStateChanged(AbsListView view, int scrollState) ;
public void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) ;
几个参数的意义分别为
AbsListView view所监听的listview对象
int firstVisibleItem能看见的第一个item的位置
int visibleItemCount能看见的item的数量
int totalItemCount所有item的总数
代码如下,我们在onScroll中进行判断
lvMatch.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if(firstVisibleItem == 0){
//已滚动到最顶部
}
if(firstVisibleItem+visibleItemCount == totalItemCount){
//滚动到底部
}
}
});
Android 的屏幕滚动操作不如 iPhone 流畅顺滑,两者的系统架构不同导致。
1.首先是iOS对屏幕反应的优先级是最高的(Touch-Media-Service-Core架构),也就是说用户只要碰了屏幕,系统最优先去处理屏幕显示,然后才是其他。而安卓则是传统的Application-Framework-Library(JAVA虚拟机)-Kernal架构,图形图像处理在Library这层,优先级不是那么高。如果系统负荷较高,则无暇顾及用户触摸的反应。
2.其次是iOS对图像的各种特效处理(放大、缩小、旋转、滚动等)都是基于GPU硬件加速的,与APP无关。这是APPLE采用封闭式硬件的优势。而安卓为了适应不同的手机硬件,做不到这点,很多APP的图形特效都靠APP自己去进行软件渲染,效率低。最新的4.1已经改进,但也无法做到所有特效都靠GPU硬件加速。
3.就是安卓的JAVA虚拟机:相对iOS的Objectiv-C,JAVA天生运行效率低下,需要占用大量内存来换取执行速度,而不定期的内存自动回收机制,直接导致安卓界面的卡顿现象,无论如何优化也不可能改掉。2.3版安卓就是为改善此设计而发布:引入了一种新的并行内存回收机制来减轻这种卡顿影响,但也仅仅是减轻,而无法彻底消除。也因此2.3版成为安卓重要的里程碑。
4.当然如果android程序软件在代码层面存在一些明显的bug,也会导致滑动卡顿,需要更新数据的时候进行合理的刷新。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流