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

效果图如下:



布局 

先说布局,可以用帧布局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 监听;当有一点滑动(也可以提供一个值)或者是到达底部的时候就出现回到顶部的按钮。 



有很多知识点:

  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);

/******************** 监听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://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;
}
}

}


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