当前位置: 首页 > news >正文

Android ListView监听上下滑动(判断是否显示返回顶部按钮)

在有些listview上面和ScrollView上,当滑动到底部的时候,在右下角会出现一个回到顶部的按钮,提供更好的用户体验。

效果图如下:

Android listview ,ScrollView 回到顶部的按钮0


布局 

先说布局,可以用帧布局Framelayout,也可以用相对布局relativelayout.看下listview的布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white" >

    <ListView
        android:id="@+id/my_listView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp" />

    <Button
        android:id="@+id/top_btn"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:visibility="gone"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_marginBottom="6dp"
        android:layout_marginRight="6dp"
        android:background="@drawable/top_btn_bg"
        android:gravity="center"
        android:text="顶" />

</RelativeLayout>

Listview 回到顶部的活动代码 
是从网上找到的代码,作者为:zihao 
/**
 * 主界面
 * 
 * @author zihao
 * @details 因为有些手机是有虚拟按键的(在计算屏幕分辨率的时候,有些可以去除掉虚拟区域的区域->如三星,有些不行->如MX3),为了计算的准确性,
 *          各位可以设置Activity为Theme
 *          .NoTitleBar.Fullscreen填满屏幕(解决类似MX3这种在计算过程中把虚拟键盘算入屏幕高度的)。
 */
public class ListActivity extends Activity implements OnClickListener {

	private ListView listView;// List数据列表
	private Button toTopBtn;// 返回顶部的按钮
	private MyAdapter adapter;
	private boolean scrollFlag = false;// 标记是否滑动
	private int lastVisibleItemPosition = 0;// 标记上次滑动位置

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_list);

		initView();
	}

	/**
	 * 初始化视图
	 */
	private void initView() {
		listView = (ListView) findViewById(R.id.my_listView);
		toTopBtn = (Button) findViewById(R.id.top_btn);

		adapter = new MyAdapter(this, getTitleDatas());
		listView.setAdapter(adapter);

		toTopBtn.setOnClickListener(this);
		listView.setOnScrollListener(new OnScrollListener() {

			@Override
			public void onScrollStateChanged(AbsListView view, int scrollState) {
				// TODO Auto-generated method stub
				switch (scrollState) {
				// 当不滚动时
				case OnScrollListener.SCROLL_STATE_IDLE:// 是当屏幕停止滚动时
					scrollFlag = false;
					// 判断滚动到底部
					if (listView.getLastVisiblePosition() == (listView
							.getCount() - 1)) {
						toTopBtn.setVisibility(View.VISIBLE);
					}
					// 判断滚动到顶部
					if (listView.getFirstVisiblePosition() == 0) {
						toTopBtn.setVisibility(View.GONE);
					}

					break;
				case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:// 滚动时
					scrollFlag = true;
					break;
				case OnScrollListener.SCROLL_STATE_FLING:// 是当用户由于之前划动屏幕并抬起手指,屏幕产生惯性滑动时
					scrollFlag = false;
					break;
				}
			}

			/**
			 * firstVisibleItem:当前能看见的第一个列表项ID(从0开始)
			 * visibleItemCount:当前能看见的列表项个数(小半个也算) totalItemCount:列表项共数
			 */
			@Override
			public void onScroll(AbsListView view, int firstVisibleItem,
					int visibleItemCount, int totalItemCount) {
				// 当开始滑动且ListView底部的Y轴点超出屏幕最大范围时,显示或隐藏顶部按钮
				if (scrollFlag
						&& ScreenUtil.getScreenViewBottomHeight(listView) >= ScreenUtil
								.getScreenHeight(ListActivity.this)) {
					if (firstVisibleItem > lastVisibleItemPosition) {// 上滑
						toTopBtn.setVisibility(View.VISIBLE);
					} else if (firstVisibleItem < lastVisibleItemPosition) {// 下滑
						toTopBtn.setVisibility(View.GONE);
					} else {
						return;
					}
					lastVisibleItemPosition = firstVisibleItem;
				}
			}
		});
	}

	/**
	 * 获取标题数据列表
	 * 
	 * @return
	 */
	private List<String> getTitleDatas() {
		List<String> titleArray = new ArrayList<String>();
		for (int i = 0; i < 30; i++) {
			titleArray.add("这是第" + i + "个item");
		}
		return titleArray;
	}

	/**
	 * 滚动ListView到指定位置
	 * 
	 * @param pos
	 */
	private void setListViewPos(int pos) {
		if (android.os.Build.VERSION.SDK_INT >= 8) {
			listView.smoothScrollToPosition(pos);
		} else {
			listView.setSelection(pos);
		}
	}

	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		switch (v.getId()) {
		case R.id.top_btn:// 点击按钮返回到ListView的第一项
			setListViewPos(0);
			break;
		}
	}

}

