Android進階篇之ListView、GridView以及ScrollView實現按鈕控制滾動
阿新 • • 發佈:2019-02-06
這次還是一樣,因為專案需要,需要對滾動檢視需要手動控制,也就是點選上下左右按鈕,能讓滾動控制元件觸發對應的操作
在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的建構函式就可以了
有什麼問題,歡迎小夥伴們參與討論!