Android之双击回到顶部
2016-06-24 10:26
417 查看
双击回到顶部在Android应用中用的很多,众所周知的微信消息列表,朋友圈都提供这样的效果,下面我将自己自项目中的实践记录下来,分享给大家
网上有很多的获取双击事件的方法,这里我讲它稍加封装,整个工程也可以使用
首先我们来定义双击事件的接口
[java] view
plain copy
package com.....activity.info;
import android.view.View;
/**
* @author wfy
* 单击双击事件接口
*/
public interface OnDoubleClickListener {
public void OnSingleClick(View v);
public void OnDoubleClick(View v);
}
下来定义一个DoubleClick类,它提供一个静态方法给一个view注册双击事件,注释我已经写的及其详细了,不再多说
[java] view
plain copy
package com.....activity.info;
import android.os.Handler;
import android.os.Message;
import android.view.View;
/**
* @author wfy
* 消息列表+好友动态的双击回到顶部
*/
public class DoubleClick {
public static void registerDoubleClickListener(View view, final OnDoubleClickListener listener){
if(listener==null) return;
view.setOnClickListener(new View.OnClickListener() {
//双击间隔时间350毫秒
private static final int DOUBLE_CLICK_TIME = 350;
private boolean flag = true;
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
listener.OnSingleClick((View)msg.obj);
}
};
//等待双击
public void onClick(final View v) {
if(flag){
flag = false;//与执行双击事件
new Thread(){
public void run() {
try {
Thread.sleep(DOUBLE_CLICK_TIME);
//此时线程沉睡 而flag被修改为false 在DOUBLE_CLICK_TIME内点击则 进入else
} catch (InterruptedException e) {
e.printStackTrace();
} //等待双击时间,否则执行单击事件
if(!flag){
//睡醒了看一看flag被人动过没,没有人动,则认作单击事件
//因此不建议用此方法执行单击事件 因为会等待睡醒,有点击延迟的存在
//没有人动,自己把它改成true,以接受下次点击
flag = true;
Message msg = handler.obtainMessage();
msg.obj = v;
//发个消息,让执行单击
handler.sendMessage(msg);
}
}
}.start();
}else{
flag = true;
listener.OnDoubleClick(v); //执行双击
}
}
});
}
}
[java] view
plain copy
Button button=new Button(this);
DoubleClick.registerDoubleClickListener(button, new OnDoubleClickListener() {
@Override
public void OnSingleClick(View v) {
// TODO Auto-generated method stub
}
@Override
public void OnDoubleClick(View v) {
// TODO Auto-generated method stub
GoTopTask task=new GoTopTask();
task.execute(firstposition);
}
});
[java] view
plain copy
private class GoTopTask extends AsyncTask<Integer, Integer, String>{
@Override
protected void onPreExecute() {
//回到顶部时间置0 此处的时间不是侠义上的时间
time=0;
super.onPreExecute();
}
@Override
protected String doInBackground(Integer... params) {
// TODO Auto-generated method stub
for(int i=params[0];i>=0;i--){
publishProgress(i);
//返回顶部时间耗费15个item还没回去,则直接去顶部
//目的:要产生滚动的假象,但也不能耗时过多
time++;
if(time>15){
publishProgress(0);
return null;
}
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
lv.setSelection(values[0]);
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
@Override
protected void onCancelled() {
// TODO Auto-generated method stub
super.onCancelled();
}
}
写到这里相信大家都明白思路了,就是用lv.setSelection(0)让list回到顶部,可是这里存在三个问题:1、直接闪回到顶部用户体验不是很好,很突兀 2、如1所说,那一个个往会显示,可是你有1000个item,我看到好几百个时,往回一个一个滚吗?相信没有人有那个耐心等 3、不能每次都从最后往会滚,从当前可见的第一个item滚,那么如何获取当前可见的第一个item?
对于第一个问题和第二个问题:我在异步任务里已经做了判断,先一个一个滚,滚到第十五个(也就是异步任务里的time)还没回去则直接回顶部,这样既有了滚动的动作,也不会因为有好多item让用户等待太久
对于第三个问题:首先在当前的activity里定义一个静态的变量,用来持续追踪当前可见的第一个item,然后通过监听lv滚动事件实时修改firstposition,这里贴出代码
[java] view
plain copy
lv.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
firstposition=firstVisibleItem;
}
});
好了,到这里就大功告成了,是不是很简单,之所以写的很详细,是想让看的人理解,而不是仅仅copy我的code,理解了就是自己的,方法很重要。
首先:获取双击事件
网上有很多的获取双击事件的方法,这里我讲它稍加封装,整个工程也可以使用首先我们来定义双击事件的接口
[java] view
plain copy
package com.....activity.info;
import android.view.View;
/**
* @author wfy
* 单击双击事件接口
*/
public interface OnDoubleClickListener {
public void OnSingleClick(View v);
public void OnDoubleClick(View v);
}
下来定义一个DoubleClick类,它提供一个静态方法给一个view注册双击事件,注释我已经写的及其详细了,不再多说
[java] view
plain copy
package com.....activity.info;
import android.os.Handler;
import android.os.Message;
import android.view.View;
/**
* @author wfy
* 消息列表+好友动态的双击回到顶部
*/
public class DoubleClick {
public static void registerDoubleClickListener(View view, final OnDoubleClickListener listener){
if(listener==null) return;
view.setOnClickListener(new View.OnClickListener() {
//双击间隔时间350毫秒
private static final int DOUBLE_CLICK_TIME = 350;
private boolean flag = true;
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
listener.OnSingleClick((View)msg.obj);
}
};
//等待双击
public void onClick(final View v) {
if(flag){
flag = false;//与执行双击事件
new Thread(){
public void run() {
try {
Thread.sleep(DOUBLE_CLICK_TIME);
//此时线程沉睡 而flag被修改为false 在DOUBLE_CLICK_TIME内点击则 进入else
} catch (InterruptedException e) {
e.printStackTrace();
} //等待双击时间,否则执行单击事件
if(!flag){
//睡醒了看一看flag被人动过没,没有人动,则认作单击事件
//因此不建议用此方法执行单击事件 因为会等待睡醒,有点击延迟的存在
//没有人动,自己把它改成true,以接受下次点击
flag = true;
Message msg = handler.obtainMessage();
msg.obj = v;
//发个消息,让执行单击
handler.sendMessage(msg);
}
}
}.start();
}else{
flag = true;
listener.OnDoubleClick(v); //执行双击
}
}
});
}
}
其次:给你要双击的组件注册双击事件,此处用button演示一下
[java] viewplain copy
Button button=new Button(this);
DoubleClick.registerDoubleClickListener(button, new OnDoubleClickListener() {
@Override
public void OnSingleClick(View v) {
// TODO Auto-generated method stub
}
@Override
public void OnDoubleClick(View v) {
// TODO Auto-generated method stub
GoTopTask task=new GoTopTask();
task.execute(firstposition);
}
});
最后:细心的会发现,在上面的OnDoubleClick方法中我启动了一个异步任务,下面贴出代码,这是一个内部类
[java] viewplain copy
private class GoTopTask extends AsyncTask<Integer, Integer, String>{
@Override
protected void onPreExecute() {
//回到顶部时间置0 此处的时间不是侠义上的时间
time=0;
super.onPreExecute();
}
@Override
protected String doInBackground(Integer... params) {
// TODO Auto-generated method stub
for(int i=params[0];i>=0;i--){
publishProgress(i);
//返回顶部时间耗费15个item还没回去,则直接去顶部
//目的:要产生滚动的假象,但也不能耗时过多
time++;
if(time>15){
publishProgress(0);
return null;
}
try {
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
lv.setSelection(values[0]);
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
@Override
protected void onCancelled() {
// TODO Auto-generated method stub
super.onCancelled();
}
}
写到这里相信大家都明白思路了,就是用lv.setSelection(0)让list回到顶部,可是这里存在三个问题:1、直接闪回到顶部用户体验不是很好,很突兀 2、如1所说,那一个个往会显示,可是你有1000个item,我看到好几百个时,往回一个一个滚吗?相信没有人有那个耐心等 3、不能每次都从最后往会滚,从当前可见的第一个item滚,那么如何获取当前可见的第一个item?
对于第一个问题和第二个问题:我在异步任务里已经做了判断,先一个一个滚,滚到第十五个(也就是异步任务里的time)还没回去则直接回顶部,这样既有了滚动的动作,也不会因为有好多item让用户等待太久
对于第三个问题:首先在当前的activity里定义一个静态的变量,用来持续追踪当前可见的第一个item,然后通过监听lv滚动事件实时修改firstposition,这里贴出代码
[java] view
plain copy
lv.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
firstposition=firstVisibleItem;
}
});
好了,到这里就大功告成了,是不是很简单,之所以写的很详细,是想让看的人理解,而不是仅仅copy我的code,理解了就是自己的,方法很重要。
相关文章推荐
- Android N上一些新特性的介绍
- 欢迎使用CSDN-markdown编辑器
- Android 开发中的消息机制 Handler 机制
- Android快速开发系列 10个常用工具类
- Android应用内加载pdf的方法?
- Android里面的各种广播
- Android 开发中的消息机制 Looper基础
- Android调用相机
- Android 自定义控件——View(学习篇)
- android studio配置指南
- Android控件ListView的外面嵌套ScrollView的坑
- 图解 Android 事件分发机制
- Android自定义控件,可以滑动的导航栏(Navigation Bar)
- Android Support Library package简介
- android数据存储—SharedPreference
- Android.mk 代码注释
- Android开源SlidingMenu的使用
- Android开发模板------RecyclerView的使用
- Error inflating Edittext错误
- Android Studio 多渠道打包改名(超简单版)