在上面的代码中,对listview 设置 setOnScrollListener 监听;当有一点滑动(也可以提供一个值)或者是到达底部的时候就出现回到顶部的按钮。 

scrollview的代码 

有很多知识点:

  1. scrollview的滑动停止监听。
  2. scrollview回到顶部,或者底部的方法。
  3. scrollview到达顶部或者底部的判断方法。

上面的参考连接也都写在注释里面了。

public class ScrollViewActivity extends Activity implements OnClickListener {

	private ScrollView scrollView;// scrollView数据列表
	private Button toTopBtn;// 返回顶部的按钮


	private int scrollY = 0;// 标记上次滑动位置

	private View contentView;

	private final String TAG="test";
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_scroll);

		initView();
	}

	/**
	 * 初始化视图
	 */
	private void initView() {
		scrollView = (ScrollView) findViewById(R.id.my_scrollView);
		if (contentView == null) {
			contentView = scrollView.getChildAt(0);
		}

		toTopBtn = (Button) findViewById(R.id.top_btn);
		toTopBtn.setOnClickListener(this);

		//http://blog.csdn.net/jiangwei0910410003/article/details/17024287
		/******************** 监听ScrollView滑动停止 *****************************/
		scrollView.setOnTouchListener(new OnTouchListener() {
			private int lastY = 0;
			private int touchEventId = -9983761;
			Handler handler = new Handler() {
				@Override
				public void handleMessage(Message msg) {
					super.handleMessage(msg);
					View scroller = (View) msg.obj;
					if (msg.what == touchEventId) {
						if (lastY == scroller.getScrollY()) {
							handleStop(scroller);
						} else {
							handler.sendMessageDelayed(handler.obtainMessage(
									touchEventId, scroller), 5);
							lastY = scroller.getScrollY();
						}
					}
				}
			};

			public boolean onTouch(View v, MotionEvent event) {
				if (event.getAction() == MotionEvent.ACTION_UP) {
					handler.sendMessageDelayed(
							handler.obtainMessage(touchEventId, v), 5);
				}
				return false;
			}

			/**
			 * ScrollView 停止
			 * 
			 * @param view
			 */
			private void handleStop(Object view) {
			
			    Log.i(TAG,"handleStop");
				ScrollView scroller = (ScrollView) view;
				scrollY = scroller.getScrollY();

				doOnBorderListener();
			}
		});
		/***********************************************************/

	}

	/**
	 * ScrollView 的顶部,底部判断:
	 * http://www.trinea.cn/android/on-bottom-load-more-scrollview-impl/
	 * 
	 * 其中getChildAt表示得到ScrollView的child View, 因为ScrollView只允许一个child
	 * view,所以contentView.getMeasuredHeight()表示得到子View的高度,
	 * getScrollY()表示得到y轴的滚动距离,getHeight()为scrollView的高度。
	 * 当getScrollY()达到最大时加上scrollView的高度就的就等于它内容的高度了啊~
	 * 
	 * @param pos
	 */
	private void doOnBorderListener() {
		Log.i(TAG,ScreenUtil.getScreenViewBottomHeight(scrollView) + "  "
				+ scrollView.getScrollY()+" "+ ScreenUtil
				.getScreenHeight(ScrollViewActivity.this));
		
		
		// 底部判断
		if (contentView != null
				&& contentView.getMeasuredHeight() <= scrollView.getScrollY()
						+ scrollView.getHeight()) {
			toTopBtn.setVisibility(View.VISIBLE);
			Log.i(TAG,"bottom");
		}
		// 顶部判断
		else if (scrollView.getScrollY() == 0) {
			
			Log.i(TAG,"top");
		}

		else if (scrollView.getScrollY() > 30) {
			toTopBtn.setVisibility(View.VISIBLE);
			Log.i(TAG,"test");
		}

	}

	/**
	 * 下面我们看一下这个函数: scrollView.fullScroll(ScrollView.FOCUS_DOWN);滚动到底部
	 * scrollView.fullScroll(ScrollView.FOCUS_UP);滚动到顶部
	 * 
	 * 
	 * 需要注意的是,该方法不能直接被调用 因为Android很多函数都是基于消息队列来同步,所以需要一部操作,
	 * addView完之后,不等于马上就会显示,而是在队列中等待处理,虽然很快, 但是如果立即调用fullScroll,
	 * view可能还没有显示出来,所以会失败 应该通过handler在新线程中更新
	 * 
	 * http://blog.csdn.net/t12x3456/article/details/12799825
	 * http://www.tuicool.com/articles/zayIjq
	 */
	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		switch (v.getId()) {
			case R.id.top_btn :
				scrollView.post(new Runnable() {
					@Override
					public void run() {
						scrollView.fullScroll(ScrollView.FOCUS_UP);
					}
				});
				toTopBtn.setVisibility(View.GONE);
				break;
		}
	}

}

