这次还是一样,因为项目需要,需要对滚动视图需要手动控制,也就是点击上下左右按钮,能让滚动控件触发对应的操作
在android中,滚动View最基本的有三种,分别是:ListView、GridView和ScrollView
先看效果图:1、ListView的效果图,右下角放置滚动控制按钮
2、GridView的效果图
3、ScrollView 的效果图就不上传了,因为都差不多。
是不是看完效果图觉得弱爆了,那就对了,因为现在的功能就是实现了上下滚动,如果对上面那两个按钮加上下拉加载和上拉刷新呢?甚至还可以控制当在最顶部时只显示“下”的Button,还可以做当整个滚动视图没有超过一屏时的监听
废话不多说,现在来上代码。
第一步:
编写布局文件-->>>>文件名为common_item_menu_scorll_btns.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/common_menu_scroll_up"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/common_menu_scroll_up_selector"/>
<Button
android:id="@+id/common_menu_scroll_down"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/common_menu_scroll_down_selector"/>
</LinearLayout>
第二步:
编写自定义视图,因为ListView和GridView都是继承AbsListView,所以可以把需要控制的类型由三个变成两个
/**
* 如果需要加载更多的滚动视图就需要设置OnAddMoreDataListener
* @author yejihuang
*/
public class ScrollBtnView extends LinearLayout implements OnClickListener{
private Context mContext ;
private ScrollView scroll ;
private AbsListView mAbsListView ;
public int selectIndex ;
private boolean isListBottom ;
public boolean isListTop ;
private int type ;
private Hodler hodler ;
private OnScrollBtnListener onScrollBtnListener ;
private OnOpratorScrollBtnListener onOpratorScrollBtnListener ;
/**
* 如果不需要加载更多功能请使用ScrollBtnView(Context context, Object obj)
* 需要请使用ScrollBtnView(Context context, Object obj, OnOpratorScrollBtnListener onOpratorScrollBtnListener)
* @param context 上下文对象
* @param obj 需要被控制滚动的对象,在这里只写了三种,ScrollView,ListView,GridView
*/
public ScrollBtnView(Context context, Object obj) {
super(context);
mContext = context ;
initData() ;
initView() ;
getObject(obj) ;
}
/**
* 如果不需要加载更多功能请使用ScrollBtnView(Context context, Object obj)
* 需要请使用ScrollBtnView(Context context, Object obj, OnOpratorScrollBtnListener onOpratorScrollBtnListener)
* @param context 上下文对象
* @param obj 需要被控制滚动的对象,在这里只写了三种,ScrollView,ListView,GridView
*/
public ScrollBtnView(Context context, Object obj, OnOpratorScrollBtnListener onOpratorScrollBtnListener) {
super(context);
mContext = context ;
initData() ;
initView() ;
getObject(obj) ;
this.onOpratorScrollBtnListener = onOpratorScrollBtnListener ;
}
private void initView() {
View view = LayoutInflater.from(mContext).inflate(R.layout.common_item_menu_scorll_btns, this, true) ;
view.setVisibility(View.GONE) ;
hodler = new Hodler() ;
hodler.view = view ;
hodler.upBtn = (Button) view.findViewById(R.id.common_menu_scroll_up) ;
hodler.downBtn = (Button) view.findViewById(R.id.common_menu_scroll_down) ;
hodler.upBtn.setOnClickListener(this) ;
hodler.downBtn.setOnClickListener(this) ;
if (isListTop)
hodler.upBtn.setVisibility(View.GONE) ;
}
private void initData() {
this.selectIndex = 0 ;
isListTop = true ;
}
/**
* 根据传入的对象判断是哪一种滚动,然后强制转换
* @param obj
*/
private void getObject(Object obj) {
if (obj instanceof ScrollView) {
this.type = ScrollBtnConstant.TYPE_SCROLL ;
this.scroll = (ScrollView) obj ;
this.scroll.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()) {
//停止了,此处你的操作业务
refreshCtrlScrollBtn();
} else {
handler.sendMessageDelayed(handler.obtainMessage(touchEventId, scroller), 1);
lastY = scroller.getScrollY();
}
}
}
};
@Override
public boolean onTouch(View v, MotionEvent event) {
int eventAction = event.getAction();
int y = (int) event.getRawY();
switch (eventAction) {
case MotionEvent.ACTION_UP:
handler.sendMessageDelayed(handler.obtainMessage(touchEventId, v), 5);
break;
default:
break;
}
return false;
}
});
hodler.view.setVisibility(View.VISIBLE) ;
} else if (obj instanceof AbsListView) {
this.type = ScrollBtnConstant.TYPE_LIST ;
this.mAbsListView = (AbsListView) obj ;
MainHandler.post2Main(new Runnable() {
@Override
public void run() {
mAbsListView.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {
selectIndex = mAbsListView.getFirstVisiblePosition() ;
refreshCtrlScrollBtn() ;
}
if(onScrollBtnListener != null){
onScrollBtnListener.onScrollStateChanged(view, scrollState) ;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if(totalItemCount <= visibleItemCount){
hodler.view.setVisibility(View.GONE) ;
} else {
hodler.view.setVisibility(View.VISIBLE) ;
}
if(onScrollBtnListener != null){
onScrollBtnListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
}
}
}) ;
}
}, 1500) ;
}
}
public void setOnOpratorScrollBtnListener(
OnOpratorScrollBtnListener onOpratorScrollBtnListener) {
this.onOpratorScrollBtnListener = onOpratorScrollBtnListener;
}
/**
* 拦截触摸事件,以免触摸到地图层
*/
@Override
public boolean onTouchEvent(MotionEvent arg0) {
return true;
}
@Override
public void onClick(View v) {
int direct ;
if (v.getId() == R.id.common_menu_scroll_up)
direct = ScrollBtnConstant.UP ;
else
direct = ScrollBtnConstant.DOWN ;
//执行上下滚动事件
switch (direct) {
case ScrollBtnConstant.UP:
switch (type) {
case ScrollBtnConstant.TYPE_SCROLL:
scroll.smoothScrollBy(0, ScrollBtnConstant.DEFAULT_DISTANCE_UP) ;
break;
case ScrollBtnConstant.TYPE_LIST:
if (selectIndex > 0) {
selectIndex = mAbsListView.getFirstVisiblePosition() ;
selectIndex -- ;
}
mAbsListView.smoothScrollToPosition(selectIndex);
break;
}
break;
case ScrollBtnConstant.DOWN:
switch (type) {
case ScrollBtnConstant.TYPE_SCROLL:
scroll.smoothScrollBy(0, ScrollBtnConstant.DEFAULT_DISTANCE_DOWN) ;
break;
case ScrollBtnConstant.TYPE_LIST:
if (selectIndex < mAbsListView.getCount() - 1) {
selectIndex = mAbsListView.getLastVisiblePosition() ;
selectIndex ++ ;
isListBottom = false ;
} else {
isListBottom = true ;
}
if (!isListBottom) { // 如果是滑动到了最底部,点击向下继续滚动
mAbsListView.smoothScrollToPosition(selectIndex);
} else { //如果已经到最底部,再点击向下,就刷新数据
if (!NullUtils.isNull(onOpratorScrollBtnListener)
&& onOpratorScrollBtnListener.doLoadMore()) {
selectIndex ++ ; //一定是放在刷新之后
mAbsListView.smoothScrollToPosition(selectIndex);
}
}
break;
}
break;
default:
break;
}
refreshCtrlScrollBtn();
}
public void refreshCtrlScrollBtn() {
//执行up按钮隐藏和出现的逻辑
switch (type) {
case ScrollBtnConstant.TYPE_SCROLL:
if (scroll.getScrollY() == 0) {
isListTop = true ;
hodler.upBtn.setVisibility(View.GONE) ;
} else {
isListTop = false ;
hodler.upBtn.setVisibility(View.VISIBLE) ;
}
break;
case ScrollBtnConstant.TYPE_LIST:
int top = mAbsListView.getChildAt(0).getTop() ;
int distance = mAbsListView.getChildAt(0).getHeight() / 2 ;
if (selectIndex <= 0) {
if (top > (-1) * distance) { //对滚动距离小于item高度的一半的时候,弹回顶部,当滚动距离大于一半切没有超出下一个item就自动滚动到下一个item
isListTop = true ;
mAbsListView.setSelection(0) ;
hodler.upBtn.setVisibility(View.GONE) ;
} else {
isListTop = false ;
mAbsListView.setSelection(1) ;
hodler.upBtn.setVisibility(View.VISIBLE) ;
}
} else {
isListTop = false ;
hodler.upBtn.setVisibility(View.VISIBLE) ;
}
break;
}
}
/**
* 添加一个加载更多刷新函数的接口
* @author yejihuang
*
*/
public interface OnOpratorScrollBtnListener {
/**
* 加载更多
* @return
*/
public boolean doLoadMore () ;
}
/**
* 这个接口是把对传入的滚动控件,所触发的滚动监听分发出去
* @author yejihuang
*
*/
public interface OnScrollBtnListener {
public void onScrollStateChanged(AbsListView view, int scrollState) ;
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) ;
}
public void setOnScrollBtnListener(OnScrollBtnListener onScrollBtnListener) {
this.onScrollBtnListener = onScrollBtnListener;
}
class Hodler {
View view ;
Button upBtn ;
Button downBtn ;
}
class ScrollBtnConstant {
/**
* 默认点击一次滚动的距离
*/
public static final int DEFAULT_DISTANCE_DOWN = 200 ;
public static final int DEFAULT_DISTANCE_UP = -200 ;
public static final int DOWN = 1 ;
public static final int UP = 2 ;
public static final int TYPE_SCROLL = 1 ;
public static final int TYPE_LIST = 2 ;
}
}
代码中NullUtils.isNull()只是一个判断对象是否是NULL的静态函数,如果使用直接换成Object != null就可以了
第三步:
滚动控制的按钮视图写好了,现在就是直接添加到自己想要的地方就可以,先看看在listview布局文件中怎么添加,加一个LinearLayout布局容器来装那个滚动控制视图,
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ListView
android:id="@+id/MyListView"
android:divider="@drawable/sslist_driver"
android:dividerHeight="1dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</ListView>
<LinearLayout
android:id="@+id/scroll_btns"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true">
</LinearLayout>
</RelativeLayout>
然后在Java代码中动态添加
LinearLayout linear = (LinearLayout) findViewById(R.id.scroll_btns) ;
linear.addView(new ScrollBtnView(this, list)) ;
此处的list是指你想要控制的listview的对象
如果想控制GridView那就把list改成GridView 的实例对象就可以了,简单吧!
现在来说说当滚动到了最底部,继续点击向下就加载更多数据。
只要实现onOpratorScrollBtnListener监听器就可以了
可以从代码中看出有两种方式,多加一行setOnOpratorScrollBtnListener代码和实现带onOpratorScrollBtnListener的构造函数就可以了
有什么问题,欢迎小伙伴们参与讨论!