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

来源:互联网 发布:java se深入浅出 编辑:程序博客网 时间:2024/06/05 07:17

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

在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() {@Overridepublic 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();}}}};@Overridepublic 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() {@Overridepublic void run() {mAbsListView.setOnScrollListener(new OnScrollListener() {@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {selectIndex = mAbsListView.getFirstVisiblePosition() ;refreshCtrlScrollBtn() ;}if(onScrollBtnListener != null){onScrollBtnListener.onScrollStateChanged(view, scrollState) ;}}@Overridepublic 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;}/** * 拦截触摸事件,以免触摸到地图层 */@Overridepublic boolean onTouchEvent(MotionEvent arg0) {return true;}@Overridepublic void onClick(View v) {int direct ;if (v.getId() == R.id.common_menu_scroll_up)direct = ScrollBtnConstant.UP ;elsedirect = 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就自动滚动到下一个itemisListTop = 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 0
原创粉丝点击