很多细节都注释在代码里面了,参考链接也已经加上。大家下载下代码执行一下看看。

代码http://download.csdn.net/detail/jjdhshdahhdd/9059757

相关文章:

  • django返回json的几种方法以及android调用
  • Lind.DDD.ExpressionExtensions动态构建表达式树,实现对数据集的权限控制
  • 在Visual Studio中用C++语言创建DLL动态链接库图文教程
  • 2015.12.30 日学习总结
  • 谈模块独立拆分上线一些经验
  • SpringMVC multipart文件上传
  • apache开源项目--ibatis
  • 快播活该被抓,跟公诉人是谁无关
  • 一则简单演示样例看Oracle的“无私”健壮性
  • 忘记Mysql的root密码怎么办?
  • Linux vim 命令
  • [转载]基于TFS实践敏捷-工作项跟踪
  • ODBC CRecordSet访问
  • mysql 常用函数以及常见查询语句
  • 在.Net MVC结构API接口中判断http头信息实现公共的权限验证过滤器示例
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • eclipse的离线汉化
  • hadoop集群管理系统搭建规划说明
  • JAVA_NIO系列——Channel和Buffer详解
  • Linux快速复制或删除大量小文件
  • MySQL用户中的%到底包不包括localhost?
  • scala基础语法(二)
  • 聊聊springcloud的EurekaClientAutoConfiguration
  • 如何合理的规划jvm性能调优
  • 如何实现 font-size 的响应式
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • 手机app有了短信验证码还有没必要有图片验证码?
  • 用 Swift 编写面向协议的视图
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • #中国IT界的第一本漂流日记 传递IT正能量# 【分享得“IT漂友”勋章】
  • (2022版)一套教程搞定k8s安装到实战 | RBAC
  • (39)STM32——FLASH闪存
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (二)构建dubbo分布式平台-平台功能导图
  • (附源码)计算机毕业设计ssm高校《大学语文》课程作业在线管理系统
  • (算法)Game
  • (万字长文)Spring的核心知识尽揽其中
  • (转)setTimeout 和 setInterval 的区别
  • (转)菜鸟学数据库(三)——存储过程
  • (转)总结使用Unity 3D优化游戏运行性能的经验
  • .Net core 6.0 升8.0
  • .NET Core 版本不支持的问题
  • .net 调用php,php 调用.net com组件 --
  • .net 提取注释生成API文档 帮助文档
  • .net流程开发平台的一些难点(1)
  • .NET设计模式(2):单件模式(Singleton Pattern)
  • .NET与 java通用的3DES加密解密方法
  • .NET中统一的存储过程调用方法(收藏)
  • .pop ----remove 删除
  • [ C++ ] STL---string类的模拟实现
  • [Angular] 笔记 7:模块
  • [BZOJ] 2006: [NOI2010]超级钢琴
  • [c#基础]值类型和引用类型的Equals,==的区别