Android进阶篇之ListView、GridView以及ScrollView实现按钮控制滚动

这次还是一样,因为项目需要,需要对滚动视图需要手动控制,也就是点击上下左右按钮,能让滚动控件触发对应的操作

在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的构造函数就可以了

有什么问题,欢迎小伙伴们参与讨论!




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值