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
相关文章
|
6月前
|
Android开发
Android使用ViewPager做无限轮播,人为滑动时停止
Android使用ViewPager做无限轮播,人为滑动时停止
109 2
|
7月前
|
监控 Android开发 开发者
Android经典面试题之实战经验分享:如何简单实现App的前后台监听判断
本文介绍在Android中判断应用前后台状态的两种方法:`ActivityLifecycleCallbacks`和`ProcessLifecycleOwner`。前者提供精细控制,适用于需针对每个Activity处理的场景;后者简化前后台检测,适用于多数应用。两者各有优劣:`ActivityLifecycleCallbacks`更精确但复杂度高;`ProcessLifecycleOwner`更简便但可能在极端场景下略有差异。根据应用需求选择合适方法。
63 2
|
8月前
|
XML IDE 开发工具
【Android UI】自定义带按钮的标题栏
【Android UI】自定义带按钮的标题栏
77 7
【Android UI】自定义带按钮的标题栏
|
7月前
|
API Android开发
Android 监听Notification 被清除实例代码
Android 监听Notification 被清除实例代码
|
8月前
|
Android开发
技术经验分享:Android前后台切换的监听
技术经验分享:Android前后台切换的监听
153 2
|
8月前
|
API Android开发 开发者
`RecyclerView`是Android API 21引入的UI组件,用于替代ListView和GridView
【6月更文挑战第26天】`RecyclerView`是Android API 21引入的UI组件,用于替代ListView和GridView。它提供高效的数据视图复用,优化的布局管理,支持多种布局(如线性、网格),并解耦数据、适配器和视图。RecyclerView的灵活性、性能(如局部刷新和动画支持)和扩展性使其成为现代Android开发的首选,特别是在处理大规模数据集时。
100 2
|
8月前
|
安全 JavaScript 前端开发
kotlin开发安卓app,JetPack Compose框架,给webview新增一个按钮,点击刷新网页
在Kotlin中开发Android应用,使用Jetpack Compose框架时,可以通过添加一个按钮到TopAppBar来实现WebView页面的刷新功能。按钮位于右上角,点击后调用`webViewState?.reload()`来刷新网页内容。以下是代码摘要:
|
8月前
|
存储 Android开发
安卓app,MediaPlayer播放本地音频 | 按钮控制播放和停止
在Jetpack Compose中,不直接操作原生Android组件如`Button`和`MediaPlayer`,而是使用Compose UI构建器定义界面并结合ViewModel管理音频播放逻辑。以下示例展示如何播放本地音频并用按钮控制播放/停止:创建一个`AudioPlayerViewModel`管理`MediaPlayer`实例和播放状态,然后在Compose UI中使用`Button`根据`isPlaying`状态控制播放。记得在`MainActivity`设置Compose UI,并处理相关依赖和权限。
|
7月前
|
Android开发
Android仿高德首页三段式滑动
Android仿高德首页三段式滑动
189 0
|
8月前
|
编解码 Android开发
Android 解决TextView多行滑动与NestedScrollView嵌套滑动冲突的问题
Android 解决TextView多行滑动与NestedScrollView嵌套滑动冲突的问题
149 0

热门文章

最新文章

  • 1
    如何修复 Android 和 Windows 不支持视频编解码器的问题?
  • 2
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 3
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
  • 4
    【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
  • 5
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
  • 6
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 7
    Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
  • 8
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 9
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
  • 10
    Android学习自定义View(四)——继承控件(滑动时ListView的Item出现删除按钮)